From 62980eba69c58475f12cfc366813ca4ff2fbfd63 Mon Sep 17 00:00:00 2001 From: zzh <1368735060@qq.com> Date: Thu, 8 Oct 2026 17:30:19 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=AE=A2=E5=8D=95=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E9=80=89=E4=B8=AD=E3=80=81H5=20=E4=BD=93=E9=AA=8C=E4=B8=8E?= =?UTF-8?q?=E8=BD=A8=E8=BF=B9=E8=AE=A2=E5=8D=95=E7=B1=BB=E5=9E=8B=E5=AD=97?= =?UTF-8?q?=E5=85=B8=E5=85=9C=E5=BA=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复运单批量弹窗 v-if 打开时无数据,并优化充值页操作区、官网登录入口、H5 揽收列表与优惠券无门槛文案;订单类型字典改走 Dictionary/GetList。 Co-authored-by: Cursor --- src/api/interface-trackOrder/trackOrder.ts | 35 ++- src/components/HandsontablePro/index.vue | 165 ++++++++-- src/views/channel/salesProducts/index.vue | 163 ++++++---- src/views/channel/serviceChannels/index.vue | 6 +- .../components/H5CouponsSheet.vue | 6 +- .../components/H5PickupOrdersSheet.vue | 21 +- src/views/h5/customer-center/locale/en-US.ts | 1 + src/views/h5/customer-center/locale/zh-CN.ts | 1 + .../myOrders/components/MarkClaimedModal.vue | 24 +- .../components/MarkProblematicModal.vue | 24 +- .../components/OrderPayConfirmModal.vue | 1 + .../components/MarkClaimedModal.vue | 24 +- .../components/MarkProblematicModal.vue | 24 +- .../components/OrderPayConfirmModal.vue | 1 + .../components/ReallocateModal.vue | 29 +- src/views/site/styles/ai-advisor.css | 31 +- src/views/user/recharge/deposit.vue | 297 ++++++++++-------- 17 files changed, 565 insertions(+), 288 deletions(-) diff --git a/src/api/interface-trackOrder/trackOrder.ts b/src/api/interface-trackOrder/trackOrder.ts index 260877a..bdc38d4 100644 --- a/src/api/interface-trackOrder/trackOrder.ts +++ b/src/api/interface-trackOrder/trackOrder.ts @@ -68,14 +68,39 @@ export async function trackOrderGetOrderOperationsByIdGet( ); } -/** 获取订单类型字典 GET /Track/Order/GetOrderTypeDict */ +/** + * 获取订单类型字典。 + * 轨迹后端无 /Track/Order/GetOrderTypeDict(404),统一走 Dictionary/GetList。 + * 返回形态兼容旧调用方:`{ data: Record }`。 + */ export async function trackOrderGetOrderTypeDictGet(options?: { [key: string]: any; }) { - return request>(`trackApi/Track/Order/GetOrderTypeDict`, { - method: 'GET', - ...(options || {}), - }); + const list = await request>( + `trackApi/Dictionary/GetList`, + { + method: 'GET', + params: { + type: 'TrackOrderType', + }, + ...(options || {}), + }, + ); + + if (Array.isArray(list)) { + const dict: Record = {}; + for (const item of list) { + if (item?.key == null) continue; + dict[String(item.key)] = String(item.value ?? ''); + } + return { data: dict }; + } + + if (list && typeof list === 'object' && (list as any).data != null) { + return list as { data: Record }; + } + + return { data: (list as Record) || {} }; } /** 获取分页的轨迹订单 POST /Track/Order/GetTrackOrderList */ diff --git a/src/components/HandsontablePro/index.vue b/src/components/HandsontablePro/index.vue index 9730fcf..e9af2b3 100644 --- a/src/components/HandsontablePro/index.vue +++ b/src/components/HandsontablePro/index.vue @@ -219,6 +219,8 @@ /** 编辑写回源数据时跳过 data watch,避免打断输入 */ let ignoreDataWatch = false; + /** loadData / 程序化选区期间跳过 selection 回写,避免清空业务页已选 */ + let selectionLock = 0; /** 表头初始化/销毁期间不向业务页 emit search,避免首屏重复拉接口 */ let headerSearchEmitReady = false; let headerSearchReadyTimer: ReturnType | null = null; @@ -620,6 +622,54 @@ return props.data[rowIndex]; } + function publishSelection(rows: any[], indices: Set) { + selectedRows.value = rows; + selectedRowIndicesSet.value = indices; + emit('update:selectedRows', rows); + emit('selection-change', rows); + applySelectedRowStyles(); + } + + /** 复选框列为批量操作真相源:按 checked 汇总选中行 */ + function syncSelectionFromCheckboxes() { + if (!props.showCheckboxColumn) return; + const visualCount = + displayRowIndices.value.length > 0 ? displayRowIndices.value.length : props.data.length; + const indices = new Set(); + const rows: any[] = []; + for (let visual = 0; visual < visualCount; visual++) { + const row = rowAt(visual); + if (row && (row as any).checked) { + indices.add(visual); + rows.push(row); + } + } + publishSelection(rows, indices); + } + + function shouldKeepSelectionOnOutsideClick(event: MouseEvent): boolean { + const target = event?.target as HTMLElement | null; + if (!target) return false; + // 点工具栏/分页/下拉/弹层时保留选中,避免「选中后点立即支付已清空」 + return !!target.closest( + [ + '.table-toolbar', + '.actions-right', + '.toolbar-right', + '.toolbar-left', + '.arco-btn', + '.arco-dropdown', + '.arco-dropdown-option', + '.arco-trigger-popup', + '.arco-pagination', + '.arco-modal', + '.arco-drawer', + '.arco-select-dropdown', + '.column-config-icon-btn', + ].join(','), + ); + } + function buildRowDataArray(row: any, visualIndex: number): any[] { const rowData: any[] = []; // 固定:操作 → 序号 → 复选框 → 数据 @@ -1343,6 +1393,7 @@ if (!changes || source === 'loadData') return; const { checkboxColIndex, dataColStart } = getLayoutIndices(); ignoreDataWatch = true; + let checkboxChanged = false; try { changes.forEach(([row, col, oldValue, newValue]: any[]) => { const rowData = rowAt(row); @@ -1350,6 +1401,7 @@ if (col === checkboxColIndex) { (rowData as any).checked = newValue || false; + checkboxChanged = true; emit('checkbox-change', rowData, newValue || false, row); return; } @@ -1375,6 +1427,9 @@ oldValue, }); }); + if (checkboxChanged) { + syncSelectionFromCheckboxes(); + } } finally { // 可编辑模式:值已写入源对象且 HOT 自身已更新,禁止 loadData, // 否则会打断连续编辑 / 关掉下拉。仅在 nextTick 后恢复 data watch。 @@ -1398,6 +1453,11 @@ colHeaders: headerTexts, rowHeaders: false, selectionMode: 'multiple', + // 点工具栏/分页时保留选中,避免批量按钮拿到空选区 + outsideClickDeselects(event: MouseEvent) { + if (props.showCheckboxColumn) return false; + return !shouldKeepSelectionOnOutsideClick(event); + }, width: '100%', height: tableHeight, licenseKey: 'non-commercial-and-evaluation', @@ -1780,31 +1840,30 @@ return cellProperties; }, afterSelectionEnd: function(r: number, c: number, r2: number, c2: number) { - if (!hotInstance) return; + if (!hotInstance || selectionLock) return; - const selected = hotInstance.getSelected() || []; - const selectedRowIndices = new Set(); + // 开启复选框时,批量选中以 checked 为准,避免单元格选区覆盖 + if (props.showCheckboxColumn) { + applySelectedRowStyles(); + } else { + const selected = hotInstance.getSelected() || []; + const selectedRowIndices = new Set(); - selected.forEach(([rowStart, colStart, rowEnd, colEnd]: number[]) => { - const startRow = Math.min(rowStart, rowEnd); - const endRow = Math.max(rowStart, rowEnd); - for (let i = startRow; i <= endRow; i++) { - if (i >= 0 && i < props.data.length) { - selectedRowIndices.add(i); + selected.forEach(([rowStart, _colStart, rowEnd, _colEnd]: number[]) => { + const startRow = Math.min(rowStart, rowEnd); + const endRow = Math.max(rowStart, rowEnd); + for (let i = startRow; i <= endRow; i++) { + if (i >= 0 && i < props.data.length) { + selectedRowIndices.add(i); + } } - } - }); + }); - selectedRowIndicesSet.value = selectedRowIndices; - selectedRows.value = Array.from(selectedRowIndices) - .map(index => rowAt(index)) - .filter(Boolean); - - emit('update:selectedRows', selectedRows.value); - emit('selection-change', selectedRows.value); - - // 应用选中行样式 - applySelectedRowStyles(); + publishSelection( + Array.from(selectedRowIndices).map((index) => rowAt(index)).filter(Boolean), + selectedRowIndices, + ); + } // 可编辑模式:单击单元格即进入编辑(表单录入体验) if ( @@ -1865,7 +1924,7 @@ afterOnCellMouseDown: function(event: any, coords: any, td: any) { const { actionColIndex, serialColIndex, checkboxColIndex, dataColStart } = getLayoutIndices(); - // 复选框列 + // 复选框列(自定义 DOM,不走内置 editor) if (coords.col === checkboxColIndex) { const target = event.target; if (target.type === 'checkbox') { @@ -1873,8 +1932,16 @@ if (rowIndex >= 0 && rowIndex < props.data.length) { const row = rowAt(rowIndex); const checked = target.checked; - (row as any).checked = checked; - emit('checkbox-change', row, checked, rowIndex); + ignoreDataWatch = true; + try { + (row as any).checked = checked; + syncSelectionFromCheckboxes(); + emit('checkbox-change', row, checked, rowIndex); + } finally { + nextTick(() => { + ignoreDataWatch = false; + }); + } } } } @@ -2290,8 +2357,14 @@ } if (!props.data.length) { displayRowIndices.value = []; - hotInstance.loadData([]); - hotInstance.render(); + selectionLock += 1; + try { + hotInstance.loadData([]); + hotInstance.render(); + publishSelection([], new Set()); + } finally { + selectionLock -= 1; + } return; } @@ -2310,9 +2383,19 @@ } const data = syncDisplayRows(); - - hotInstance.loadData(data); - hotInstance.render(); + selectionLock += 1; + try { + hotInstance.loadData(data); + hotInstance.render(); + // loadData 会清掉 HOT 单元格选区;复选框模式按 checked 回写业务选中 + if (props.showCheckboxColumn) { + syncSelectionFromCheckboxes(); + } else { + applySelectedRowStyles(); + } + } finally { + selectionLock -= 1; + } // 刷新尺寸以确保 Handsontable 内置滚动视口(.wtHolder)尺寸正确 setTimeout(() => { @@ -2642,10 +2725,26 @@ refresh: updateData, getSelectedRows: () => selectedRows.value, clearSelection: () => { - if (hotInstance) { - hotInstance.deselectCell(); - selectedRows.value = []; - selectedRowIndicesSet.value = new Set(); + selectionLock += 1; + try { + if (hotInstance) { + hotInstance.deselectCell(); + } + if (props.showCheckboxColumn) { + ignoreDataWatch = true; + try { + props.data.forEach((row) => { + if (row) (row as any).checked = false; + }); + } finally { + nextTick(() => { + ignoreDataWatch = false; + }); + } + } + publishSelection([], new Set()); + } finally { + selectionLock -= 1; } }, }); diff --git a/src/views/channel/salesProducts/index.vue b/src/views/channel/salesProducts/index.vue index 0547ff8..54418e8 100644 --- a/src/views/channel/salesProducts/index.vue +++ b/src/views/channel/salesProducts/index.vue @@ -1152,6 +1152,16 @@ const id = Number(key.slice(5)); const product = filteredProductList.value.find((p: any) => p.id === id); if (!product) return; + // 已选中且卖价已加载:忽略重复 select(树/受控 selectedKeys 偶发连发) + if ( + selectedProduct.value === id + && activeTab.value === 'price' + && priceTabLoadedProductId === id + && !configFormDirty.value + && !rulesFormDirty.value + ) { + return; + } const ok = await confirmDiscardUnsavedChanges(); if (!ok) return; await handleSelectProduct(product); @@ -1180,65 +1190,80 @@ let priceTabLoadSeq = 0; /** 当前 priceTableData 所属产品;切走再回来时直接复用,不再空表重拉 */ let priceTabLoadedProductId: number | null = null; - /** 已做过发布态对比的列表签名,避免每次切 tab 都解析整份卖价快照 */ - let pricePublishCheckedSig = ''; + /** 同产品进行中的列表请求复用,避免树 select 连发打两次 price/list */ + let priceTabInflight: { productId: number; promise: Promise } | null = null; const priceListLoading = ref(false); - async function loadPriceTabData(productId: number) { + async function loadPriceTabData(productId: number, opts?: { force?: boolean }) { + if (priceTabInflight?.productId === productId) { + await priceTabInflight.promise; + return; + } + // 已加载过该产品(含空列表)且非强制刷新:跳过,避免重复 price/list + if (!opts?.force && priceTabLoadedProductId === productId) { + return; + } + const seq = ++priceTabLoadSeq; const showSpinner = priceTabLoadedProductId !== productId || priceTableData.value.length === 0; if (showSpinner) priceListLoading.value = true; - try { - // 列表不拉 details,也不等发布记录。生效版本在列表渲染后单独补。 - const prices = await getSalesProductPriceList(productId, { includeDetails: false }); - // 快速切换产品时丢弃过期响应 - if (seq !== priceTabLoadSeq || selectedProduct.value !== productId) return; - // 映射前确保字典就绪,计费因素列显示中文名而非 code - if (!salesPriceDictFetched.value) { - await ensureSalesPriceDictLoaded(); + + const run = (async () => { + try { + // 列表不拉 details,也不等发布记录。生效版本在列表渲染后单独补。 + const prices = await getSalesProductPriceList(productId, { includeDetails: false }); + // 快速切换产品时丢弃过期响应 if (seq !== priceTabLoadSeq || selectedProduct.value !== productId) return; - } - // factors 仍可能较多:markRaw 禁止 Vue 深度代理 - const rows = (prices || []).map((it: any) => { - const factors = Array.isArray(it.factors) ? it.factors : []; - const audit = pickResolvedAudit(it); - return { - id: it.id, - serialNumber: it.serialNumber, - status: isEnableStatusEnabled(it.status ?? it.Status), - priceName: it.priceName, - costItem: it.costItem, - costUnit: it.costUnit, - currency: it.currency, - chargingCondition: it.chargingCondition || '', - billingFactors: factors - .map((f: any) => pricingFactorColumnLabel(String(f?.factor ?? f?.name ?? ''))) - .filter(Boolean) - .join('+'), - factors: markRaw(factors), - details: null as any[] | null, - modifyTime: audit.updateTime, - modifier: audit.updateBy, - }; - }); - priceTableData.value = rows; - priceTabLoadedProductId = productId; - void refreshSalesProductPriceEffectiveInfo(productId); - // 发布同步态必须每次刷新:不能跟价格行 modifyTime 签名绑死,否则刚发布后签名不变会跳过刷新、徽章一直「待发布」 - void refreshPricePublishSyncStatus(productId).then(() => { - if (seq === priceTabLoadSeq && selectedProduct.value === productId) { - pricePublishCheckedSig = `${productId}|${rows - .map((r) => `${r.id}:${r.modifyTime}:${r.status ? 1 : 0}`) - .join(',')}`; + // 映射前确保字典就绪,计费因素列显示中文名而非 code + if (!salesPriceDictFetched.value) { + await ensureSalesPriceDictLoaded(); + if (seq !== priceTabLoadSeq || selectedProduct.value !== productId) return; } - }); - } catch (e) { - if (seq !== priceTabLoadSeq) return; - console.error(e); - effectiveVersion.value = '--'; - effectiveTime.value = '--'; + // factors 仍可能较多:markRaw 禁止 Vue 深度代理 + const rows = (prices || []).map((it: any) => { + const factors = Array.isArray(it.factors) ? it.factors : []; + const audit = pickResolvedAudit(it); + return { + id: it.id, + serialNumber: it.serialNumber, + status: isEnableStatusEnabled(it.status ?? it.Status), + priceName: it.priceName, + costItem: it.costItem, + costUnit: it.costUnit, + currency: it.currency, + chargingCondition: it.chargingCondition || '', + billingFactors: factors + .map((f: any) => pricingFactorColumnLabel(String(f?.factor ?? f?.name ?? ''))) + .filter(Boolean) + .join('+'), + factors: markRaw(factors), + details: null as any[] | null, + modifyTime: audit.updateTime, + modifier: audit.updateBy, + }; + }); + priceTableData.value = rows; + priceTabLoadedProductId = productId; + void refreshSalesProductPriceEffectiveInfo(productId); + // 徽章只听后端 sync-status,不在前端算差异 + void refreshPricePublishSyncStatus(productId); + } catch (e) { + if (seq !== priceTabLoadSeq) return; + console.error(e); + effectiveVersion.value = '--'; + effectiveTime.value = '--'; + } finally { + if (seq === priceTabLoadSeq) priceListLoading.value = false; + } + })(); + + priceTabInflight = { productId, promise: run }; + try { + await run; } finally { - if (seq === priceTabLoadSeq) priceListLoading.value = false; + if (priceTabInflight?.productId === productId && priceTabInflight.promise === run) { + priceTabInflight = null; + } } } @@ -1404,9 +1429,10 @@ return detail?.content ?? detail?.Content ?? null; } + /** 仅展示后端 sync-status.pending,前端不做快照 diff */ async function refreshPricePublishSyncStatus(productId?: number) { const pid = productId ?? selectedProduct.value; - if (pid == null || !priceTableData.value.length) { + if (pid == null) { pricePublishChecking.value = false; pricePublishPending.value = null; return; @@ -1419,7 +1445,8 @@ operatorType: 'price', }); if (seq !== priceTabLoadSeq || selectedProduct.value !== pid) return; - pricePublishPending.value = !!(status?.pending ?? status?.Pending); + const pending = status?.pending ?? status?.Pending; + pricePublishPending.value = typeof pending === 'boolean' ? pending : null; } catch { if (seq === priceTabLoadSeq) pricePublishPending.value = null; } finally { @@ -1561,6 +1588,20 @@ const handleSelectProduct = async (product: any) => { const productChanged = selectedProduct.value !== product.id; + // 同产品重复选中且当前 tab 数据已在:不再打 detail / price/list + if ( + !productChanged + && product?.id + && ( + (activeTab.value === 'price' && priceTabLoadedProductId === product.id) + || (activeTab.value === 'rules' && rulesTabLoadedProductId === product.id) + || (activeTab.value === 'records' && recordsTabLoadedProductId === product.id) + || activeTab.value === 'config' + || activeTab.value === 'customerGuide' + ) + ) { + return; + } selectedProduct.value = product.id; configPublishPending.value = false; rulesPublishPending.value = false; @@ -1569,12 +1610,12 @@ if (productChanged && activeTab.value !== 'price') { priceTableData.value = []; priceTabLoadedProductId = null; - pricePublishCheckedSig = ''; pricePublishPending.value = null; pricePublishChecking.value = false; effectiveVersion.value = '--'; effectiveTime.value = '--'; } else if (activeTab.value === 'price') { + // 切到卖价 tab / 换产品:先清空徽章,等 sync-status 回来再显示 pricePublishPending.value = null; pricePublishChecking.value = false; } @@ -2272,9 +2313,9 @@ publishModalMethods.closeModal(); await loadRecordsTabData(pid, true); if (operatorType === 'price') { - pricePublishCheckedSig = ''; - pricePublishPending.value = false; - await loadPriceTabData(pid); + // 不乐观改徽章;等后端 sync-status 重算 + pricePublishPending.value = null; + await loadPriceTabData(pid, { force: true }); await refreshPricePublishSyncStatus(pid); } } catch (e: any) { @@ -3576,7 +3617,7 @@ }; } else { // 兼容后端不返回 id:用唯一组合定位刚新增记录,切成编辑态避免下次重复 create - await loadPriceTabData(pid); + await loadPriceTabData(pid, { force: true }); const latest = [...priceTableData.value] .reverse() .find((row: any) => row.serialNumber === payload.serialNumber && row.costItem === payload.costItem); @@ -3606,7 +3647,7 @@ try { const msg = await submitPriceConfig(pid); Message.success(msg); - await loadPriceTabData(pid); + await loadPriceTabData(pid, { force: true }); priceModalVisible.value = false; } catch (e: any) { Message.error(e?.message || '保存失败'); @@ -4169,7 +4210,7 @@ deletePriceModalVisible.value = false; deletingPriceRecord.value = null; deletePriceInput.value = ''; - if (productId != null) await loadPriceTabData(productId); + if (productId != null) await loadPriceTabData(productId, { force: true }); } catch (e: any) { Message.error(e?.message || '删除失败'); } @@ -4188,7 +4229,7 @@ if (pid == null || record?.id == null) return try { await toggleSalesProductPriceStatus(record.id, toEnableStatus(!!record.status)) - await loadPriceTabData(pid) + await loadPriceTabData(pid, { force: true }) } catch (e: any) { record.status = !record.status Message.error(e?.message || '更新失败') diff --git a/src/views/channel/serviceChannels/index.vue b/src/views/channel/serviceChannels/index.vue index fa1a2b3..1420450 100644 --- a/src/views/channel/serviceChannels/index.vue +++ b/src/views/channel/serviceChannels/index.vue @@ -4106,9 +4106,10 @@ const publishDiffStatus = computed(() => { return 'changed' }) +/** 仅展示后端 sync-status.pending,前端不做快照 diff */ async function refreshPricePublishSyncStatus(serviceChannelId?: number | string) { const cid = serviceChannelId ?? (selectedChannel.value as any)?.id - if (cid == null || !priceTableData.value.length) { + if (cid == null) { pricePublishChecking.value = false pricePublishPending.value = null return @@ -4119,7 +4120,8 @@ async function refreshPricePublishSyncStatus(serviceChannelId?: number | string) serviceChannelId: cid, operatorType: 'price', }) - pricePublishPending.value = !!(status?.pending ?? status?.Pending) + const pending = status?.pending ?? status?.Pending + pricePublishPending.value = typeof pending === 'boolean' ? pending : null } catch { pricePublishPending.value = null } finally { diff --git a/src/views/h5/customer-center/components/H5CouponsSheet.vue b/src/views/h5/customer-center/components/H5CouponsSheet.vue index 1bd8f8f..57f31bd 100644 --- a/src/views/h5/customer-center/components/H5CouponsSheet.vue +++ b/src/views/h5/customer-center/components/H5CouponsSheet.vue @@ -83,7 +83,11 @@

- {{ t('h5.coupons.minOrder', { amount: formatAmount(item.minOrderAmount) }) }} + {{ + Number(item.minOrderAmount) > 0 + ? t('h5.coupons.minOrder', { amount: formatAmount(item.minOrderAmount) }) + : t('h5.coupons.noThreshold') + }}

diff --git a/src/views/h5/customer-center/components/H5PickupOrdersSheet.vue b/src/views/h5/customer-center/components/H5PickupOrdersSheet.vue index c7a988d..578dc0f 100644 --- a/src/views/h5/customer-center/components/H5PickupOrdersSheet.vue +++ b/src/views/h5/customer-center/components/H5PickupOrdersSheet.vue @@ -453,6 +453,7 @@ defineExpose({ openWithDetail, reload: load }) } .h5-pklist__handle { + flex-shrink: 0; width: 36px; height: 4px; margin: 10px auto 0; @@ -461,6 +462,7 @@ defineExpose({ openWithDetail, reload: load }) } .h5-pklist__head { + flex-shrink: 0; display: flex; align-items: flex-start; justify-content: space-between; @@ -496,10 +498,14 @@ defineExpose({ openWithDetail, reload: load }) } .h5-pklist__filters { + flex-shrink: 0; + z-index: 2; display: flex; + align-items: center; gap: 8px; overflow-x: auto; - padding: 12px 16px; + padding: 12px 16px 10px; + background: #f5f6f8; -webkit-overflow-scrolling: touch; &::-webkit-scrollbar { @@ -526,10 +532,17 @@ defineExpose({ openWithDetail, reload: load }) } .h5-pklist__body { - flex: 1; - min-height: 220px; + flex: 1 1 auto; + min-height: 0; + width: 100%; + display: block; overflow: auto; - padding: 0 16px 16px; + padding: 4px 16px 16px; + -webkit-overflow-scrolling: touch; + + :deep(.arco-spin-children) { + min-height: 160px; + } } .h5-pklist-card { diff --git a/src/views/h5/customer-center/locale/en-US.ts b/src/views/h5/customer-center/locale/en-US.ts index 698cdac..bd9b4ef 100644 --- a/src/views/h5/customer-center/locale/en-US.ts +++ b/src/views/h5/customer-center/locale/en-US.ts @@ -837,6 +837,7 @@ export default { 'h5.coupons.tab.used': 'Used', 'h5.coupons.tab.expired': 'Expired', 'h5.coupons.minOrder': 'Min order {amount}', + 'h5.coupons.noThreshold': 'No minimum', 'h5.coupons.use': 'Use now', 'h5.coupons.discountUnit': ' off', 'h5.coupons.expiringSoon': 'Expiring soon', diff --git a/src/views/h5/customer-center/locale/zh-CN.ts b/src/views/h5/customer-center/locale/zh-CN.ts index b4c2ef4..f713dba 100644 --- a/src/views/h5/customer-center/locale/zh-CN.ts +++ b/src/views/h5/customer-center/locale/zh-CN.ts @@ -820,6 +820,7 @@ export default { 'h5.coupons.unnamed': '优惠券', 'h5.coupons.use': '去使用', 'h5.coupons.minOrder': '满{amount}可用', + 'h5.coupons.noThreshold': '无门槛', 'h5.coupons.discountUnit': '折', 'h5.coupons.expiringSoon': '即将过期', 'h5.coupons.badge.newcomer': '新人', diff --git a/src/views/order/myOrders/components/MarkClaimedModal.vue b/src/views/order/myOrders/components/MarkClaimedModal.vue index 9082384..752e1e2 100644 --- a/src/views/order/myOrders/components/MarkClaimedModal.vue +++ b/src/views/order/myOrders/components/MarkClaimedModal.vue @@ -207,23 +207,27 @@ function onClaimTypeChange(key: string) { formRef.value?.setValues?.({ ...formState, claimType: key }) } +const modalTitle = computed(() => + t('order.myOrders.claimed.modalTitle', { count: props.orderIds.length }), +) + watch( () => props.visible, async (open) => { if (!open) return resetForm() - modalMethods.setModalProps({ - title: t('order.myOrders.claimed.modalTitle', { count: props.orderIds.length }), - width: 720, - maskClosable: false, - }) - modalMethods.openModal(true) await nextTick() formRef.value?.setValues?.({ ...formState }) formRef.value?.formRef?.clearValidate?.() }, + { immediate: true }, ) +function onUpdateVisible(val: boolean) { + if (val === props.visible) return + emit('update:visible', val) +} + async function submitBatchJob(payload: Record) { const job = await postOrderBatchJob({ action: 'mark-claimed', @@ -314,14 +318,18 @@ async function handleSubmit() { function handleCancel() { emit('update:visible', false) - modalMethods.closeModal() }