From 2b5f2f939cc19926fa324ba1e313f613748c0db7 Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Thu, 15 Oct 2026 10:06:07 +0800 Subject: [PATCH] fix(mobile-oa-h5): align presign and freight tags with registry mirror Use info for draft; full payMode codes; receptionSource/transportType colors. Co-authored-by: Cursor --- .../market/components/PresignTransferCard.vue | 24 ++---- mobile-oa-h5/src/market/list-presenter.js | 28 +++++-- mobile-oa-h5/src/market/modules/freight.js | 78 ++++++++++++------- mobile-oa-h5/src/market/modules/presign.js | 21 +++-- .../src/market/presign/presign-list-model.js | 5 +- .../src/market/presign/presign-presenter.js | 13 ++-- .../market/presign/presign-presenter.test.js | 2 + 7 files changed, 97 insertions(+), 74 deletions(-) diff --git a/mobile-oa-h5/src/market/components/PresignTransferCard.vue b/mobile-oa-h5/src/market/components/PresignTransferCard.vue index f217e3eb..71401f28 100644 --- a/mobile-oa-h5/src/market/components/PresignTransferCard.vue +++ b/mobile-oa-h5/src/market/components/PresignTransferCard.vue @@ -75,7 +75,6 @@ v-if="can('submit')" type="primary" size="small" - icon="passed" :loading="busyAction === 'submit-transfer'" :disabled="busy" @click="$emit('submit-transfer', modelValue)" @@ -85,7 +84,6 @@ type="warning" plain size="small" - icon="revoke" :loading="busyAction === 'withdraw-transfer'" :disabled="busy" @click="$emit('withdraw-transfer', modelValue)" @@ -97,7 +95,6 @@ type="danger" plain size="small" - icon="delete-o" :disabled="busy" @click="$emit('remove', modelValue)" >删除 @@ -110,6 +107,7 @@ import { computed } from 'vue' import OaDatePicker from '../../oa/components/OaDatePicker.vue' import OaMoneyField from '../../oa/components/OaMoneyField.vue' import { removeMarketAttachmentAt } from '../attachment-upload-state.js' +import { resolveStatusTag, payStatus } from '../status-tag-registry.js' import PresignAttachmentUploader from './PresignAttachmentUploader.vue' import PresignSelectField from './PresignSelectField.vue' @@ -142,21 +140,11 @@ const canDelete = computed(() => !props.disabled && (newRow.value || actionSet.v const busy = computed(() => Boolean(props.busyAction) || props.uploading) const showActions = computed(() => canDelete.value || can('submit') || can('withdraw')) -const statusLabel = computed(() => ({ - dfj: '已付款', - jfqrz: '付款确认中', - yjf: '付款完成', - tfqrz: '退费确认中', - ytf: '已退费' -}[String(props.modelValue.payStatus || 'dfj')] || '已付款')) - -const statusTone = computed(() => ({ - dfj: 'default', - jfqrz: 'warning', - yjf: 'success', - tfqrz: 'warning', - ytf: 'default' -}[String(props.modelValue.payStatus || 'dfj')] || 'default')) +const statusTag = computed(() => + resolveStatusTag(payStatus, props.modelValue.payStatus || 'dfj') +) +const statusLabel = computed(() => statusTag.value.label) +const statusTone = computed(() => statusTag.value.tagType) function can(action) { return !props.disabled && actionSet.value.has(action) diff --git a/mobile-oa-h5/src/market/list-presenter.js b/mobile-oa-h5/src/market/list-presenter.js index 4302dd7f..ab63929e 100644 --- a/mobile-oa-h5/src/market/list-presenter.js +++ b/mobile-oa-h5/src/market/list-presenter.js @@ -5,7 +5,9 @@ import { payMode, protocolStatus, donationStatus, - paymentChaseStatus + paymentChaseStatus, + receptionSource, + transportType } from './status-tag-registry.js' const SEARCH_PLACEHOLDERS = Object.freeze({ @@ -298,10 +300,12 @@ function freightSampleBlock(row, index) { const title = sampleCode ? `样本 ${index + 1} · ${sampleCode}` : `样本 ${index + 1}` + const source = resolveStatusTag(receptionSource, row?.sampleSource) return { key: String(row?.id || row?.sampleId || `${sampleCode || 'sample'}-${index}`), title, - status: label(SOURCE_LABELS, row?.sampleSource), + status: source.label, + statusTone: source.tagType, fields: [ field('协议号', row?.protocolNo, { wide: true }), field('母亲姓名', row?.motherName), @@ -312,18 +316,30 @@ function freightSampleBlock(row, index) { } } +function freightTransportDisplay(item) { + const code = String(item?.transportMode || '').trim() + const provided = String(item?.transportModeLabel || '').trim() + if (provided && provided !== code) return provided + if (!code && !provided) return '—' + if (!code) return provided + return resolveStatusTag(transportType, code).label +} + function freightCard(role, item) { const rows = Array.isArray(item.items) ? item.items : [] const first = rows[0] || {} - const transportMode = label({}, item.transportModeLabel || item.transportMode) - const source = label(SOURCE_LABELS, first.sampleSource || item.sourceLabel) + const transportCode = String(item.transportMode || '').trim() + const transportTag = resolveStatusTag(transportType, transportCode) + const transportMode = freightTransportDisplay(item) + const source = resolveStatusTag(receptionSource, first.sampleSource || item.sourceLabel) const sampleCount = Number(item.visibleItemCount ?? rows.length) || 0 return { title: text(item.freightNo), subtitle: `${transportMode} · ${money(item.freightAmount)}`, - status: source, + status: source.label, + statusTone: source.tagType, fields: [ - field('运输方式', transportMode, { tag: true }), + field('运输方式', transportMode, { tag: true, tagType: transportTag.tagType }), field('运费金额', money(item.freightAmount), { money: true }), field('关联数', String(sampleCount)), field('创建人', personName(item.creatorName || item.createByName, item.createBy)), diff --git a/mobile-oa-h5/src/market/modules/freight.js b/mobile-oa-h5/src/market/modules/freight.js index 6e4f197e..702eeeaf 100644 --- a/mobile-oa-h5/src/market/modules/freight.js +++ b/mobile-oa-h5/src/market/modules/freight.js @@ -1,10 +1,11 @@ -const SOURCE_LABELS = Object.freeze({ cell_storage: '细胞存储', research_donation: '科研捐赠' }) +import { resolveStatusTag, receptionSource, transportType } from '../status-tag-registry.js' -function dictionaryLabel(map, code, providedLabel) { - const label = String(providedLabel || '').trim() +function transportDisplay(code, providedLabel) { const key = String(code || '').trim() + const label = String(providedLabel || '').trim() if (label && label !== key) return label - return map[key] || (key ? '未知' : '—') + if (!key) return '—' + return resolveStatusTag(transportType, key).label } function person(name, id) { @@ -24,29 +25,39 @@ export default { key: 'freight', resource: 'freights', actions: { - specialist: ['view', 'create', 'edit', 'link', 'unlink'], - manager: ['view', 'create', 'edit', 'link', 'unlink'] + specialist: ['view', 'create', 'edit', 'delete', 'link', 'unlink'], + manager: ['view', 'create', 'edit', 'delete', 'link', 'unlink'] }, listParams: ({ status } = {}) => ({ transportMode: status || '', includeItems: true }), statusOptions: [{ text: '全部运输方式', value: '' }], - filterFields: [ - { key: 'transportMode', label: '运输方式', type: 'select', optionKey: 'transportModes' }, + // 运费列表用搜索下方 van-dropdown-menu(对齐预签约),不走筛选弹层 + filterFields: [], + inlineDropdownFilters: [ + { key: 'transportMode', allText: '全部运输方式', optionKey: 'transportModes' }, { - key: 'sampleSource', label: '样本来源', type: 'select', options: [ + key: 'sampleSource', + allText: '全部样本来源', + options: [ { text: '细胞存储', value: 'cell_storage' }, { text: '科研捐赠', value: 'research_donation' } ] - }, - { key: 'createTimeRange', label: '创建时间', type: 'date-range' } + } ], detailSections(detail) { + const transportCode = String(detail?.transportMode || '').trim() + const transportTag = resolveStatusTag(transportType, transportCode) return [ { key: 'base', title: '运费信息', fields: [ { label: '批次号', value: detail?.freightNo || '—' }, - { label: '运输方式', value: dictionaryLabel({}, detail?.transportMode, detail?.transportModeLabel), tag: true, tagType: 'primary' }, + { + label: '运输方式', + value: transportDisplay(transportCode, detail?.transportModeLabel), + tag: true, + tagType: transportTag.tagType + }, { label: '运费金额', value: money(detail?.freightAmount) }, { label: '关联数', value: String(detail?.visibleItemCount ?? detail?.items?.length ?? 0) }, { label: '创建人', value: person(detail?.creatorName || detail?.createByName, detail?.createBy) }, @@ -60,19 +71,23 @@ export default { key: 'items', title: '关联样本', fields: [], - cards: (detail?.items || []).map((item, index) => ({ - key: String(item?.id || `item-${index}`), - title: item?.sampleCode || `样本 ${index + 1}`, - statusText: dictionaryLabel(SOURCE_LABELS, item?.sampleSource), - fields: [ - { label: '来源', value: dictionaryLabel(SOURCE_LABELS, item?.sampleSource) }, - { label: '协议单号', value: item?.protocolNo || '—' }, - { label: '样本编码', value: item?.sampleCode || '—' }, - { label: '样本类型', value: item?.sampleTypeName || '—' }, - { label: '母亲姓名', value: item?.motherName || '—' }, - { label: '子女姓名', value: item?.newbornName || '—' } - ] - })) + cards: (detail?.items || []).map((item, index) => { + const source = resolveStatusTag(receptionSource, item?.sampleSource) + return { + key: String(item?.id || `item-${index}`), + title: item?.sampleCode || `样本 ${index + 1}`, + statusText: source.label, + statusTone: source.tagType, + fields: [ + { label: '来源', value: source.label, tag: true, tagType: source.tagType }, + { label: '协议单号', value: item?.protocolNo || '—' }, + { label: '样本编码', value: item?.sampleCode || '—' }, + { label: '样本类型', value: item?.sampleTypeName || '—' }, + { label: '母亲姓名', value: item?.motherName || '—' }, + { label: '子女姓名', value: item?.newbornName || '—' } + ] + } + }) } ] }, @@ -83,8 +98,13 @@ export default { if (action === 'unlink') return Array.isArray(detailItems) ? detailItems : [] return Array.isArray(optionRows) ? optionRows : [] }, - formSections: [{ key: 'base', title: '运费批次', fields: [ - { key: 'transportMode', label: '运输方式', type: 'select', optionKey: 'transportModes', required: true }, - { key: 'freightAmount', label: '运费金额', type: 'number', required: true } - ] }] + formSections: [{ + key: 'base', + title: '运费批次', + fieldsLayout: 'grid-2', + fields: [ + { key: 'transportMode', label: '运输方式', type: 'select', optionKey: 'transportModes', required: true }, + { key: 'freightAmount', label: '运费金额', type: 'number', required: true } + ] + }] } diff --git a/mobile-oa-h5/src/market/modules/presign.js b/mobile-oa-h5/src/market/modules/presign.js index 72afb5a2..8de59903 100644 --- a/mobile-oa-h5/src/market/modules/presign.js +++ b/mobile-oa-h5/src/market/modules/presign.js @@ -6,14 +6,8 @@ import { presignStatusLabel, presignStatusTone } from '../presign/presign-presenter.js' +import { resolveStatusTag, payMode, payStatus } from '../status-tag-registry.js' -const paymentStatus = Object.freeze({ - dfj: { label: '已付款', tone: 'default' }, - jfqrz: { label: '付款确认中', tone: 'warning' }, - yjf: { label: '付款完成', tone: 'success' }, - tfqrz: { label: '退费确认中', tone: 'warning' }, - ytf: { label: '已退费', tone: 'default' } -}) const transferTypeLabels = Object.freeze({ wxzz: '微信转账', wx: '微信转账', wechat: '微信转账', zzbzz: '支付宝转账', zfb: '支付宝转账', alipay: '支付宝转账', @@ -51,6 +45,12 @@ function displayValue(value) { return value && value !== '-' ? value : '—' } +function payModeLabel(value) { + const key = String(value || '').trim() + if (!key) return '—' + return resolveStatusTag(payMode, key).label +} + export default { key: 'presign', resource: 'presign-orders', @@ -85,13 +85,12 @@ export default { detailSections(detail) { const status = String(detail?.orderStatus || '') const transfers = (detail?.transfers || []).map((transfer, index) => { - const paymentCode = String(transfer?.payStatus || 'dfj') - const payment = paymentStatus[paymentCode] || { label: '未知', tone: 'default' } + const payment = resolveStatusTag(payStatus, transfer?.payStatus || 'dfj') return { ...transfer, title: `意向金转账 ${index + 1}`, statusLabel: payment.label, - statusTone: payment.tone, + statusTone: payment.tagType, transferAmount: formatPresignMoney(transfer?.transferAmount), transferTime: formatPresignDateTime(transfer?.transferTime) } @@ -110,7 +109,7 @@ export default { { label: '采集专员', value: person(detail?.collectorUserName, detail?.collectorUserId) }, { label: '采集经理', value: person(detail?.regionManagerUserName, detail?.regionManagerUserId) }, { label: '采集时间', value: displayValue(formatPresignDateTime(detail?.sampleCollectTime)) }, - { label: '缴费方式', value: dictionaryLabel({ fq: '分期', dj: '趸交' }, detail?.payMode) }, + { label: '缴费方式', value: payModeLabel(detail?.payMode) }, { label: '样本类型', value: Array.isArray(detail?.sampleTypeNames) && detail.sampleTypeNames.length diff --git a/mobile-oa-h5/src/market/presign/presign-list-model.js b/mobile-oa-h5/src/market/presign/presign-list-model.js index d61c05a8..ea9f322d 100644 --- a/mobile-oa-h5/src/market/presign/presign-list-model.js +++ b/mobile-oa-h5/src/market/presign/presign-list-model.js @@ -1,4 +1,5 @@ import { intersectAllowedActions } from '../action-policy.js' +import { resolveStatusTag, payMode } from '../status-tag-registry.js' import { formatPresignDate, formatPresignDateTime, @@ -9,7 +10,6 @@ import { } from './presign-presenter.js' const CARD_ACTIONS = new Set(['edit', 'convert', 'delete']) -const PAY_MODE_LABELS = Object.freeze({ dj: '趸交', fq: '分期', fgd: '分改趸', djfq: '趸交+分期' }) function displayText(value) { return String(value ?? '').trim() || '-' @@ -21,7 +21,8 @@ function actionCode(action) { function payModeLabel(value) { const key = String(value || '').trim() - return PAY_MODE_LABELS[key] || (key ? '未知' : '-') + if (!key) return '-' + return resolveStatusTag(payMode, key).label } export function buildPresignListParams({ keyword = '', orderStatus = '', page = 1, pageSize = 10 } = {}) { diff --git a/mobile-oa-h5/src/market/presign/presign-presenter.js b/mobile-oa-h5/src/market/presign/presign-presenter.js index 5bb36813..836b542f 100644 --- a/mobile-oa-h5/src/market/presign/presign-presenter.js +++ b/mobile-oa-h5/src/market/presign/presign-presenter.js @@ -1,9 +1,4 @@ -const PRESIGN_STATUS = Object.freeze({ - draft: Object.freeze({ label: '草稿', tone: 'default' }), - active: Object.freeze({ label: '进行中', tone: 'warning' }), - converted: Object.freeze({ label: '已转正式', tone: 'success' }), - void: Object.freeze({ label: '已作废', tone: 'danger' }) -}) +import { resolveStatusTag, presignOrderStatus } from '../status-tag-registry.js' function validDateParts(year, month, day) { const date = new Date(Date.UTC(year, month - 1, day)) @@ -83,11 +78,13 @@ export function formatPresignMoney(value) { export function presignStatusLabel(value) { const code = String(value ?? '').trim() if (!code) return '-' - return PRESIGN_STATUS[code]?.label || '未知' + return resolveStatusTag(presignOrderStatus, code).label } export function presignStatusTone(value) { - return PRESIGN_STATUS[String(value ?? '').trim()]?.tone || 'default' + const code = String(value ?? '').trim() + if (!code) return 'info' + return resolveStatusTag(presignOrderStatus, code).tagType } export function presignCardIndex(page, pageSize, position) { diff --git a/mobile-oa-h5/src/market/presign/presign-presenter.test.js b/mobile-oa-h5/src/market/presign/presign-presenter.test.js index e2233dc6..33a86888 100644 --- a/mobile-oa-h5/src/market/presign/presign-presenter.test.js +++ b/mobile-oa-h5/src/market/presign/presign-presenter.test.js @@ -40,6 +40,8 @@ test('uses the Web presign status labels and mobile semantic tones', () => { assert.equal(presignStatusLabel('active'), '进行中') assert.equal(presignStatusLabel('converted'), '已转正式') assert.equal(presignStatusLabel('void'), '已作废') + assert.equal(presignStatusTone('draft'), 'info') + assert.notEqual(presignStatusTone('draft'), 'default') assert.equal(presignStatusTone('converted'), 'success') assert.equal(presignStatusTone('void'), 'danger') assert.equal(presignStatusLabel('custom'), '未知')