From 72c1684f30f72b098d21838a5cab6e6b905a6d19 Mon Sep 17 00:00:00 2001 From: chenghuan Date: Fri, 3 Jul 2026 13:36:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=AE=A2=E5=8D=95=E6=A8=A1=E5=9D=97):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=B9=E9=87=8F=E5=8F=91=E5=87=BA=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=8F=8A=E8=BF=9B=E5=BA=A6=E5=AF=B9=E8=AF=9D=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增筛选单本书的复选框选项 - 添加批量发出按钮,支持多选订单发出 - 实现批量发出进度对话框,显示处理状态和失败明细 - 优化订单数据处理逻辑,提升用户体验 --- src/views/modules/order/buyorder.vue | 619 +++++++++++++++++- .../shop/commonMedicineTags/shopproduct.vue | 7 +- 2 files changed, 608 insertions(+), 18 deletions(-) diff --git a/src/views/modules/order/buyorder.vue b/src/views/modules/order/buyorder.vue index 5cd34c0..9d61c25 100644 --- a/src/views/modules/order/buyorder.vue +++ b/src/views/modules/order/buyorder.vue @@ -86,19 +86,44 @@ + +
+ 筛选单本书 + +
+
+ 查询
- +
合并发出 - + 批量发出 +
+ 全选 +
+
批量打印 @@ -589,6 +614,111 @@ 关 闭 + +
+
+
+
+
+ + + +
+
+
{{ batchDeliverStatusTitle }}
+
{{ batchDeliverStatusDesc }}
+
+
+
+ +
+
+ + +
+ +
+
+
+
+
{{ batchDeliverProgress.totalCount }}
+
订单总数
+
+
+
+
+
+
{{ batchDeliverProgress.processedCount }}
+
已处理
+
+
+
+
+
+
{{ batchDeliverProgress.successCount }}
+
成功
+
+
+
+
+
+
{{ batchDeliverProgress.failCount }}
+
失败
+
+
+
+
+ +
+ + {{ batchDeliverProgress.failMessage }} +
+ +
+ + 后台正在处理发货任务,请勿关闭页面 +
+ +
+
+ 失败明细 + 共 {{ batchDeliverProgress.failedItems.length }} 条 +
+ + + + +
+
+ + + {{ batchDeliverProgress.finished ? '完成' : '处理中...' }} + + +
@@ -646,20 +776,35 @@ dataForm: { key: '', time: '', - productName: '' + productName: '', + filterPresale: false, + showOne: false }, PrintSheetList: [], //打印列表 sheetListLoading: false, selectedPrintList: [], // 选中的面单列表 mergeList: [], // 检查订单可合并项数组 checkboxGroup: { - isIndeterminate: true, + isIndeterminate: false, checkAll: false }, multipleDisabled: false, // 待发出多选是否可用 //childrenChecked:[], checkedOrders: [], // 新的筛选 fullscreenLoading: false, + batchDeliverLoading: false, + batchDeliverProgressVisible: false, + batchDeliverPollTimer: null, + batchDeliverProgress: { + taskId: null, + totalCount: 0, + successCount: 0, + failCount: 0, + processedCount: 0, + finished: false, + failMessage: null, + failedItems: [] + }, deliverDetailVisible: false, splitDeliverVisible: false, mergeDliverVisible: false, @@ -824,8 +969,37 @@ return n > 0 ? n : 0 } return paidNum + }, + batchDeliverPercent() { + const { processedCount, totalCount } = this.batchDeliverProgress + if (!totalCount) return 0 + return Math.min(100, Math.round((processedCount / totalCount) * 100)) + }, + batchDeliverStatusType() { + if (!this.batchDeliverProgress.finished) return 'processing' + if (this.batchDeliverProgress.failCount > 0) return 'warning' + return 'success' + }, + batchDeliverStatusTitle() { + if (!this.batchDeliverProgress.finished) return '正在批量发出' + if (this.batchDeliverProgress.failCount > 0) return '发出完成(部分失败)' + return '全部发出成功' + }, + batchDeliverStatusDesc() { + if (!this.batchDeliverProgress.finished) { + return `已完成 ${this.batchDeliverProgress.processedCount} / ${this.batchDeliverProgress.totalCount} 单` + } + return `成功 ${this.batchDeliverProgress.successCount} 单,失败 ${this.batchDeliverProgress.failCount} 单` + }, + batchDeliverProgressColor() { + if (!this.batchDeliverProgress.finished) return '#409EFF' + if (this.batchDeliverProgress.failCount > 0) return '#E6A23C' + return '#67C23A' } }, + beforeDestroy() { + this.stopBatchDeliverPolling() + }, methods: { computedVipType(userVips) { if (!userVips || userVips.length === 0) return ''; @@ -1073,15 +1247,27 @@ }); }, - // 全选/全不选 + // 获取可勾选的待发出订单 id + getSelectableOrderIds() { + return this.dataList + .filter(item => item.isSend != 1) + .map(item => item.orderId) + }, + // 同步全选复选框状态 + syncCheckAllState() { + const selectableIds = this.getSelectableOrderIds() + const checkedCount = this.checkedOrders.length + this.checkboxGroup.checkAll = checkedCount > 0 && checkedCount === selectableIds.length + this.checkboxGroup.isIndeterminate = checkedCount > 0 && checkedCount < selectableIds.length + }, + // 全选/取消全选 handleCheckAllChange(val) { - // console.log(this.selectOptions)------------ - let newidList = this.dataList.map(item => item.orderId); - this.checkedOrders = newidList - this.checkboxGroup.isIndeterminate = !this.checkboxGroup.isIndeterminate; - if (this.checkboxGroup.isIndeterminate) { + if (val) { + this.checkedOrders = this.getSelectableOrderIds() + } else { this.checkedOrders = [] } + this.checkboxGroup.isIndeterminate = false }, // 添加-更新-订单备注 editBeizhu(val) { @@ -1121,6 +1307,7 @@ "pageIndex": this.pageIndex, "pageSize": this.pageSize, "filterPresale": this.dataForm.filterPresale?1:0, + "showOne": this.dataForm.showOne ? 1 : 0, "orderType": this.orderType }) }).then(({data}) => { @@ -1130,6 +1317,9 @@ this.totalPage = data.result.total if (this.tabChange.tabActiveName === '1') { // 判断可选按钮是否可用 this.isMultipleDisabled() + this.checkedOrders = [] + this.checkboxGroup.checkAll = false + this.checkboxGroup.isIndeterminate = false } //如果是名医精彩 出现导出按钮 if(this.orderType=='mingyijingcai'){ @@ -1507,13 +1697,120 @@ this.setDeliverVisible = false this.getDataList() this.checkedOrders = [] - this.isIndeterminate = true + this.checkboxGroup.checkAll = false + this.checkboxGroup.isIndeterminate = false }, // 关闭面单预览 closeSheetDliverDialog(val) { this.sheetVisible = val }, // 批量发出 + batchDeliver() { + if (!this.checkedOrders.length) { + this.$message.warning('请先勾选要发出的订单') + return + } + this.$confirm(`共选中了${this.checkedOrders.length}条订单,是否批量发出?`, '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + this.batchDeliverLoading = true + this.$http({ + url: this.$http.adornUrl('/book/buyOrder/batchDelivery'), + method: 'post', + data: this.checkedOrders, + timeout: 0 + }).then(({ data }) => { + if (data && data.code === 0) { + if (data.taskId) { + this.checkedOrders = [] + this.checkboxGroup.checkAll = false + this.checkboxGroup.isIndeterminate = false + this.openBatchDeliverProgress(data) + } else { + this.$message.success('批量发出成功') + this.checkedOrders = [] + this.checkboxGroup.checkAll = false + this.checkboxGroup.isIndeterminate = false + this.getDataList() + } + } else if (data) { + if (data.msg === '订单列表不能为空') { + this.$message.error('订单列表不能为空') + } else { + this.$message.error(`以下订单不符合发出条件:${data.msg}`) + } + } + }).catch(() => { + this.$message.error('批量发出失败,请稍后重试') + }).finally(() => { + this.batchDeliverLoading = false + }) + }).catch(() => {}) + }, + openBatchDeliverProgress(submitData) { + this.batchDeliverProgress = { + taskId: submitData.taskId, + totalCount: submitData.totalCount || 0, + successCount: 0, + failCount: 0, + processedCount: 0, + finished: false, + failMessage: null, + failedItems: [] + } + this.batchDeliverProgressVisible = true + this.pollBatchDeliveryProgress() + this.batchDeliverPollTimer = setInterval(() => { + this.pollBatchDeliveryProgress() + }, 1000) + }, + pollBatchDeliveryProgress() { + if (!this.batchDeliverProgress.taskId) return + this.$http({ + url: this.$http.adornUrl('/book/buyOrder/getBatchDeliveryProgress'), + method: 'get', + params: this.$http.adornParams({ + taskId: this.batchDeliverProgress.taskId + }) + }).then(({ data }) => { + if (data && data.code === 0) { + this.batchDeliverProgress = { + ...this.batchDeliverProgress, + totalCount: data.totalCount, + successCount: data.successCount, + failCount: data.failCount, + processedCount: data.processedCount, + finished: data.finished, + failMessage: data.failMessage, + failedItems: data.failedItems || [] + } + if (data.finished) { + this.stopBatchDeliverPolling() + this.getDataList() + if (data.failCount > 0) { + this.$message.warning(`批量发出完成,成功 ${data.successCount} 条,失败 ${data.failCount} 条`) + } else { + this.$message.success('批量发出完成') + } + } + } + }).catch(() => {}) + }, + stopBatchDeliverPolling() { + if (this.batchDeliverPollTimer) { + clearInterval(this.batchDeliverPollTimer) + this.batchDeliverPollTimer = null + } + }, + closeBatchDeliverProgressDialog() { + this.batchDeliverProgressVisible = false + this.stopBatchDeliverPolling() + }, + handleBatchDeliverProgressClose() { + this.stopBatchDeliverPolling() + }, setDeliver() { this.setDeliverVisible = true }, @@ -1590,8 +1887,8 @@ this.setDeliverVisible = true }, handleCheckedChange(val) { - console.log(val) this.checkedOrders = val + this.syncCheckAllState() }, //名医精彩-导出 handleExport(){ @@ -1646,7 +1943,8 @@ watch: { tabChange: { handler(val, oldVal) { - this.dataForm.filterPresale=false + this.dataForm.filterPresale = false + this.dataForm.showOne = false //console.log(val) this.getDataList() if (this.tabChange.tabActiveName === '' || this.tabChange.tabActiveName === '0' || this.tabChange @@ -1679,6 +1977,28 @@ text-align: left; border-bottom: 1px solid #f1f1f1; } + + .batch-deliver-progress-dialog { + border-radius: 12px; + overflow: hidden; + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12); + } + + .batch-deliver-progress-dialog .el-dialog__header { + display: none; + padding: 0; + border-bottom: none; + } + + .batch-deliver-progress-dialog .el-dialog__body { + padding: 0; + } + + .batch-deliver-progress-dialog .el-dialog__footer { + padding: 16px 24px 24px; + border-top: 1px solid #f0f2f5; + text-align: center; + } diff --git a/src/views/modules/shop/commonMedicineTags/shopproduct.vue b/src/views/modules/shop/commonMedicineTags/shopproduct.vue index e705e03..3ca6992 100644 --- a/src/views/modules/shop/commonMedicineTags/shopproduct.vue +++ b/src/views/modules/shop/commonMedicineTags/shopproduct.vue @@ -387,7 +387,7 @@ this.$emit('delete',[row]) this.$forceUpdate(); }, getRowKeys(row) { - return row.productId; + return row.id; }, handleSelectionChange(val) { console.log("🚀 ~ handleSelectionChange ~ val:", val); @@ -447,9 +447,6 @@ this.$emit('delete',[row]) }, // 获取关联数据列表 async getAssociatedGoodsList() { - console.log("🚀 ~ getAssociatedGoodsList ~ form:", form); - // :currentId="addForm.id" - // currentType="bookLabelId" var form = { ...this.dataForm }; if (this.currentType == "bookLabelId") { @@ -476,10 +473,10 @@ this.$emit('delete',[row]) }), }).then(async ({ data }) => { if (data && data.code === 0) { + this.dataListLoading = false; var list = [...data.result.records]; // this.associatedGoodsList = [...data.result.records]; - this.dataListLoading = false; list.forEach((item) => { item.isEdit = false })