feat(transport): unify client truck and looseboard demand forms

This commit is contained in:
2026-10-19 15:50:39 +08:00
parent 34650b06df
commit 17580fb0a2
6 changed files with 285 additions and 167 deletions
@@ -7,6 +7,9 @@ import ts from 'typescript'
const api = readFileSync(new URL('./api/businessOrders.ts', import.meta.url), 'utf8')
const routes = readFileSync(new URL('./routes.ts', import.meta.url), 'utf8')
const view = readFileSync(new URL('./components/BusinessOrdersView.vue', import.meta.url), 'utf8')
const demandComponent = readFileSync(new URL('./components/TransportDemandForm.vue', import.meta.url), 'utf8')
const demandLogic = ts.transpileModule(readFileSync(new URL('./transportDemandForm.ts', import.meta.url), 'utf8'), { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText.replace(/^export /gm, '')
const demandHelpers = runInNewContext(`${demandLogic}\n({ createTransportDemandForm, transportDemandRules, transportDemandError, buildTransportDemand })`)
const procurementApi = readFileSync(new URL('./api/procurement.ts', import.meta.url), 'utf8')
const procurementView = readFileSync(new URL('./views/ProcurementView.vue', import.meta.url), 'utf8')
@@ -106,7 +109,7 @@ test('preserves the existing transport responsive rules without adding a narrow-
assert.match(view, /queryFields/)
assert.match(view, /\.detail-grid \{ grid-template-columns: 1fr; \}/)
assert.match(view, /\.form-card :deep\(\.el-form-item\) \{ display: block; \}/)
assert.match(view, /\.budget-form-item :deep\(\.el-form-item__content\) \{ display: flex; flex-wrap: nowrap; \}/)
assert.match(demandComponent, /\.transport-demand-budget \{ display: grid; width: 100%/)
})
test('uses the shared dense order-list and detail visual language', () => {
@@ -121,18 +124,18 @@ function transportHarness(kind = 'trucking', failFirst = false) {
const script = view.match(/<script setup lang="ts">([\s\S]*?)<\/script>/)[1]
const compiled = ts.transpileModule(script, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText
.replace(/^import .*?;$/gm, '').replace(/^export \{\};$/gm, '')
const harness = runInNewContext(`${compiled}\n({ form, rules, formRef, submit, detail, detailFields })`, {
const harness = runInNewContext(`${compiled}\n({ form, formRef, submit, detail, detailFields })`, {
defineProps: () => ({ kind, createPage: true, detailPage: false }),
withDefaults: props => props,
computed: getter => ({ get value() { return typeof getter === 'function' ? getter() : getter.get() } }),
reactive: value => value, ref: value => ({ value }), onMounted: () => {}, watch: () => {},
useAuthStore: () => ({ hasPermission: () => true }), useRouter: () => ({ push: async () => {} }), useRoute: () => ({ params: {} }),
DEFAULT_CONTAINER_TYPE: '40HQ', poolOrderStatusLabels: {},
...demandHelpers, poolOrderStatusLabels: {},
ElMessage: { success: () => {}, error: () => {} },
createTransport: async (business, payload) => { calls.push({ business, payload: { ...payload } }); if (failFirst && calls.length === 1) throw new Error('retry'); },
})
harness.formRef.value = { validate: async () => true, clearValidate: () => {} }
return { ...harness, calls }
return { ...harness, calls, rules: { get value() { return demandHelpers.transportDemandRules(kind === 'trucking' ? 'truck' : 'looseboard', harness.form) } } }
}
test('truck requires both contacts vehicle and minute times without inheriting looseboard fields', () => {