From 31ed31da92077e43552d46695501f7fb41c35b66 Mon Sep 17 00:00:00 2001 From: xiaojibeier Date: Wed, 8 Jul 2026 16:47:32 +0800 Subject: [PATCH] 20260708001 --- src/api/customer.js | 28 ++- src/api/customerPrice.js | 26 ++- src/api/pricingTable.js | 19 +- src/api/supplyCoordCollection.js | 20 +- src/api/supplySupplier.js | 25 +- .../global-tab/GlobalTabCostPanel.vue | 213 +++++++++++++++++- src/config/buildId.json | 4 +- src/data/appChangelog.js | 54 ++++- src/utils/whRdcDeployCandidatesTree.js | 6 +- src/views/base/WhRdcDeployLinkDialog.vue | 28 +-- src/views/base/WhSceneLinkGoodsDlg.vue | 46 +++- src/views/base/WhSrfRdcDeployPane.vue | 16 +- src/views/base/WhSrfRdcPane.vue | 4 +- src/views/base/WhSrfRdcRightPane.vue | 2 +- src/views/dealer/DealerPriceBook.vue | 127 +---------- src/views/supply/SupplierList.vue | 41 +++- .../supply/SupplyCoordCollectionManage.vue | 2 +- src/views/supply/SupplySupplierFormDlg.vue | 72 ++++-- 18 files changed, 530 insertions(+), 203 deletions(-) diff --git a/src/api/customer.js b/src/api/customer.js index 0ab3a8a..d19b80c 100644 --- a/src/api/customer.js +++ b/src/api/customer.js @@ -17,9 +17,24 @@ import { pickSupplierBlocCode, pickSupplierCompanyCode, pickSupplierDisplayName, + pickSupplierSpecialDeliveryCommissionRate, + formatSupplierSpecialDeliveryCommissionRate, resolveOrgEffectiveSceneCodes, } from '@/api/supplySupplier' +function buildCustomerSpecialDeliveryFields(formOrRow) { + const rate = pickSupplierSpecialDeliveryCommissionRate(formOrRow) + return { + special_delivery_commission_rate: rate ?? 0, + } +} + +function buildCustomerSpecialDeliveryFieldsFromRow(row) { + return { + special_delivery_commission_rate: pickSupplierSpecialDeliveryCommissionRate(row) ?? 0, + } +} + /** @param {unknown} res */ function unwrapResponseData(res) { if (res == null) return res @@ -99,15 +114,22 @@ export function buildCustomerAddPayload(form, { blocCode }) { return { ...buildSupplierAddPayload(form, { blocCode }), company_type: 3, + ...buildCustomerSpecialDeliveryFields(form), } } export function buildCustomerModifyPayload(form, companyCode, opts = {}) { - return buildSupplierModifyPayload(form, companyCode, opts) + return { + ...buildSupplierModifyPayload(form, companyCode, opts), + ...buildCustomerSpecialDeliveryFields(form), + } } export function buildCustomerModifyPayloadFromRow(row, opts = {}) { - return buildSupplierModifyPayloadFromRow(row, opts) + return { + ...buildSupplierModifyPayloadFromRow(row, opts), + ...buildCustomerSpecialDeliveryFieldsFromRow(row), + } } export async function fetchCustomerGroupTreeListed() { @@ -132,5 +154,7 @@ export { pickSupplierCompanyCode as pickCustomerCompanyCode, pickSupplierDisplayName as pickCustomerDisplayName, resolveOrgEffectiveSceneCodes, + pickSupplierSpecialDeliveryCommissionRate, + formatSupplierSpecialDeliveryCommissionRate, buildSupplierFormFields as buildCustomerFormFields, } diff --git a/src/api/customerPrice.js b/src/api/customerPrice.js index 5ab255f..2e691aa 100644 --- a/src/api/customerPrice.js +++ b/src/api/customerPrice.js @@ -524,6 +524,30 @@ export function serializeBenefitBuckets(buckets) { return out } +/** add 接口:excess_performance / benefit 须为 JSONArray;无票种分组时传 [] */ +export function serializeExcessPerformanceForAdd(buckets) { + const src = buckets && typeof buckets === 'object' ? buckets : {} + const namedKeys = Object.keys(src).filter((k) => String(k).trim() !== '') + if (!namedKeys.length) return [] + return serializeExcessPerformanceBucketsAsCustomArray(src) +} + +/** add 接口:benefit 同 excess_performance,无分组时传 [] */ +export function serializeBenefitForAdd(buckets) { + const src = buckets && typeof buckets === 'object' ? buckets : {} + const namedKeys = Object.keys(src).filter((k) => String(k).trim() !== '') + if (!namedKeys.length) return [] + return serializeBenefitBucketsAsCustomArray(src) +} + +/** 表单 → 新增请求体(超额绩效/好处费为数组) */ +export function buildCustomerPriceAddBody(form, extras = {}) { + const body = buildCustomerPriceWriteBody(form, extras) + body.excess_performance = serializeExcessPerformanceForAdd(form?.excess_performance_buckets) + body.benefit = serializeBenefitForAdd(form?.benefit_buckets) + return body +} + /** 表单 → 新增/修改请求体 */ export function buildCustomerPriceWriteBody(form, extras = {}) { const excess_performance = serializeExcessPerformanceBuckets(form?.excess_performance_buckets) @@ -586,7 +610,7 @@ export function buildCustomerPriceAddItem(company_code, goods_code, overrides = const cc = String(company_code ?? '').trim() const gc = String(goods_code ?? '').trim() const o = overrides && typeof overrides === 'object' ? overrides : {} - return buildCustomerPriceWriteBody( + return buildCustomerPriceAddBody( { excess_performance_buckets: groupsToPerformanceBuckets([]), benefit_buckets: groupsToBenefitBuckets([]), diff --git a/src/api/pricingTable.js b/src/api/pricingTable.js index 3f6f500..1e1fb96 100644 --- a/src/api/pricingTable.js +++ b/src/api/pricingTable.js @@ -88,16 +88,16 @@ export function normalizePricingTableRow(raw, idx = 0) { const internal_bill_type = pickText(raw, 'internal_bill_name', 'internal_bill_type') const internal_input_tax_rate = pickRate(raw, 'internal_bill_tax', 'internal_input_tax_rate') const source_rdc_name = pickText(raw, 'rdc_warehouse_name', 'source_rdc_name') - const source_rdc_code = pickText(raw, 'rdc_warehouse_code', 'source_rdc') + const source_rdc_code = pickText(raw, 'rdc_warehouse_code', 'source_rdc_code', 'source_rdc') const fence_value = pickMoney(raw, 'fence_price', 'fence_value') - const bloc = pickText(raw, 'supplier_bloc_code') - const company = pickText(raw, 'supplier_company_code') + const supplier_company_code = pickText(raw, 'supplier_company_code', 'company_code') return { - key: pickText(raw, 'key', 'id') ?? `${bloc || 'bloc'}-${company || idx}`, + key: pickText(raw, 'key', 'id') ?? `${bloc || 'bloc'}-${supplier_company_code || idx}`, supplier_bloc_name, supplier_company_name, + supplier_company_code, goods_name, bill_type, input_tax_rate, @@ -107,6 +107,7 @@ export function normalizePricingTableRow(raw, idx = 0) { internal_input_tax_rate, source_rdc: source_rdc_name || source_rdc_code, source_rdc_name, + source_rdc_code, fence_value, } } @@ -150,16 +151,16 @@ function unwrapPricingCalculatePayload(res) { return envelope } -/** 算价响应 → debug 文本(供弹窗展示) */ +/** 算价响应 → 明细文本(供弹窗展示) */ export function formatPricingCalculateDebug(res) { const payload = unwrapPricingCalculatePayload(res) const debug = payload?.debug ?? res?.data?.debug ?? res?.debug if (debug == null || debug === '') { const fallback = payload && typeof payload === 'object' ? payload : (res?.data ?? res) try { - return `(接口未返回 debug)\n\n${JSON.stringify(fallback, null, 2)}` + return `(接口未返回计算明细)\n\n${JSON.stringify(fallback, null, 2)}` } catch { - return '(接口未返回 debug)' + return '(接口未返回计算明细)' } } if (typeof debug === 'string') return debug @@ -193,8 +194,12 @@ export async function pricingCalculate(body = {}) { } const supply_collection_code = str(body.supply_collection_code) const customer_price_code = str(body.customer_price_code) + const supplier_company_code = str(body.supplier_company_code) + const warehouse_code = str(body.warehouse_code) if (supply_collection_code) payload.supply_collection_code = supply_collection_code if (customer_price_code) payload.customer_price_code = customer_price_code + if (supplier_company_code) payload.supplier_company_code = supplier_company_code + if (warehouse_code) payload.warehouse_code = warehouse_code return request.post('/api/pricing/calculate', payload) } diff --git a/src/api/supplyCoordCollection.js b/src/api/supplyCoordCollection.js index e118507..427d1d9 100755 --- a/src/api/supplyCoordCollection.js +++ b/src/api/supplyCoordCollection.js @@ -677,17 +677,17 @@ export function pickCollectionTargetDelayedRebateMonths(row) { } /** - * 列表/编辑回填:帐期月数(接口仍用 payment_days,后端新增 payment_months 时再兼容读取) + * 列表/编辑回填:帐期月数(接口字段 payment_months;兼容旧 payment_days) * @param {object} [row] */ export function pickCollectionPaymentMonths(row) { const r = row && typeof row === 'object' ? row : {} const v = - r.payment_days + r.payment_months + ?? r.payment_month + ?? r.payment_days ?? r.payment_period_days ?? r.paymentDays - ?? r.payment_months - ?? r.payment_month if (v === null || v === undefined || v === '') return '' return String(v) } @@ -711,6 +711,14 @@ export function resolveOrgContactPerson(raw) { return { code: '', label: nameLabel || contactRaw } } +function resolveCollectionPaymentMonthsValue(p) { + const src = p && typeof p === 'object' ? p : {} + const v = src.payment_months ?? src.payment_days + if (v === null || v === undefined || v === '') return 0 + const n = Number(v) + return Number.isFinite(n) ? n : 0 +} + /** * POST /api/supply/collection/add 请求体(与三步向导快照对齐) * @param {object} parts @@ -751,7 +759,7 @@ export function buildSupplyCollectionAddBody(parts) { owner_code: String(p.owner_code || '').trim(), scenes, warehouses, - payment_days: p.payment_days ?? 60, + payment_months: resolveCollectionPaymentMonthsValue(p), is_support_acceptance: p.is_support_acceptance === true || acceptanceRaw === '支持', is_support_receipt: p.is_support_receipt === true, @@ -805,7 +813,7 @@ export function buildCoordCollectionSaveBody(parts) { supplier_org_type: String(p.supplier_org_type || '').trim(), partner_org_type: String(p.partner_org_type || '').trim(), warehouse_codes: Array.isArray(p.warehouse_codes) ? [...p.warehouse_codes] : [], - payment_days: p.payment_days, + payment_months: resolveCollectionPaymentMonthsValue(p), acceptance_payment: String(p.acceptance_payment || '').trim(), rebate_delay_base_months: p.rebate_delay_base_months diff --git a/src/api/supplySupplier.js b/src/api/supplySupplier.js index 7d03ebd..3c2e3f0 100755 --- a/src/api/supplySupplier.js +++ b/src/api/supplySupplier.js @@ -439,6 +439,27 @@ export function formatSupplierOutputVatRateLabel(row) { return '—' } +/** listed 行解析专项送货计提率 */ +export function pickSupplierSpecialDeliveryCommissionRate(row) { + if (!row || typeof row !== 'object') return null + const r = /** @type {Record} */ (row) + const field = r.field && typeof r.field === 'object' ? r.field : null + const fields = r.fields && typeof r.fields === 'object' ? r.fields : null + const raw = r.special_delivery_commission_rate + ?? field?.special_delivery_commission_rate + ?? fields?.special_delivery_commission_rate + if (raw === null || raw === undefined || raw === '') return null + const n = Number(raw) + return Number.isFinite(n) ? n : null +} + +/** 详情展示:专项送货计提率 */ +export function formatSupplierSpecialDeliveryCommissionRate(row) { + const n = pickSupplierSpecialDeliveryCommissionRate(row) + if (n == null) return '—' + return `${n}%` +} + /** listed 行解析 sale_type(1 渠道 / 2 零售) */ export function pickSupplierSaleType(row) { if (!row || typeof row !== 'object') return ORG_SALE_TYPE_CHANNEL @@ -458,6 +479,7 @@ export function buildSupplierFormStateFromRow(row) { output_vat_rate_key: '', is_support_receipt: false, sale_type: ORG_SALE_TYPE_CHANNEL, + special_delivery_commission_rate: null, credit_code: '', legal_person: '', contact_person: '', @@ -469,7 +491,7 @@ export function buildSupplierFormStateFromRow(row) { if (!row || typeof row !== 'object') return { ...base } const next = { ...base } for (const key of Object.keys(base)) { - if (key === 'output_vat_rate_key' || key === 'is_support_receipt' || key === 'org_type' || key === 'sale_type') continue + if (key === 'output_vat_rate_key' || key === 'is_support_receipt' || key === 'org_type' || key === 'sale_type' || key === 'special_delivery_commission_rate') continue if (row[key] !== undefined && row[key] !== null) next[key] = row[key] } const tax = hydrateSupplierOrgTaxFields(row) @@ -479,6 +501,7 @@ export function buildSupplierFormStateFromRow(row) { is_support_receipt: tax.is_support_receipt, output_vat_rate_key: tax.output_vat_rate_key, sale_type: pickSupplierSaleType(row), + special_delivery_commission_rate: pickSupplierSpecialDeliveryCommissionRate(row), } } diff --git a/src/components/global-tab/GlobalTabCostPanel.vue b/src/components/global-tab/GlobalTabCostPanel.vue index 1a9ecfb..2abdd09 100644 --- a/src/components/global-tab/GlobalTabCostPanel.vue +++ b/src/components/global-tab/GlobalTabCostPanel.vue @@ -106,7 +106,22 @@
{{ row.source_rdc_name || row.source_rdc || '—' }}
-
{{ fmtMoney(row.fence_value) }}
+
+ + + + + {{ fmtMoney(row.fence_value) }} + + {{ fmtMoney(row.fence_value) }} +
@@ -115,17 +130,49 @@ + + + +
+
{{ calculateDebugText }}
+
+ +
+
+ + diff --git a/src/config/buildId.json b/src/config/buildId.json index 1ade934..51a8c24 100755 --- a/src/config/buildId.json +++ b/src/config/buildId.json @@ -1,4 +1,4 @@ { - "buildId": "20260707009", - "generatedAt": "2026-07-07T14:48:25.301Z" + "buildId": "20260708004", + "generatedAt": "2026-07-08T08:40:29.095Z" } \ No newline at end of file diff --git a/src/data/appChangelog.js b/src/data/appChangelog.js index 6150a4b..124c49d 100755 --- a/src/data/appChangelog.js +++ b/src/data/appChangelog.js @@ -42,11 +42,61 @@ * @typedef {{ date: string, items: ChangelogItem[] }} ChangelogDay */ -/** 应用版本(如 0.7.032 → 侧栏 v0.7,弹窗 v0.7.032) */ -export const APP_VERSION = '0.7.032' +/** 应用版本(如 0.7.035 → 侧栏 v0.7,弹窗 v0.7.035) */ +export const APP_VERSION = '0.7.39' /** @type {ChangelogDay[]} */ export const APP_CHANGELOG = [ + { + date: '2026-07-08', + items: [ + { + icon: 'mdi:format-list-bulleted', + kind: 'add', + text: '「物料列表 → 成本围栏」围栏值前增加可点击「?」,对接 `POST /api/pricing/calculate` 查看算价明细(传 `supplier_company_code`、`warehouse_code` 及当前纳税身份/商品);弹窗宽 1200px、仅内容区滚动,`Teleport` 挂 body 避免嵌套物料弹窗生命周期警告。', + }, + { + icon: 'mdi:notebook-outline', + kind: 'change', + text: '「客户管理 → 客户价格本」移除顶栏「批量计算」按钮及相关算价弹窗逻辑。', + }, + { + icon: 'mdi:storefront-outline', + kind: 'add', + text: '「客户管理 → 客户列表」组织新建/编辑对接 `special_delivery_commission_rate`(客户专项送货计提率),仅走 `/api/customer/add`、`/api/customer/modify`;供货目录供应商接口不带该字段。', + }, + { + icon: 'mdi:truck-delivery-outline', + kind: 'change', + text: '「供应商列表」「客户列表」组织详情与新建/编辑弹窗:基本信息拆为「工商信息」「其他信息」;销售类型单独置于「其他信息」;客户另增专项送货计提率,输入框与详情展示带 % 单位。', + }, + { + icon: 'mdi:storefront-outline', + kind: 'fix', + text: '「客户列表」组织详情「工商信息」卡片(信用代码、法人、组织类型)因 computed 漏写 return 未渲染,已修复。', + }, + { + icon: 'mdi:warehouse', + kind: 'change', + text: '「仓库管理 → RDC 物料」可调配仓相关文案统一为「源采购仓」:Tab、批量关联按钮、关联弹窗标题/说明/候选区、确认保存提示及列表空态等用户可见文案同步更名。', + }, + { + icon: 'mdi:warehouse', + kind: 'change', + text: '「仓库管理 → 关联物料」弹窗:全部/已关联/未关联 Tab 移入物料顶栏,缩小字号并固定高度,与「物料 · N 条」垂直对齐,避免单行过扁。', + }, + { + icon: 'mdi:notebook-outline', + kind: 'fix', + text: '「客户管理 → 客户价格本」通过场景/分类添加或手动新增时,`/api/customer/price/add` / `batch_add` 的 `excess_performance`、`benefit` 无票种分组时改传空数组 `[]`,不再提交 `{ rate, amount }` 对象,修复后端 JSONArray 类型转换报错。', + }, + { + icon: 'mdi:folder-cog-outline', + kind: 'change', + text: '「统筹集合管理」新建/编辑第三步「财务成本损益」:接口字段 `payment_days` 更名为 `payment_months`(帐期月数);add/modify 提交与列表回填优先读新字段,兼容旧 `payment_days`。', + }, + ], + }, { date: '2026-07-07', items: [ diff --git a/src/utils/whRdcDeployCandidatesTree.js b/src/utils/whRdcDeployCandidatesTree.js index 260a38f..7251367 100755 --- a/src/utils/whRdcDeployCandidatesTree.js +++ b/src/utils/whRdcDeployCandidatesTree.js @@ -278,7 +278,7 @@ export function validateDeployPairings(anchorRows, anchorToDeployMap, deployTree continue } if (!pick.key || !pickToWarehouseCode(pick)) { - return { ok: false, message: '可调配仓勾选数据不完整', unmappedCount: unmappedRows.length + 1 } + return { ok: false, message: '源采购仓勾选数据不完整', unmappedCount: unmappedRows.length + 1 } } mappedCount += 1 rowsToSave.push(row) @@ -290,14 +290,14 @@ export function validateDeployPairings(anchorRows, anchorToDeployMap, deployTree if (pendingRequired.length) { return { ok: false, - message: `还有 ${pendingRequired.length} 条物料有可调配仓尚未勾选,请先完成关联后再确定`, + message: `还有 ${pendingRequired.length} 条物料有源采购仓尚未勾选,请先完成关联后再确定`, unmappedCount: pendingRequired.length, mappedCount, } } if (mappedCount === 0) { - return { ok: false, message: '没有可保存的可调配仓关联', unmappedCount: unmappedRows.length } + return { ok: false, message: '没有可保存的源采购仓关联', unmappedCount: unmappedRows.length } } return { diff --git a/src/views/base/WhRdcDeployLinkDialog.vue b/src/views/base/WhRdcDeployLinkDialog.vue index d7c92a0..580cb40 100755 --- a/src/views/base/WhRdcDeployLinkDialog.vue +++ b/src/views/base/WhRdcDeployLinkDialog.vue @@ -9,7 +9,7 @@ class="wh-rdc-deploy-link-dlg wh-fs-scope" @closed="onClosed" > - + +
+
其他信息
+
+
+
+ +
+
+
{{ card.label }}
+
{{ card.value }}
+
{{ card.sub }}
+
+
+
+
@@ -724,6 +745,7 @@ import { pickSupplierSaleType, pickPartnerOrgDisplayName, pickSupplierDisplayName, + formatSupplierSpecialDeliveryCommissionRate, supplySupplierBlocRemove, supplySupplierBlocSceneListed, supplySupplierBlocSceneSet, @@ -1035,7 +1057,7 @@ const mainInfoCards = computed(() => { const businessInfoCards = computed(() => { const row = activeRow.value - return [ + const cards = [ { key: 'credit_code', icon: 'mdi:card-account-details-outline', @@ -1057,6 +1079,13 @@ const businessInfoCards = computed(() => { value: displayText(pickSupplierOrgType(row)), tone: 'indigo', }, + ] + return cards +}) + +const otherInfoCards = computed(() => { + const row = activeRow.value + const cards = [ { key: 'sales_type', icon: 'mdi:tag-outline', @@ -1065,6 +1094,16 @@ const businessInfoCards = computed(() => { tone: 'violet', }, ] + if (isCustomer.value) { + cards.push({ + key: 'special_delivery_commission_rate', + icon: 'mdi:percent-outline', + label: '客户专项送货计提率', + value: formatSupplierSpecialDeliveryCommissionRate(row), + tone: 'amber', + }) + } + return cards }) function infoCardGridStyle(card) { diff --git a/src/views/supply/SupplyCoordCollectionManage.vue b/src/views/supply/SupplyCoordCollectionManage.vue index 6136a57..a55d716 100755 --- a/src/views/supply/SupplyCoordCollectionManage.vue +++ b/src/views/supply/SupplyCoordCollectionManage.vue @@ -2604,7 +2604,7 @@ function buildStep3Payload() { const baseDelayed = parseWizardInt(form.baseDelayedRebateMonths, { allowZero: true }) const targetDelayed = parseWizardInt(form.targetDelayedRebateMonths, { allowZero: true }) return { - payment_days: parseWizardInt(form.paymentMonths), + payment_months: parseWizardInt(form.paymentMonths), acceptance_payment: form.acceptancePayment, rebate_delay_base_months: baseDelayed, rebate_delay_target_months: targetDelayed, diff --git a/src/views/supply/SupplySupplierFormDlg.vue b/src/views/supply/SupplySupplierFormDlg.vue index e02523f..25ab213 100755 --- a/src/views/supply/SupplySupplierFormDlg.vue +++ b/src/views/supply/SupplySupplierFormDlg.vue @@ -41,23 +41,10 @@ /> - - - - - +
工商信息
@@ -75,6 +62,37 @@ +
其他信息
+
+ + + + + + +
+ + % +
+
+
@@ -312,6 +330,32 @@ async function submit() { .supply-supplier-form--org .supply-supplier-form-pair-grid .el-form-item { margin-bottom: 18px; } +.supply-supplier-form-section-title { + margin: 4px 0 2px; + padding-top: 2px; + font-size: calc(13px + var(--wh-fs-delta, 0px)); + font-weight: 600; + color: #606266; + line-height: 1.4; +} +.supply-supplier-rate-field { + display: flex; + align-items: center; + gap: 8px; + width: 100%; +} +.supply-supplier-rate-field .supply-supplier-rate-input { + flex: 1; + min-width: 0; +} +.supply-supplier-rate-field .supply-supplier-rate-input .el-input { + width: 100%; +} +.supply-supplier-rate-unit { + flex-shrink: 0; + color: #909399; + font-size: calc(14px + var(--wh-fs-delta, 0px)); +} .el-dialog.supply-supplier-form-dlg .el-dialog__body, .el-dialog.supply-supplier-form-dlg .el-form-item__label, .el-dialog.supply-supplier-form-dlg .el-input__inner,