|
|
@@ -73,6 +73,13 @@
|
|
|
@click="handleConfirm">
|
|
|
确认出票
|
|
|
</el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ class="danger-btn item"
|
|
|
+ v-if="payChannel === '现金' && currentTicket"
|
|
|
+ @click="showBatchDialog">
|
|
|
+ 批量出票
|
|
|
+ </el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -206,6 +213,69 @@
|
|
|
:tourist-list="touristList"
|
|
|
:update-tourist="updateTourist"
|
|
|
ref="touristList"></TouristList>
|
|
|
+
|
|
|
+ <!-- 批量出票弹框 -->
|
|
|
+ <el-dialog
|
|
|
+ title="批量出票"
|
|
|
+ :visible.sync="batchDialogVisible"
|
|
|
+ width="500px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @close="batchDialogVisible = false">
|
|
|
+ <div v-loading="batchLoading" element-loading-text="正在批量出票中...">
|
|
|
+ <el-alert
|
|
|
+ title="批量出票过程中不要操作!!!"
|
|
|
+ type="error"
|
|
|
+ :closable="false"
|
|
|
+ show-icon>
|
|
|
+ </el-alert>
|
|
|
+
|
|
|
+ <el-form label-width="140px" style="margin-top: 20px;">
|
|
|
+ <el-form-item label="出票模式">
|
|
|
+ <el-radio-group v-model="batchMode">
|
|
|
+ <el-radio value="single" label="single">一码一人</el-radio>
|
|
|
+ <el-radio value="multi" label="multi">一码多人</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="每张票人数">
|
|
|
+ <el-input-number
|
|
|
+ v-model="batchPeoplePerTicket"
|
|
|
+ :min="1"
|
|
|
+ :max="50"
|
|
|
+ :disabled="batchMode === 'single'"
|
|
|
+ style="width: 200px">
|
|
|
+ </el-input-number>
|
|
|
+ <span style="margin-left: 10px; color: #909399;">人</span>
|
|
|
+ <el-tag v-if="batchMode === 'single'" type="info" style="margin-left: 10px;">一码一人固定为1</el-tag>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="订单数量">
|
|
|
+ <el-input-number
|
|
|
+ v-model="batchOrderCount"
|
|
|
+ :min="1"
|
|
|
+ :max="500"
|
|
|
+ style="width: 200px">
|
|
|
+ </el-input-number>
|
|
|
+ <span style="margin-left: 10px; color: #909399;">个订单</span>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item v-if="batchLoading" label="出票进度">
|
|
|
+ <el-progress :percentage="Math.round(batchProgress / batchTotal * 100)" :status="batchProgress === batchTotal ? 'success' : undefined"></el-progress>
|
|
|
+ <span style="margin-left: 10px;">{{ batchProgress }} / {{ batchTotal }}</span>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <span slot="footer">
|
|
|
+ <el-button @click="batchDialogVisible = false" :disabled="batchLoading">取消</el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ :loading="batchLoading"
|
|
|
+ @click="batchCreateOrderLoop">
|
|
|
+ {{ batchLoading ? '出票中...' : '开始批量出票' }}
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ </el-dialog>
|
|
|
</el-card>
|
|
|
</template>
|
|
|
|
|
|
@@ -216,6 +286,7 @@ import Confirm from './Confirm'
|
|
|
import PrintSmallTicketCheckbox from '../common/PrintSmallTicketCheckbox'
|
|
|
import UploadImgList from '../common/uploadImgList'
|
|
|
import orderItemMixin from '../common/orderItemMixin'
|
|
|
+import { createOrder, getSingleOrder } from '@/api/order'
|
|
|
|
|
|
/** 封装一个公共方法numCalc() 用于浮点数运算 */
|
|
|
// num1 num2传入两个值 symbol +-*/符号
|
|
|
@@ -320,6 +391,14 @@ export default {
|
|
|
autoPrintSmallTicket: this.$localStore.get('autoPrintSmallTicket'),
|
|
|
showDiscountDialog: false,
|
|
|
currentItem: null,
|
|
|
+ // 批量出票
|
|
|
+ batchDialogVisible: false,
|
|
|
+ batchMode: 'single', // 'single' 一码一人, 'multi' 一码多人
|
|
|
+ batchPeoplePerTicket: 1,
|
|
|
+ batchOrderCount: 1,
|
|
|
+ batchLoading: false,
|
|
|
+ batchProgress: 0,
|
|
|
+ batchTotal: 0,
|
|
|
discountInfo: {
|
|
|
ticketPrice: 0,
|
|
|
discountPrice: 0,
|
|
|
@@ -408,6 +487,166 @@ export default {
|
|
|
const payment = this.$localStore.get('defaultPayWay') || this.payChannelOptions[0]
|
|
|
|
|
|
this.payChannel = this.payChannelOptions.indexOf(payment) < 0 ? this.payChannelOptions[0] : payment
|
|
|
+ },
|
|
|
+ // 显示批量出票对话框
|
|
|
+ showBatchDialog () {
|
|
|
+ this.formData = this.$parent.$refs.formInfo.form
|
|
|
+ this.batchDialogVisible = true
|
|
|
+ this.batchMode = 'single'
|
|
|
+ this.batchPeoplePerTicket = 1
|
|
|
+ this.batchOrderCount = 1
|
|
|
+ this.batchProgress = 0
|
|
|
+ this.batchTotal = 0
|
|
|
+ },
|
|
|
+ // 构建批量出票参数
|
|
|
+ buildBatchParams () {
|
|
|
+ const params = JSON.parse(JSON.stringify(this.formData))
|
|
|
+ const moment = require('moment')
|
|
|
+
|
|
|
+ params.playDateBegin = moment(this.formData.playDateBegin).format('YYYY-MM-DD')
|
|
|
+ params.playDateEnd = moment(this.formData.playDateEnd).format('YYYY-MM-DD')
|
|
|
+
|
|
|
+ // 从currentTicket构建票务,不使用全局tickets
|
|
|
+ const tickets = []
|
|
|
+ const singlePrice = this.currentTicket.price
|
|
|
+ const playDateBegin = params.playDateBegin
|
|
|
+ const playDateEnd = params.playDateEnd
|
|
|
+
|
|
|
+ if (this.batchMode === 'single') {
|
|
|
+ // 一码一人:每张票一个人
|
|
|
+ for (let i = 0; i < this.batchPeoplePerTicket; i++) {
|
|
|
+ tickets.push({
|
|
|
+ ticketTypeId: this.currentTicket.id,
|
|
|
+ price: singlePrice,
|
|
|
+ originalPrice: singlePrice,
|
|
|
+ checkNum: 1,
|
|
|
+ playDateBegin,
|
|
|
+ playDateEnd,
|
|
|
+ isDiscount: this.currentTicket.isDiscount || 0,
|
|
|
+ batchConfigId: params.batchConfigId || '',
|
|
|
+ guestName: '',
|
|
|
+ guestPhone: '',
|
|
|
+ guestIdentify: '',
|
|
|
+ guestIdentifyType: 0,
|
|
|
+ face: null,
|
|
|
+ ticketNo: '',
|
|
|
+ isStorage: 0,
|
|
|
+ discountPrice: 0,
|
|
|
+ discountDescription: ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ params.price = this.$NP.times(singlePrice, this.batchPeoplePerTicket)
|
|
|
+ } else {
|
|
|
+ // 一码多人:一张票对应N人
|
|
|
+ tickets.push({
|
|
|
+ ticketTypeId: this.currentTicket.id,
|
|
|
+ price: this.$NP.times(singlePrice, this.batchPeoplePerTicket),
|
|
|
+ originalPrice: singlePrice,
|
|
|
+ checkNum: this.batchPeoplePerTicket,
|
|
|
+ playDateBegin,
|
|
|
+ playDateEnd,
|
|
|
+ isDiscount: this.currentTicket.isDiscount || 0,
|
|
|
+ batchConfigId: params.batchConfigId || '',
|
|
|
+ guestName: '',
|
|
|
+ guestPhone: '',
|
|
|
+ guestIdentify: '',
|
|
|
+ guestIdentifyType: 0,
|
|
|
+ face: null,
|
|
|
+ ticketNo: '',
|
|
|
+ isStorage: 0,
|
|
|
+ discountPrice: 0,
|
|
|
+ discountDescription: '',
|
|
|
+ ticketOrderTravellers: [{
|
|
|
+ name: '',
|
|
|
+ idType: 0,
|
|
|
+ idNum: '',
|
|
|
+ mobile: ''
|
|
|
+ }]
|
|
|
+ })
|
|
|
+ params.price = this.$NP.times(singlePrice, this.batchPeoplePerTicket)
|
|
|
+ }
|
|
|
+
|
|
|
+ params.tickets = tickets
|
|
|
+ params.payChannel = '现金'
|
|
|
+ params.sellDevice = (this.$parent.$refs.formInfo.sellerDevice && this.$parent.$refs.formInfo.sellerDevice.ip4) || ''
|
|
|
+ params.createOrderRemark = this.createOrderRemark
|
|
|
+
|
|
|
+ // 处理ticketNo和face
|
|
|
+ params.tickets.forEach(ticket => {
|
|
|
+ if (params.checkWay !== 5) {
|
|
|
+ ticket.ticketNo = ''
|
|
|
+ ticket.isStorage = 0
|
|
|
+ } else {
|
|
|
+ ticket.isStorage = 1
|
|
|
+ }
|
|
|
+ ticket.face = {
|
|
|
+ faceImg: ticket.face
|
|
|
+ }
|
|
|
+ ticket.batchConfigId = params.batchConfigId || ticket.batchConfigId || ''
|
|
|
+ })
|
|
|
+
|
|
|
+ return params
|
|
|
+ },
|
|
|
+ // 校验批量出票输入
|
|
|
+ validateBatchInput () {
|
|
|
+ if (!this.currentTicket) {
|
|
|
+ this.$message.error('请先选择票种')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!this.batchPeoplePerTicket || this.batchPeoplePerTicket < 1) {
|
|
|
+ this.$message.error('请输入正确的每张票人数')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (this.batchMode === 'multi' && this.batchPeoplePerTicket > 50) {
|
|
|
+ this.$message.error('一码多人模式下每张票人数不能超过50')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!this.batchOrderCount || this.batchOrderCount < 1) {
|
|
|
+ this.$message.error('请输入正确的订单数量')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ // 批量出票循环
|
|
|
+ async batchCreateOrderLoop () {
|
|
|
+ if (!this.validateBatchInput()) return
|
|
|
+
|
|
|
+ const baseParams = this.buildBatchParams()
|
|
|
+ this.batchLoading = true
|
|
|
+ this.batchTotal = this.batchOrderCount
|
|
|
+ this.batchProgress = 0
|
|
|
+
|
|
|
+ for (let i = 0; i < this.batchOrderCount; i++) {
|
|
|
+ try {
|
|
|
+ const freshParams = JSON.parse(JSON.stringify(baseParams))
|
|
|
+ const res = await createOrder(freshParams)
|
|
|
+ this.batchProgress = i + 1
|
|
|
+
|
|
|
+ // 每个订单成功后调用打印
|
|
|
+ const order = res.data?.order
|
|
|
+ if (order?.id) {
|
|
|
+ getSingleOrder(order.id).then(res2 => {
|
|
|
+ this.autoPrintSmallTicket && this.$printSmallTicket(order)
|
|
|
+ const order2 = res2.data
|
|
|
+ this.autoPrint && this.$print(order2)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 少量延时,避免并发问题
|
|
|
+ if (i < this.batchOrderCount - 1) {
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 300))
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('批量出票失败', e)
|
|
|
+ this.$message.error(`第${i + 1}次出票失败: ${e.message || e.msg || '未知错误'}`)
|
|
|
+ // 继续下一张
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.batchLoading = false
|
|
|
+ this.$message.success(`批量出票完成,成功出票 ${this.batchProgress} 次`)
|
|
|
+ this.batchDialogVisible = false
|
|
|
+ this.$emit('clear')
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
@@ -424,7 +663,9 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
mounted () {
|
|
|
- this.payChannel = this.$localStore.get('defaultPayWay') || this.$localStore.get('retailPayment') || this.payChannelOptions[0]
|
|
|
+ const payment = this.$localStore.get('defaultPayWay') || this.$localStore.get('retailPayment') || this.payChannelOptions[0]
|
|
|
+
|
|
|
+ this.payChannel = this.payChannelOptions.indexOf(payment) < 0 ? this.payChannelOptions[0] : payment
|
|
|
}
|
|
|
}
|
|
|
</script>
|