import assert from 'node:assert/strict' import test from 'node:test' import * as navigation from '../src/utils/mp-webview' const api = navigation as any test('客户进入合同后继续查看报价,返回合同仍保留最外层客户来源', () => { assert.equal(typeof api.mpContractRelatedLocation, 'function') const location = api.mpContractRelatedLocation('quote', { id: 'K-1', quoteId: 'Q1' }, { from: 'customer', customerId: 'C1' }) assert.equal(location.path, '/m/crm/quote/Q1') assert.deepEqual(api.mpRelatedContractReturnLocation(location.query), { path: '/m/crm/contract/K-1', query: { from: 'customer', customerId: 'C1' } }) }) test('关联客户和商机复用现有客户详情,不需要商机列表命中', () => { assert.equal(typeof api.mpContractRelatedLocation, 'function') const row = { id: 'K1', customerId: 'C1', opportunityId: 'O999' } assert.equal(api.mpContractRelatedLocation('customer', row, {}).path, '/m/crm/customer/C1') const location = api.mpContractRelatedLocation('opportunity', row, {}) assert.equal(location.path, '/m/crm/customer/C1') assert.equal(location.query.tab, 'opportunity') assert.equal(location.query.opportunityId, 'O999') }) test('非法目标与返回ID不能形成任意站外或相对路径', () => { assert.equal(typeof api.mpContractRelatedLocation, 'function') for (const value of ['../x', '//evil.test', 'x?foo=1', ['K1'], '']) { assert.equal(api.mpContractRelatedLocation('quote', { id: 'K1', quoteId: value }, {}), null) assert.equal(api.mpRelatedContractReturnLocation({ from: 'contract', returnContractId: value }), null) } }) test('商机跟进展示使用Web crm_follow_type,未知值保留原值', async () => { const { readFileSync } = await import('node:fs') const { compile } = await import('vue') const { resolveOpportunityDictLabel } = await import('../src/utils/crm-opportunity-labels') const source = readFileSync(new URL('../src/views/m/crm/customer/RelatedPanel.vue', import.meta.url), 'utf8') const expression = source.match(/{{\s*([^{}]*row\.followType[^{}]*)\s*}}/)?.[1] assert.ok(expression) const dict = { dictMap: { crm_follow_type: [{ value: 'phone', label: '客户电话' }], crm_opportunity_follow_type: [{ value: 'phone', label: '商机电话' }] }, getLabel: (type: string) => type === 'crm_follow_type' ? '客户电话' : '商机电话' } const render = compile(`{{ ${expression} }}`) assert.equal(render({ row: { followType: 'phone' }, dict, resolveOpportunityDictLabel }, []).children, '客户电话') assert.equal(render({ row: { followType: 'legacy' }, dict, resolveOpportunityDictLabel }, []).children, 'legacy') }) test('关闭旧商机不能清除新目标query,关闭当前只移除目标并保留返回链', async () => { const { readFileSync } = await import('node:fs') const { parse } = await import('@vue/compiler-sfc') const ts = (await import('typescript')).default const source = parse(readFileSync(new URL('../src/views/m/crm/customer/detail.vue', import.meta.url), 'utf8')).descriptor.scriptSetup!.content const ast = ts.createSourceFile('detail.ts', source, ts.ScriptTarget.Latest, true) const method = ast.statements.find((node) => ts.isFunctionDeclaration(node) && node.name?.text === 'clearTargetOpportunity')! const calls: any[] = [] const route = { path: '/m/crm/customer/C1', query: { opportunityId: 'O2', from: 'contract', returnContractId: 'K1', originCustomerId: 'C0', tab: 'opportunity' } } const clear = new Function('route', 'router', 'targetOpportunityId', 'isCurrentCustomerRoute', `${ts.transpile(method.getText(ast))};return clearTargetOpportunity`)(route, { replace: (v: any) => calls.push(v) }, { value: 'O2' }, () => true) clear('O1') assert.equal(calls.length, 0) clear('O2') assert.deepEqual(calls, [{ path: route.path, query: { from: 'contract', returnContractId: 'K1', originCustomerId: 'C0', tab: 'opportunity' } }]) }) test('历史数值ID仅接受安全整数,合同和关联对象一致规范化', () => { for (const id of [1, 123, Number.MAX_SAFE_INTEGER]) { assert.equal(api.mpCrmRecordId(id), String(id)) const location = api.mpContractRelatedLocation('customer', { id, customerId: id }, {}) assert.equal(location.path, `/m/crm/customer/${id}`) assert.equal(api.mpRelatedContractReturnLocation(location.query).path, `/m/crm/contract/${id}`) } for (const id of [NaN, Infinity, -Infinity, 1.5, Number.MAX_SAFE_INTEGER + 1]) { assert.equal(api.mpCrmRecordId(id), '') assert.equal(api.mpContractRelatedLocation('customer', { id, customerId: 'C1' }, {}), null) assert.equal(api.mpContractRelatedLocation('customer', { id: 'K1', customerId: id }, {}), null) } })