| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- <template>
- <el-dialog
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :visible="visible"
- :before-close="handleClose"
- title="出票确认"
- width="80%">
- <el-form
- v-loading="submitDisable"
- element-loading-text="正在处理付款请求,请稍候"
- class="info-wrap"
- label-width="100px"
- :inline="true">
- <div style="margin-bottom: 20px;">
- 付款方式:
- <el-radio-group
- :disabled="createOrderStatus===1"
- size="medium"
- fill="#ff6934"
- v-model="currentPayChannel">
- <el-radio-button
- v-for="val in payChannelOptions"
- :key="val"
- :label="val"></el-radio-button>
- </el-radio-group>
- </div>
- <div class="btn-wrap">
- <span class="item">整单打折减免金额<Tip
- msg="输入整单减免金额后按回车。"
- style="margin-left: 0!important;"></Tip>:
- <el-input-number
- :min="0"
- :max="original_finalPrice"
- :precision="2"
- :controls="false"
- v-model.number="cutOrderMoney"
- ></el-input-number>
- </span>
- </div>
- <el-table
- border
- :data="orderInfo"
- style="margin-bottom:30px">
- <el-table-column
- prop="ticketName"
- label="票种名称">
- </el-table-column>
- <el-table-column
- label="游玩日期">
- <template slot-scope="scope">
- {{ scope.row.payDateBegin | formatDate }}
- </template>
- </el-table-column>
- <el-table-column
- prop="count"
- label="数量">
- </el-table-column>
- <!-- <el-table-column
- prop="total"
- label="小计">
- </el-table-column> -->
- </el-table>
- <el-form-item
- label="总数"
- class="warning">
- <span class="strong">
- {{ totalCount }}
- </span> 张
- </el-form-item>
- <el-form-item
- label="总金额"
- class="warning">
- <span class="strong">
- {{ orderPrice }}
- </span> 元
- </el-form-item>
- <el-form-item
- label="折扣"
- class="warning">
- <span class="strong">
- {{ discount }}
- </span> 折
- </el-form-item>
- <el-form-item
- v-if="cutOrderMoney===0"
- label="折后总额"
- class="warning">
- <span class="strong">
- {{ finalPrice }}
- </span> 元
- </el-form-item>
- <el-form-item
- v-else
- label="折后总额"
- class="warning">
- <span class="strong">
- <del>{{ original_finalPrice }}</del> {{ real_finalPrice }}
- </span> 元
- </el-form-item>
- <el-form-item
- label="检票方式"
- class="warning">
- <span class="strong">
- {{ getCheckWayName(formData?formData.checkWay:'') }}
- </span>
- </el-form-item>
- <el-form-item
- label="付款方式"
- class="warning">
- <span class="strong">
- {{ currentPayChannel }}
- </span>
- </el-form-item>
- <el-form-item
- v-if="currentPayChannel==='旅行社余额' && currentAgency"
- label="预付余额"
- class="warning">
- <span class="strong">
- {{ currentAgency.prepayment_amount }}
- </span>
- </el-form-item>
- <el-form-item
- v-if="currentPayChannel==='旅行社余额' && currentAgency"
- label="信用限额"
- class="warning">
- <span class="strong">
- {{ currentAgency.prepayment_type?currentAgency.prepayment_limit:'无限制' }}
- </span>
- </el-form-item>
- <br>
- <el-form-item
- label="备注">
- {{ formData.remark }}
- </el-form-item>
- </el-form>
- <div
- class="table-box"
- style="padding-top:0">
- <Collapse title="游客详情信息">
- <el-table
- stripe
- :data="tickets">
- <el-table-column
- type="index"
- width="50"
- >
- </el-table-column>
- <el-table-column
- prop="guestName"
- label="游客姓名"
- >
- </el-table-column>
- <el-table-column
- prop="guestPhone"
- label="游客电话"
- >
- </el-table-column>
- <el-table-column
- prop="guestIdentify"
- label="身份证"
- min-width="130"
- >
- </el-table-column>
- <el-table-column
- v-if="formData.checkWay===5"
- prop="ticketNo"
- label="票号"
- min-width="130"
- >
- </el-table-column>
- </el-table>
- </Collapse>
- </div>
- <div class="dialog-btn-wrap">
- 打印小票
- <el-switch
- style="margin:0 50px 0 10px"
- v-model="isPrintSmallTicket">
- </el-switch>
- 自动打印
- <el-switch
- style="margin:0 50px 0 10px"
- v-model="isPrint">
- </el-switch>
- <el-button @click="handleClose">
- 取消
- </el-button>
- <el-button
- type="warning"
- v-if="showRefresh"
- :disabled="isRefresh"
- @click="payRefresh">
- 刷新支付状态<span v-if="isRefresh">({{ countNum }})</span>
- </el-button>
- <el-button
- type="danger"
- v-if="scenicName==='狼山景区'||scenicName==='军山景区'"
- @click="$refs.queryPos.show()">
- 查询POS机交易
- </el-button>
- <el-button
- type="primary"
- :disabled="submitDisable"
- @click="submit()"
- >
- {{ submitDisable?'正在处理':'确认出票' }}
- </el-button>
- </div>
- <ReadValueCard
- ref="readValueCard"
- @getInfo="handleValueCardPay"
- @close="submitDisable=false"></ReadValueCard>
- <QueryPos
- ref="queryPos"
- @confirm="handleQueryPos"></QueryPos>
- <!-- GlobalComponents 全局组件 -->
- <PosQrCodeReader
- ref="posQrCodeReader"
- @getQrcode="submit"></PosQrCodeReader>
- <XSCQrCodeReader
- ref="XSCQrCodeReader"
- @getQrcode="submit"></XSCQrCodeReader>
- <ValueCardInput
- ref="ValueCardInput"
- @getMemberSystemId="submit"></ValueCardInput>
- </el-dialog>
- </template>
- <script>
- import mixin from './mixin'
- import posMixin from '@/pages/common/posMixin'
- // import confirmMixin from '../common/confirmMixin'
- import confirmMixinMingtou from '../common/confirmMixinMingtouGroup'
- import Tip from '@/components/Tip'
- export default {
- props: {
- discount: {
- type: Number,
- default: 0
- },
- // 当整单打折时,这个原有的最终价格不再是最终价格了。
- // 考虑到它本来是父组件computed算出来而且是传给本组件的props,
- // 也不能改变这个finalPrice的值。只能改变它的定义了。
- // 即,当整单打折时,它不再是真正的最终价格
- finalPrice: {
- type: Number,
- default: 0
- }
- },
- // mixins: [mixin, posMixin, confirmMixin],
- mixins: [mixin, posMixin, confirmMixinMingtou],
- computed: {
- agencyList () {
- return this.$store.state.app.agencyList
- },
- currentAgency () {
- return this.agencyList.find(i => i.id === this.formData.travelAgencyId)
- }
- },
- components: {
- Tip
- },
- data () {
- return {
- pageName: '团体售票',
- cutOrderMoney: 0, // 整单打折金额
- cutOrderMoney_work: 0, // 计算中不断变小的打折金额
- // 注意,因为cutOrderMoney被watch了,一改动它就会触发setParams
- // 为防止死循环,不断随着减price而变小的待减免金额另外用cutOrderMoney_work去存
- original_finalPrice: this.finalPrice, // 记录整单打折前的最终价格
- original_tickets: this.tickets, // 记录整单打折前的tickets,在mixin里去设初值
- // 注意,不应到mounted里去赋值,因为这个对话框只是显示和隐藏,并不会重新mount,
- // 应当到ConfirmMixinMingtouGroup.js的show方法里去赋初值
- real_finalPrice: this.finalPrice, // 真·最终价格
- // 注:这里初值不能写成this.finalPrice - this.cutOrderMoney,否则NAN
- printPlayDateBegin: ''
- }
- },
- watch: {
- cutOrderMoney (e) {
- this.cutOrderMoney_work = e // 重置待抵消减免金额
- this.resetTickets()
- console.log('整单打折减免金额:', this.cutOrderMoney)
- // finalPrice可能会变,故采用original_finalPrice减cutOrderMoney来算
- this.doOrderCut()
- }
- },
- methods: {
- resetTickets () {
- // 设置整单打折金额后再修改需要重置tickets,否则会在之前打折的基础上再打折
- this.tickets = JSON.parse(JSON.stringify(this.original_tickets))
- },
- doOrderCut () {
- // 根据cutOrderMoney去改写tickets里的price
- // 有可能finalPrice被重算,故先改tickets数组中的单价
- // 注意setParams里还用到this.orderInfo,这里面每个票种元素的tickets数组也要去改。
- console.log('整单操作前tickets:', this.tickets)
- console.log('价格们(整单操作前):' + this.tickets.map(item => item.price).join(' '))
- console.log('orderInfo:', this.orderInfo)
- // 修改setParams里面要用到的this.orderInfo票种数组内每个票种的tickets数组
- const reduceOrderInfo = (OrderInfo, cutOrderMoney) => {
- // OrderInfo是基于票种的数组,每个票种里面有tickets属性
- let result = []
- for (let ticketInfo of OrderInfo) {
- let tickets = ticketInfo.tickets
- let updatedInnerTickets = []
- for (let ticketItem of tickets) {
- if (cutOrderMoney > 0) {
- // 整单打折没减完
- if (ticketItem.price > cutOrderMoney) {
- // 该票价足够剩下的整单打折
- ticketItem.price -= cutOrderMoney
- cutOrderMoney = 0
- } else {
- cutOrderMoney -= ticketItem.price // 注意先后顺序
- ticketItem.price = 0
- }
- }
- ticketItem.discountPrice = ticketItem.price
- updatedInnerTickets.push(ticketItem)
- }
- console.log('票种价格:', tickets.map(item => item.price).join(' '))
- let updatedTicketInfo = { ...ticketInfo, tickets: updatedInnerTickets }
- result.push(updatedTicketInfo)
- }
- return result
- }
- // 修改打平后的tickets数组
- const reduceTickets = (tickets, cutOrderMoney) => {
- let result = []
- for (let ticket of tickets) {
- if (cutOrderMoney > 0) {
- // 整单打折没减完
- if (ticket.price >= cutOrderMoney) {
- // 该票价足够剩下的整单打折
- ticket.price -= cutOrderMoney
- cutOrderMoney = 0
- } else {
- cutOrderMoney -= ticket.price // 注意先后顺序
- ticket.price = 0
- }
- }
- ticket.discountPrice = ticket.price
- result.push(ticket)
- }
- return result
- }
- const tmpOrderInfo = reduceOrderInfo(this.orderInfo, this.cutOrderMoney_work) // setParams里面要用
- console.log('this.orderInfo', this.orderInfo)
- console.log('tmpOrderInfo:', tmpOrderInfo)
- this.orderInfo = tmpOrderInfo
- this.tickets = reduceTickets(this.tickets, this.cutOrderMoney_work) // 注意顺序
- console.log('整单操作后的tickets:', this.tickets)
- console.log('价格们(setParams前):' + this.tickets.map(item => item.price).join(' '))
- /**
- * 不能改变这个this.finalPrice,它是父组件OrderInfoMingtou的computed里的,
- * 而且作为props传给本组件。考虑用另外一个变量存,就是finalPrice和cutOrderMoney的差值。
- * 只有cutOrderMoney不为0时才用到,不然还用this.finalPrice。
- * 不过这样明显也改变了finalPrice的定义了,即,finalPrice它不再是真正的final。
- */
- this.real_finalPrice = this.original_finalPrice - this.cutOrderMoney
- },
- reduceTickets (tickets, cutOrderMoney) {
- let result = []
- for (let ticket of tickets) {
- if (cutOrderMoney > 0) {
- // 整单打折没减完
- if (ticket.price >= cutOrderMoney) {
- // 该票价足够剩下的整单打折
- ticket.price -= cutOrderMoney
- cutOrderMoney = 0
- } else {
- cutOrderMoney -= ticket.price // 注意先后顺序
- ticket.price = 0
- }
- }
- ticket.discountPrice = ticket.price
- result.push(ticket)
- }
- return result
- },
- setParams () {
- console.log('setParams被调用')
- // 之前是item.discountPrice为准,现在改成用item.price算
- let tickets = JSON.parse(JSON.stringify(this.tickets))
- let params = Object.assign({}, this.formData)
- // 一码多人
- if (params.checkWay - 0 === 2) {
- let allTickets = []
- // 这里的this.orderInfo来源于confirmMixinMingtouGroup.js里的 `this.orderInfo = JSON.parse(JSON.stringify(this.orderItems))`
- // 即,this.orderInfo是在show时对this.orderItems的深拷贝
- // this.orderInfo是基于票种的数组,每个票种里面再有各自的tickets
- // 而this.tickets是拍平了的
- this.orderInfo.forEach((item, index) => {
- let count = item.count
- let ticketOrderTravellers = item.tickets.map(i => {
- return {
- name: i.guestName,
- idType: i.guestIdentifyType,
- idNum: i.guestIdentify,
- mobile: i.guestPhone
- }
- })
- console.log('item.tickets:', item.tickets)
- /* 要注意item.tickets这个和this.tickets可不一样,这个item是this.orderInfo的元素 */
- console.log('setParams(item.tickets)初值:' + item.tickets.map(item => item.price).join(' '))
- console.log('setParams(this.tickets)初值:' + this.tickets.map(item => item.price).join(' '))
- let outerItem = item
- /**
- * 注意:下面的几处if代码段里重新定义了item,重新定义后的item是和tickets数组元素同类型的,其本身没有tickets属性。
- * 所以这里为了之后能访问到最初的item,需要用outerItem保存下。
- */
- // 注意,有可能出现某个票种钱被打折完了,而出现全0,若去找price为0的票就找不到了,然后obj为空,付款就在那空转
- let obj = JSON.parse(JSON.stringify(item.tickets[0]))
- obj.ticketOrderTravellers = ticketOrderTravellers
- let originItem = JSON.stringify(obj)
- if (!this.maxNum) {
- let item = JSON.parse(originItem)
- item.checkNum = count
- /**
- * 加入整单打折后,老实用加法
- * item.price = this.$NP.times(item.checkNum, item.discountPrice)
- */
- item.price = outerItem.tickets.reduce((accumulator, ticket) => this.$NP.plus(accumulator, ticket.price), 0)
- allTickets.push(item)
- return
- }
- if (count > this.maxNum) {
- let num = Math.ceil(count / this.maxNum)
- for (let i = 0; i < num - 1; i++) {
- let newItem = JSON.parse(originItem)
- newItem.checkNum = this.maxNum
- const subtotal = outerItem.tickets
- .slice(i * this.maxNum, (i + 1) * this.maxNum)
- .reduce((sum, ticket) => sum + ticket.price, 0)
- /* newItem.price = this.$NP.times(this.maxNum, newItem.discountPrice) */
- newItem.price = subtotal
- allTickets.push(newItem)
- }
- let lastItem = JSON.parse(originItem)
- // 处理最后一张票,这张最后的票没达到单票容纳人的上限
- if (count % this.maxNum === 0) {
- lastItem.checkNum = this.maxNum
- } else {
- lastItem.checkNum = count % this.maxNum
- }
- /* lastItem.price = this.$NP.times(lastItem.checkNum, lastItem.discountPrice) */
- // 由于整单打折,含票价为0的元素,不再能用乘法。
- // outerItem.tickets里面除了之前的元素,要把剩下的元素的price加起来赋给lastItem.price。
- // lastItem算价格时从之前的位置,一直切片到最后
- lastItem.price = outerItem.tickets
- .slice((num - 1) * this.maxNum, outerItem.tickets.length)
- .reduce((sum, ticket) => sum + ticket.price, 0)
- allTickets.push(lastItem)
- console.log('一码多人时的allTickets: ', allTickets)
- } else {
- /**
- * 注意,之前的item和下面重新定义的item并不相同。
- * 之前的item是有tickets属性的,而下面重新定义并覆盖了之前的item。
- * 要访问之前有tickets属性的item,需要通过outerItem来访问。
- */
- let item = JSON.parse(originItem)
- item.checkNum = count
- /* item.price = this.$NP.times(item.checkNum, item.discountPrice) */
- item.price = outerItem.tickets.reduce((accumulator, ticket) => this.$NP.plus(accumulator, ticket.price), 0)
- allTickets.push(item)
- }
- })
- params.tickets = allTickets
- } else {
- params.tickets = tickets.map(item => {
- /* item.price = item.discountPrice */
- item.price = item.price + 0 // 目前discountPrice是没有使用的
- return item
- })
- }
- params.payChannel = this.currentPayChannel
- /* params.price = this.finalPrice */
- // finalPrice不再是真正的最终价格,不过由于它是props也不好改变它,转而用变量real_finalPrice
- params.price = (this.cutOrderMoney === 0) ? this.finalPrice : this.real_finalPrice
- params.sellDevice = this.sellerDevice && this.sellerDevice.ip4
- console.log('setParams弄完之后的params:', params)
- this.params = params
- },
- createSuccessCallback () {
- // 更新旅行社余额
- this.currentPayChannel === '旅行社余额' && (this.$store.dispatch('getAgencyList'))
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .btn-wrap {
- padding-top: 20px; text-align: center;
- }
- .info-wrap {
- padding: 20px 20px;
- ::v-deep .el-form-item__label{
- font-size: 16px;
- }
- ::v-deep .el-form-item{
- display: inline-block;
- }
- .strong {
- font-size: 1.8em; font-weight: bold;
- }
- }
- </style>
- <style lang="scss" scoped>
- .btn-wrap {
- display: flex; width: 100%; margin-bottom: 10px; font-size: 14px; justify-content: space-between; align-items: center;
- .el-input {
- display: inline-block; width: 100px;
- }
- }
- </style>
|