63 lines
3.3 KiB
TypeScript
63 lines
3.3 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
import { readFileSync } from 'node:fs'
|
|
import { parse } from '@vue/compiler-sfc'
|
|
import { compile, computed, createSSRApp, ref } from 'vue'
|
|
import { renderToString } from 'vue/server-renderer'
|
|
import ts from 'typescript'
|
|
import { resolveOpportunityStageLabel, resolveOpportunityTagType } from '../src/utils/crm-opportunity-labels'
|
|
|
|
function source(file: string) {
|
|
return parse(readFileSync(new URL(`../src/views/m/crm/customer/${file}.vue`, import.meta.url), 'utf8')).descriptor
|
|
}
|
|
|
|
test('跟进联系人选项和选中回显保留姓名职位及主要标识,值仍是联系人ID', () => {
|
|
const code = source('FollowPanel').scriptSetup!.content
|
|
const ast = ts.createSourceFile('follow.ts', code, ts.ScriptTarget.Latest, true)
|
|
const fields = ast.statements.filter(ts.isVariableStatement).flatMap((n) => n.declarationList.declarations).find((n) => n.name.getText(ast) === 'fields')!
|
|
const contacts = ref([
|
|
{ id: 1, contactName: '张甲', position: '采购', isPrimary: 1 },
|
|
{ id: 2, contactName: '李乙', position: '经理', isPrimary: 0 }
|
|
])
|
|
const result = new Function('computed', 'contacts', ts.transpile(`return ${fields.initializer!.getText(ast)}`))(computed, contacts)
|
|
const field = result.value.find((f: any) => f.key === 'contactId')
|
|
assert.deepEqual(field.options, [
|
|
{ value: '1', label: '张甲 · 采购 · 主要' },
|
|
{ value: '2', label: '李乙 · 经理' }
|
|
])
|
|
const selectorCode = source('CustomerFields').scriptSetup!.content
|
|
const selectorAst = ts.createSourceFile('fields.ts', selectorCode, ts.ScriptTarget.Latest, true)
|
|
const functions = selectorAst.statements.filter((n) => ts.isFunctionDeclaration(n) && ['hasValue', 'options', 'selectLabel'].includes(n.name?.text || '')).map((n) => n.getText(selectorAst)).join('\n')
|
|
const label = new Function('props', 'dict', `${ts.transpile(functions)};return selectLabel`)(
|
|
{ modelValue: { contactId: '1' } }, {}
|
|
)
|
|
assert.equal(label(field), '张甲 · 采购 · 主要')
|
|
})
|
|
|
|
test('阶段记录用Web语义Tag,名称快照优先,未知阶段保留编码且空起点显示横线', async () => {
|
|
const template = source('RelatedPanel').template!.content.split('<h3>阶段记录</h3>')[1]
|
|
const fragment = template.match(/<div class="mp-customer-detail-card__title">[^]*?<\/div>/)![0]
|
|
const dict = {
|
|
dictMap: { crm_opportunity_stage: [
|
|
{ value: 'initial', label: '初步接触', tagType: 'warning' },
|
|
{ value: 'won', label: '赢单', tagType: 'success' }
|
|
] },
|
|
getLabel: (_: string, value: string) => ({ initial: '初步接触', won: '赢单' }[value] || ''),
|
|
getTagType: () => 'info'
|
|
}
|
|
async function render(row: any) {
|
|
const compiled = compile(fragment)
|
|
const context = { row, dict, resolveOpportunityStageLabel, resolveOpportunityTagType }
|
|
return renderToString(createSSRApp({ render: () => compiled(context, []) }))
|
|
}
|
|
const html = await render({ fromStage: 'initial', fromStageName: '历史起点', toStage: 'won' })
|
|
assert.match(html, /status-tag--warning/)
|
|
assert.match(html, /status-tag--success/)
|
|
assert.match(html, /历史起点/)
|
|
assert.match(html, /赢单/)
|
|
const unknown = await render({ toStage: 'legacy' })
|
|
assert.match(unknown, /legacy/)
|
|
assert.match(unknown, /status-tag--info/)
|
|
assert.match(unknown, /—/)
|
|
})
|