From 20a8bf538a86197da680fda84dad68e9e1adb96a Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Tue, 13 Oct 2026 15:30:22 +0800 Subject: [PATCH] feat(mobile-oa-h5): wire samplePayments into protocol payload and detail Drop read-only payment stubs; detail shows per-sample payment cards. Co-authored-by: Cursor --- mobile-oa-h5/src/market/form-payload.js | 12 ++++ mobile-oa-h5/src/market/form-payload.test.js | 13 +++++ mobile-oa-h5/src/market/modules/protocol.js | 61 ++++++++++++++------ 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/mobile-oa-h5/src/market/form-payload.js b/mobile-oa-h5/src/market/form-payload.js index d41b78fb..6973f3a3 100644 --- a/mobile-oa-h5/src/market/form-payload.js +++ b/mobile-oa-h5/src/market/form-payload.js @@ -68,6 +68,18 @@ export function buildMarketActionPayload(module, action, payload) { return clean } +/** 细胞存储协议保存时附加 samplePayments;科研捐赠忽略 */ +export function mergeProtocolSamplePayments(payload, samplePayments) { + const next = { ...(payload || {}) } + if (String(next.source || '') !== 'cell_storage') { + delete next.samplePayments + return next + } + if (samplePayments == null) return next + next.samplePayments = sanitizeMarketPayload(samplePayments) + return next +} + export function validateRequiredFields(sections, formData) { const empty = (value) => value == null || value === '' || (Array.isArray(value) && value.length === 0) for (const section of sections || []) { diff --git a/mobile-oa-h5/src/market/form-payload.test.js b/mobile-oa-h5/src/market/form-payload.test.js index 77fdd8e8..efdc060c 100644 --- a/mobile-oa-h5/src/market/form-payload.test.js +++ b/mobile-oa-h5/src/market/form-payload.test.js @@ -3,11 +3,24 @@ import test from 'node:test' import { buildMarketActionPayload, + mergeProtocolSamplePayments, pickConfiguredPayload, sanitizeMarketPayload, validateRequiredFields } from './form-payload.js' +test('mergeProtocolSamplePayments attaches only for cell_storage', () => { + const pays = [{ sampleCode: 'S1', payMode: 'dj', contractAmount: 1, schedules: [] }] + assert.equal( + mergeProtocolSamplePayments({ source: 'cell_storage', samples: [] }, pays).samplePayments.length, + 1 + ) + assert.equal( + mergeProtocolSamplePayments({ source: 'research_donation' }, pays).samplePayments, + undefined + ) +}) + test('removes authorization and routing fields recursively from form payloads', () => { assert.deepEqual( sanitizeMarketPayload({ diff --git a/mobile-oa-h5/src/market/modules/protocol.js b/mobile-oa-h5/src/market/modules/protocol.js index b2d91618..c9d521f3 100644 --- a/mobile-oa-h5/src/market/modules/protocol.js +++ b/mobile-oa-h5/src/market/modules/protocol.js @@ -139,19 +139,49 @@ export default { })) } ] - if (detail?.source === 'cell_storage' || detail?.payment) { - values.push({ - key: 'payment', - title: '缴费信息', - fields: fields(detail?.payment, [ - ['payMode', '缴费模式', { map: (item) => label(PAY_MODE_LABELS, item), tag: true }], - ['contractAmount', '合同金额'], ['installmentCount', '分期期数'], - ['installmentIntervalMonths', '每期间隔(月)'], ['lumpSumDeadline', '趸交截止时间'], - ['installmentStartDate', '分期开始时间'], ['installmentAdvanceDays', '提前催缴预警(天)'], - ['remark', '缴费备注'] - ]), - cards: [] - }) + if (detail?.source === 'cell_storage' || detail?.payment || detail?.samplePayments) { + const samplePays = Array.isArray(detail?.samplePayments) ? detail.samplePayments : [] + if (samplePays.length) { + values.push({ + key: 'payment', + title: '缴费信息', + fields: [], + cards: samplePays.map((pay, index) => ({ + key: String(pay?.id || pay?.sampleCode || `pay-${index}`), + title: pay?.sampleCode || `样本缴费 ${index + 1}`, + statusText: label(PAY_MODE_LABELS, pay?.payMode), + fields: [ + { label: '缴费模式', value: label(PAY_MODE_LABELS, pay?.payMode), tag: true }, + { label: '合同金额', value: value(pay, 'contractAmount') }, + ...(String(pay?.payMode || '') === 'dj' + ? [{ label: '趸交截止时间', value: value(pay, 'lumpSumDeadline') }] + : [ + { label: '分期期数', value: value(pay, 'installmentCount') }, + { label: '每期间隔(月)', value: value(pay, 'installmentIntervalMonths') }, + { label: '分期开始时间', value: value(pay, 'installmentStartDate') }, + { label: '提前催缴预警(天)', value: value(pay, 'installmentAdvanceDays') } + ]), + ...((pay?.schedules || []).map((sch, sIdx) => ({ + label: `第 ${sch?.scheduleNo || sIdx + 1} 期`, + value: `应缴 ${sch?.dueAmount ?? '—'} / ${sch?.dueDate || '—'}` + }))) + ] + })) + }) + } else { + values.push({ + key: 'payment', + title: '缴费信息', + fields: fields(detail?.payment, [ + ['payMode', '缴费模式', { map: (item) => label(PAY_MODE_LABELS, item), tag: true }], + ['contractAmount', '合同金额'], ['installmentCount', '分期期数'], + ['installmentIntervalMonths', '每期间隔(月)'], ['lumpSumDeadline', '趸交截止时间'], + ['installmentStartDate', '分期开始时间'], ['installmentAdvanceDays', '提前催缴预警(天)'], + ['remark', '缴费备注'] + ]), + cards: [] + }) + } } values.push({ key: 'attachments', @@ -233,11 +263,6 @@ export default { { key: 'specialRemark', label: '特殊说明', type: 'textarea' }, { key: 'remark', label: '备注', type: 'textarea' } ] }, - { key: 'payment', title: '缴费信息(只读)', nested: true, readOnly: true, editOnly: true, source: 'cell_storage', fields: [ - { key: 'payMode', label: '缴费模式', readOnly: true }, - { key: 'contractAmount', label: '合同金额', readOnly: true }, - { key: 'remark', label: '缴费备注', readOnly: true } - ] }, { key: 'attachments', title: '附件与确认', nested: true, fields: [ { key: 'protocolAttachments', label: '协议附件', type: 'upload', source: 'cell_storage' }, { key: 'consentFormUrls', label: '知情同意书', type: 'upload' },