From cfc83905734943dcfac6ffadd7530cb7cf977ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=90=A6?= Date: Thu, 6 Aug 2026 20:15:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=AD=E8=8D=AF=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E4=BF=AE=E5=A4=8D=E3=80=81=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E8=B4=A2=E5=8A=A1=E7=9A=84=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursor/rules/Code-Standards.mdc | 1 + .../product/western-medicine/api/index.ts | 6 +- .../components/MinPriceModal.vue | 132 +++- .../product/western-medicine/config/table.ts | 4 +- .../product/western-medicine/index.vue | 13 +- .../admin/api/index.ts | 24 +- .../admin/components/TcmPriceBatchModal.vue | 176 +++-- .../warehouse-drug-management/admin/index.vue | 46 +- .../admin/utils/exportWarehousePriceExcel.ts | 197 +++-- .../admin/utils/parseWarehousePriceExcel.ts | 98 ++- .../admin/utils/priceCompare.ts | 65 +- .../components/PriceCompareCardGrid.vue | 180 ++++- .../shop/components/modal.vue | 78 +- .../shop/config/form.ts | 34 + .../warehouse-drug-management/shop/index.vue | 33 +- .../store/api/index.ts | 66 +- .../store/components/StorePriceBatchModal.vue | 687 ++++++++++++++++++ .../store/components/modal.vue | 78 +- .../store/config/form.ts | 34 + .../store/config/table.ts | 6 + .../warehouse-drug-management/store/index.vue | 107 +-- .../store/utils/exportStorePriceExcel.ts | 171 +++++ .../store/utils/parseStorePriceExcel.ts | 195 +++++ .../settings/components/SignatureModal.vue | 2 +- .../components/ReportDetailDrawer.vue | 57 +- .../department-finance/config/metrics.ts | 59 ++ .../utils/exportDepartmentFinanceExcel.ts | 53 +- .../components/InvoicePriceDrawer.vue | 21 +- .../log/account-able-change-log/api/index.ts | 10 + .../account-able-change-log/config/search.ts | 53 ++ .../account-able-change-log/config/table.ts | 35 + .../log/account-able-change-log/index.vue | 21 + .../src/views/log/error-log/api/index.ts | 11 + .../log/error-log/components/detail-modal.vue | 68 ++ .../src/views/log/error-log/config/search.ts | 27 + .../src/views/log/error-log/config/table.ts | 28 + .../src/views/log/error-log/index.vue | 59 ++ .../views/log/idcard-verify-log/api/index.ts | 16 + .../components/detail-modal.vue | 60 ++ .../log/idcard-verify-log/config/search.ts | 50 ++ .../log/idcard-verify-log/config/table.ts | 32 + .../src/views/log/idcard-verify-log/index.vue | 97 +++ .../views/log/patient-call-log/api/index.ts | 11 + .../components/detail-modal.vue | 59 ++ .../log/patient-call-log/config/search.ts | 49 ++ .../log/patient-call-log/config/table.ts | 33 + .../src/views/log/patient-call-log/index.vue | 40 + .../api/index.ts | 11 + .../components/detail-modal.vue | 62 ++ .../config/search.ts | 39 + .../config/table.ts | 34 + .../product-order-price-adjust-log/index.vue | 40 + .../views/log/shared/normalizeLogFilters.ts | 30 + .../log/store-drug-update-log/api/index.ts | 11 + .../components/detail-modal.vue | 60 ++ .../store-drug-update-log/config/search.ts | 39 + .../log/store-drug-update-log/config/table.ts | 35 + .../views/log/store-drug-update-log/index.vue | 40 + .../log/sync-china-order-log/api/index.ts | 11 + .../components/detail-modal.vue | 68 ++ .../log/sync-china-order-log/config/search.ts | 36 + .../log/sync-china-order-log/config/table.ts | 33 + .../views/log/sync-china-order-log/index.vue | 47 ++ .../warehouse-drug-change-log/api/index.ts | 26 + .../components/detail-modal.vue | 110 +++ .../config/constants.ts | 13 + .../config/search.ts | 77 ++ .../warehouse-drug-change-log/config/table.ts | 61 ++ .../log/warehouse-drug-change-log/index.vue | 108 +++ .../system/ai/api-key/components/modal.vue | 4 +- .../system/ai/generation/config/search.ts | 38 +- .../src/views/system/ai/generation/index.vue | 85 ++- .../system/ai/platform/components/modal.vue | 4 +- .../ai/platform/components/model-modal.vue | 4 +- .../dict/tcm/components/TcmDictListPage.vue | 4 +- .../views/system/dict/west-unit/api/index.ts | 28 + .../src/views/system/dict/west-unit/index.vue | 214 ++++++ .../golden-formula/components/modal.vue | 4 +- .../system/home-zones/components/modal.vue | 4 +- .../system/platform-info/components/modal.vue | 2 +- .../components/qualifications-modal.vue | 4 +- .../components/modal.vue | 4 +- .../system/vip/feature/components/modal.vue | 4 +- .../system/vip/level/components/modal.vue | 4 +- .../vip/store/components/open-modal.vue | 2 +- 85 files changed, 4405 insertions(+), 377 deletions(-) create mode 100644 apps/web-antd/src/views/business/warehouse-drug-management/store/components/StorePriceBatchModal.vue create mode 100644 apps/web-antd/src/views/business/warehouse-drug-management/store/utils/exportStorePriceExcel.ts create mode 100644 apps/web-antd/src/views/business/warehouse-drug-management/store/utils/parseStorePriceExcel.ts create mode 100644 apps/web-antd/src/views/finance/department-finance/config/metrics.ts create mode 100644 apps/web-antd/src/views/log/account-able-change-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/account-able-change-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/account-able-change-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/account-able-change-log/index.vue create mode 100644 apps/web-antd/src/views/log/error-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/error-log/components/detail-modal.vue create mode 100644 apps/web-antd/src/views/log/error-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/error-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/error-log/index.vue create mode 100644 apps/web-antd/src/views/log/idcard-verify-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/idcard-verify-log/components/detail-modal.vue create mode 100644 apps/web-antd/src/views/log/idcard-verify-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/idcard-verify-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/idcard-verify-log/index.vue create mode 100644 apps/web-antd/src/views/log/patient-call-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/patient-call-log/components/detail-modal.vue create mode 100644 apps/web-antd/src/views/log/patient-call-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/patient-call-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/patient-call-log/index.vue create mode 100644 apps/web-antd/src/views/log/product-order-price-adjust-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/product-order-price-adjust-log/components/detail-modal.vue create mode 100644 apps/web-antd/src/views/log/product-order-price-adjust-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/product-order-price-adjust-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/product-order-price-adjust-log/index.vue create mode 100644 apps/web-antd/src/views/log/shared/normalizeLogFilters.ts create mode 100644 apps/web-antd/src/views/log/store-drug-update-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/store-drug-update-log/components/detail-modal.vue create mode 100644 apps/web-antd/src/views/log/store-drug-update-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/store-drug-update-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/store-drug-update-log/index.vue create mode 100644 apps/web-antd/src/views/log/sync-china-order-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/sync-china-order-log/components/detail-modal.vue create mode 100644 apps/web-antd/src/views/log/sync-china-order-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/sync-china-order-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/sync-china-order-log/index.vue create mode 100644 apps/web-antd/src/views/log/warehouse-drug-change-log/api/index.ts create mode 100644 apps/web-antd/src/views/log/warehouse-drug-change-log/components/detail-modal.vue create mode 100644 apps/web-antd/src/views/log/warehouse-drug-change-log/config/constants.ts create mode 100644 apps/web-antd/src/views/log/warehouse-drug-change-log/config/search.ts create mode 100644 apps/web-antd/src/views/log/warehouse-drug-change-log/config/table.ts create mode 100644 apps/web-antd/src/views/log/warehouse-drug-change-log/index.vue create mode 100644 apps/web-antd/src/views/system/dict/west-unit/api/index.ts create mode 100644 apps/web-antd/src/views/system/dict/west-unit/index.vue diff --git a/.cursor/rules/Code-Standards.mdc b/.cursor/rules/Code-Standards.mdc index 396f5527..4836f59c 100644 --- a/.cursor/rules/Code-Standards.mdc +++ b/.cursor/rules/Code-Standards.mdc @@ -145,6 +145,7 @@ alwaysApply: true - 表单必须用 `useVbenForm`,禁止直接 `
` 或 antd `Form` - 动态修改 schema 必须用 `formApi.updateSchema([...])`,**vben form 没有 `setComponentProps` 这个方法**(这是已踩过的坑) +- 重置表单用 `formApi.resetForm()`,**严禁 `formApi.resetFields()`**(那是 antd Form 的 API,Vben Form 没有,会报 `resetFields is not a function`;已踩过坑) - 取值/赋值用 `formApi.getValues()` / `formApi.setValues(obj)`,禁止自己 `v-model` 收集 - 校验用 `formApi.validate().then(e => { if (e.valid) {...} })` 或 `formApi.validateAndSubmitForm()` - 必填规则用字符串 `'required'` / `'selectRequired'`,规则在 `#/adapter/form.ts` 的 `defineRules` 注册 diff --git a/apps/web-antd/src/views/business/product/western-medicine/api/index.ts b/apps/web-antd/src/views/business/product/western-medicine/api/index.ts index 09a94e32..80e2d3a9 100644 --- a/apps/web-antd/src/views/business/product/western-medicine/api/index.ts +++ b/apps/web-antd/src/views/business/product/western-medicine/api/index.ts @@ -77,7 +77,11 @@ export async function updateZoneCategory(data: Record) { * 更新最低调整金额 * @param data */ -export async function updateMinAdjustPrice(data: { id: number; min_adjust_price: number | null }) { +export async function updateMinAdjustPrice(data: { + id: number; + min_adjust_price: number | null; + max_adjust_price?: number | null; +}) { return requestClient.post(`${prefix}update-min-adjust-price`, data); } diff --git a/apps/web-antd/src/views/business/product/western-medicine/components/MinPriceModal.vue b/apps/web-antd/src/views/business/product/western-medicine/components/MinPriceModal.vue index 942f0b00..058770a5 100644 --- a/apps/web-antd/src/views/business/product/western-medicine/components/MinPriceModal.vue +++ b/apps/web-antd/src/views/business/product/western-medicine/components/MinPriceModal.vue @@ -1,13 +1,23 @@ @@ -344,7 +351,7 @@ const openExcelUploadModal = () => { onClick: openBindList.bind(null, row), }, { - label: '设置底价', + label: '设置改价区间', type: 'link', icon: 'ant-design:dollar-outlined', size: 'small', diff --git a/apps/web-antd/src/views/business/warehouse-drug-management/admin/api/index.ts b/apps/web-antd/src/views/business/warehouse-drug-management/admin/api/index.ts index 5f6a7ced..3f3a2ef2 100644 --- a/apps/web-antd/src/views/business/warehouse-drug-management/admin/api/index.ts +++ b/apps/web-antd/src/views/business/warehouse-drug-management/admin/api/index.ts @@ -44,11 +44,21 @@ export async function getWarehouseDrugManagementInfo(id: number) { } /** - * 导出仓库药品药品 + * 导出仓库药品(旧:后端二进制,保留兼容) */ export async function exportWarehouseDrugManagementApi(params?: { type?: number }) { return requestClient.download(`${prefix}export`, { params }); } + +/** + * 导出 JSON 数据(供前端 ExcelJS,对齐订单 export-data) + */ +export async function getWarehouseExportDataApi(params?: { type?: number }) { + return requestClient.get<{ + total: number; + rows: Array>; + }>(`${prefix}export-data`, { params }); +} /** * 导出仓库药品药品 - 模板 */ @@ -110,22 +120,25 @@ export interface WarehouseBatchPriceItem { drug_name: string; drug_number: string; pinyin_simple: string; + unit_id?: number; + unit_name?: string; market_price: number | string; price: number | string; } /** 批量改价预览:全量仓库药品 */ export async function getAllForBatchPriceApi(params: { type: number }) { - return requestClient.get<{ items: WarehouseBatchPriceItem[] }>( - `${prefix}list-all-for-batch-price`, - { params }, - ); + return requestClient.get<{ + items: WarehouseBatchPriceItem[]; + unit_options?: { value: number; label: string }[]; + }>(`${prefix}list-all-for-batch-price`, { params }); } export interface BatchPriceUpdateItem { id: number; market_price: number; price: number; + unit_name?: string; } export interface BatchPriceCreateItem { @@ -133,6 +146,7 @@ export interface BatchPriceCreateItem { drug_number: string; market_price: number; price: number; + unit_name?: string; } /** 批量改价预览:应用更新与新增 */ diff --git a/apps/web-antd/src/views/business/warehouse-drug-management/admin/components/TcmPriceBatchModal.vue b/apps/web-antd/src/views/business/warehouse-drug-management/admin/components/TcmPriceBatchModal.vue index e695775c..0ca25c8d 100644 --- a/apps/web-antd/src/views/business/warehouse-drug-management/admin/components/TcmPriceBatchModal.vue +++ b/apps/web-antd/src/views/business/warehouse-drug-management/admin/components/TcmPriceBatchModal.vue @@ -19,17 +19,23 @@ import { downloadByData } from '#/util/tool'; import { applyBatchPriceApi, getAllForBatchPriceApi, + getWarehouseExportDataApi, type WarehouseBatchPriceItem, } from '../api'; -import { exportWarehousePriceExcel } from '../utils/exportWarehousePriceExcel'; +import { + exportWarehouseListExcel, + type WarehouseExportRow, +} from '../utils/exportWarehousePriceExcel'; import { parseWarehousePriceExcelBuffer } from '../utils/parseWarehousePriceExcel'; import { getPriceDelta, isFieldChanged, isMarketGtPrice, isPriceChanged, + isUnitChanged, normalizePricePair, parsePriceValue, + reconcileExcelPrice, type PricePair, } from '../utils/priceCompare'; import PriceCompareCardGrid, { @@ -60,10 +66,13 @@ const newRows = ref< drug_number: string; market_price: number; price: number; + unit_name: string; }> >([]); const unmatchedRows = ref([]); const excelTouchedIds = ref>(new Set()); +/** 已知单位名称集合,用于标记「待建」 */ +const knownUnitNames = ref>(new Set()); let tempIdCounter = -1; let loadAllPromise: Promise | null = null; @@ -74,6 +83,7 @@ function buildSnapshot(items: WarehouseBatchPriceItem[]) { const pair = normalizePricePair({ market_price: parsePriceValue(item.market_price), price: parsePriceValue(item.price), + unit_name: item.unit_name ?? '', }); init[item.id] = { ...pair }; loc[item.id] = { ...pair }; @@ -91,6 +101,7 @@ function resetState() { newRows.value = []; unmatchedRows.value = []; excelTouchedIds.value = new Set(); + knownUnitNames.value = new Set(); parseHint.value = ''; parsedReady.value = false; filterTab.value = 'all'; @@ -109,22 +120,44 @@ function buildCompareRow( orig: PricePair, isNew: boolean, ): PriceCompareRow { + const normalizedOrig = normalizePricePair(orig); + const normalizedCurrent = normalizePricePair(current); + const unitChanged = isUnitChanged( + normalizedOrig.unit_name, + normalizedCurrent.unit_name, + ); + const unitName = (normalizedCurrent.unit_name ?? '').trim(); + const pendingCreate = + unitName !== '' && !knownUnitNames.value.has(unitName); return { id: item.id, drug_id: item.drug_id, drug_name: item.drug_name, drug_number: item.drug_number, pinyin_simple: item.pinyin_simple, - orig_market_price: orig.market_price, - orig_price: orig.price, - market_price: current.market_price, - price: current.price, - _marketDelta: getPriceDelta(orig.market_price, current.market_price), - _priceDelta: getPriceDelta(orig.price, current.price), - _marketChanged: isFieldChanged(orig.market_price, current.market_price), - _priceChanged: isFieldChanged(orig.price, current.price), - _changed: isNew || isPriceChanged(orig, current), - _marketGtPrice: isMarketGtPrice(current), + orig_market_price: normalizedOrig.market_price, + orig_price: normalizedOrig.price, + orig_unit_name: normalizedOrig.unit_name ?? '', + market_price: normalizedCurrent.market_price, + price: normalizedCurrent.price, + unit_name: normalizedCurrent.unit_name ?? '', + _marketDelta: getPriceDelta( + normalizedOrig.market_price, + normalizedCurrent.market_price, + ), + _priceDelta: getPriceDelta(normalizedOrig.price, normalizedCurrent.price), + _marketChanged: isFieldChanged( + normalizedOrig.market_price, + normalizedCurrent.market_price, + ), + _priceChanged: isFieldChanged( + normalizedOrig.price, + normalizedCurrent.price, + ), + _unitChanged: unitChanged, + _unitPendingCreate: pendingCreate, + _changed: isNew || isPriceChanged(normalizedOrig, normalizedCurrent), + _marketGtPrice: isMarketGtPrice(normalizedCurrent), _isNew: isNew, _fromExcel: isNew ? true : undefined, }; @@ -134,11 +167,13 @@ const compareRows = computed(() => { const existingRows: PriceCompareRow[] = warehouseItems.value .filter((item) => excelTouchedIds.value.has(item.id)) .map((item) => { - const current = localPrices.value[item.id] ?? normalizePricePair({ + const fallback = normalizePricePair({ market_price: parsePriceValue(item.market_price), price: parsePriceValue(item.price), + unit_name: item.unit_name ?? '', }); - const orig = initialSnapshot.value[item.id] ?? current; + const current = localPrices.value[item.id] ?? fallback; + const orig = initialSnapshot.value[item.id] ?? fallback; return buildCompareRow(item, current, orig, false); }); @@ -149,8 +184,12 @@ const compareRows = computed(() => { drug_name: row.drug_name, drug_number: row.drug_number, }, - { market_price: row.market_price, price: row.price }, - { market_price: 0, price: 0 }, + { + market_price: row.market_price, + price: row.price, + unit_name: row.unit_name, + }, + { market_price: 0, price: 0, unit_name: '' }, true, ), ); @@ -225,6 +264,9 @@ async function loadAllDrugs() { try { const res = await getAllForBatchPriceApi({ type: productType.value }); warehouseItems.value = res?.items ?? []; + knownUnitNames.value = new Set( + (res?.unit_options ?? []).map((u) => String(u.label).trim()).filter(Boolean), + ); buildSnapshot(warehouseItems.value); } catch { message.error('加载仓库药品失败'); @@ -255,24 +297,37 @@ async function handleFileChange(info: { file: UploadFile }) { } } +/** + * 下载标准模板:与列表页「导出」同一套 export-data + 列结构, + * 避免改价模板列与导出不一致导致解析误报变更 + */ async function downloadTemplate() { - if (warehouseItems.value.length === 0) { - message.warning('暂无药品数据'); - return; - } try { - const buffer = await exportWarehousePriceExcel(warehouseItems.value); + const res = await getWarehouseExportDataApi({ type: productType.value }); + const rows = (res?.rows ?? []) as WarehouseExportRow[]; + if (rows.length === 0) { + message.warning('暂无药品数据'); + return; + } + const buffer = await exportWarehouseListExcel(rows, '仓库商品'); downloadByData( buffer, - '萧康云医-中药仓库改价模板.xlsx', + '萧康云医-仓库商品导出.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ); - message.success('模板已下载'); + message.success(`模板已下载(${res?.total ?? rows.length} 条,与导出一致)`); } catch { message.error('模板下载失败'); } } +function findWarehouseByDrugId(drugId: number) { + if (drugId <= 0) { + return undefined; + } + return warehouseItems.value.find((d) => d.drug_id === drugId); +} + function findWarehouseByNumber(number: string) { const n = number.trim(); if (!n) { @@ -300,7 +355,7 @@ async function runParse() { syncModalFooterState(); try { const buf = await selectedFile.value.arrayBuffer(); - const { items, invalidCount, rowCount } = + const { items, invalidCount, rowCount, hasUnitColumn } = await parseWarehousePriceExcelBuffer(buf); if (items.length === 0) { @@ -312,6 +367,9 @@ async function runParse() { rowCount > 5000 ? `共 ${rowCount} 行,已按上限处理前 5000 行。` : `共解析 ${items.length} 条有效行。`; + if (!hasUnitColumn) { + parseHint.value += '(未识别到单位列,单位保持原值)'; + } const nextUnmatched: UnmatchedRow[] = []; const nextNew: typeof newRows.value = []; @@ -320,31 +378,41 @@ async function runParse() { let changedExistingCount = 0; for (const row of items) { - let matched = findWarehouseByNumber(row.drug_number); + // 优先药品ID,避免同名/编码漂移误匹配 + let matched = + findWarehouseByDrugId(row.drug_id) || + findWarehouseByNumber(row.drug_number); if (!matched) { matched = findWarehouseByName(row.drug_name); } if (matched) { nextTouched.add(matched.id); - const orig = initialSnapshot.value[matched.id]; - nextLocal[matched.id] = { - market_price: row.market_price, - price: row.price, + const orig = initialSnapshot.value[matched.id] ?? { + market_price: parsePriceValue(matched.market_price), + price: parsePriceValue(matched.price), + unit_name: matched.unit_name ?? '', }; - if ( - orig && - isPriceChanged(orig, { - market_price: row.market_price, - price: row.price, - }) - ) { + // 无单位列或单元格为空:保留原单位,避免误报单位变更 + const excelUnit = (row.unit_name ?? '').trim(); + const unitName = + hasUnitColumn && excelUnit !== '' + ? excelUnit + : (orig.unit_name ?? matched.unit_name ?? ''); + // 价格与快照对账,消化 Excel 一分钱浮点误差 + const nextPair = normalizePricePair({ + market_price: reconcileExcelPrice(row.market_price, orig.market_price), + price: reconcileExcelPrice(row.price, orig.price), + unit_name: unitName, + }); + nextLocal[matched.id] = nextPair; + if (isPriceChanged(orig, nextPair)) { changedExistingCount += 1; } continue; } - if (row.drug_name || row.drug_number) { + if (row.drug_name || row.drug_number || row.drug_id > 0) { tempIdCounter -= 1; nextNew.push({ tempId: tempIdCounter, @@ -352,6 +420,7 @@ async function runParse() { drug_number: row.drug_number, market_price: row.market_price, price: row.price, + unit_name: (row.unit_name ?? '').trim(), }); } else { nextUnmatched.push(row); @@ -368,7 +437,7 @@ async function runParse() { } else if (nextNew.length > 0) { filterTab.value = 'new'; } else { - filterTab.value = 'all'; + filterTab.value = 'unchanged'; } if (invalidCount > 0) { @@ -377,6 +446,9 @@ async function runParse() { if (nextNew.length > 0) { message.info(`有 ${nextNew.length} 条药品将自动新增入库`); } + if (changedExistingCount === 0 && nextNew.length === 0) { + message.info('未检测到价格或单位变更'); + } parsedReady.value = true; } catch { @@ -391,6 +463,7 @@ function syncRowFromGrid(row: PriceCompareRow) { const normalized = normalizePricePair({ market_price: parsePriceValue(row.market_price), price: parsePriceValue(row.price), + unit_name: row.unit_name, }); if (row._isNew) { newRows.value = newRows.value.map((item) => @@ -399,6 +472,7 @@ function syncRowFromGrid(row: PriceCompareRow) { ...item, market_price: normalized.market_price, price: normalized.price, + unit_name: normalized.unit_name ?? '', } : item, ); @@ -435,6 +509,7 @@ async function handleRowSave(row: PriceCompareRow) { const saved = normalizePricePair({ market_price: parsePriceValue(row.market_price), price: parsePriceValue(row.price), + unit_name: row.unit_name, }); savingRowId.value = row.id; @@ -449,6 +524,7 @@ async function handleRowSave(row: PriceCompareRow) { drug_number: row.drug_number, market_price: saved.market_price, price: saved.price, + unit_name: saved.unit_name, }, ], notify: false, @@ -462,6 +538,7 @@ async function handleRowSave(row: PriceCompareRow) { id: row.id, market_price: saved.market_price, price: saved.price, + unit_name: saved.unit_name, }, ], creates: [], @@ -475,9 +552,17 @@ async function handleRowSave(row: PriceCompareRow) { ...localPrices.value, [row.id]: { ...saved }, }; + if (saved.unit_name) { + knownUnitNames.value.add(saved.unit_name); + } warehouseItems.value = warehouseItems.value.map((item) => item.id === row.id - ? { ...item, market_price: saved.market_price, price: saved.price } + ? { + ...item, + market_price: saved.market_price, + price: saved.price, + unit_name: saved.unit_name, + } : item, ); } @@ -499,12 +584,14 @@ async function runBatchApply() { const prices = normalizePricePair({ market_price: row.market_price, price: row.price, + unit_name: row.unit_name, }); return { drug_name: row.drug_name, drug_number: row.drug_number, market_price: prices.market_price, price: prices.price, + unit_name: prices.unit_name, }; }); @@ -522,8 +609,12 @@ async function runBatchApply() { drug_name: c.drug_name, drug_number: c.drug_number, }, - { market_price: c.market_price, price: c.price }, - { market_price: 0, price: 0 }, + { + market_price: c.market_price, + price: c.price, + unit_name: c.unit_name, + }, + { market_price: 0, price: 0, unit_name: '' }, true, ), ), @@ -541,11 +632,13 @@ async function runBatchApply() { const prices = normalizePricePair({ market_price: parsePriceValue(row.market_price), price: parsePriceValue(row.price), + unit_name: row.unit_name, }); return { id: row.id, market_price: prices.market_price, price: prices.price, + unit_name: prices.unit_name, }; }), creates, @@ -568,7 +661,7 @@ async function runBatchApply() {