优化
This commit is contained in:
+142
-32
@@ -97,7 +97,7 @@ const notificationConsumers = [
|
||||
'notifications/components/TemplateEditorDialog.vue',
|
||||
]
|
||||
const systemConsumers = ['iam/pages/InternalUsersView.vue', 'iam/pages/RolesView.vue', 'iam/pages/PermissionsView.vue']
|
||||
const selfOperatedPages = ['self-operated/components/AnalyticsView.vue']
|
||||
const selfOperatedPages = ['self-operated/components/AnalyticsView.vue', 'self-operated/components/InventoryTurnoverView.vue']
|
||||
const selfOperatedConsumers = [...selfOperatedPages, 'self-operated/components/SkuTrend.vue', 'self-operated/pages/OverviewView.vue']
|
||||
const consumers = [
|
||||
...selfOperatedConsumers,
|
||||
@@ -156,14 +156,53 @@ const densityPages = [...new Set([
|
||||
])]
|
||||
type TemplateNode = NonNullable<NonNullable<ReturnType<typeof parse>['descriptor']['template']>['ast']>['children'][number]
|
||||
type ElementNode = Extract<TemplateNode, { type: 1 }>
|
||||
const classesOf = (node: ElementNode, preload = true, dense = preload, workbench = 'DOMESTIC'): string[] => node.props.flatMap(prop => {
|
||||
const classesOf = (node: ElementNode, preload = true, dense = preload, region = 'DOMESTIC', workbench = false, embedded = false): string[] => node.props.flatMap(prop => {
|
||||
if (prop.type === 6 && prop.name === 'class') return prop.value?.content.split(/\s+/) ?? []
|
||||
if (prop.type !== 7 || prop.name !== 'bind' || prop.arg?.type !== 4 || prop.arg.content !== 'class' || prop.exp?.type !== 4 || !prop.exp.content.includes('density')) return []
|
||||
// Evaluate only the authored density class binding with the shared component's two modes.
|
||||
const value = new Function('mode', 'isPreload', 'dense', 'isDomestic', 'isOverseas', `return (${prop.exp.content})`)(preload ? 'preload' : 'confirmed', preload, dense, workbench === 'DOMESTIC', workbench === 'OVERSEAS') as Record<string, boolean>
|
||||
// Keep visual opt-in and embedding independent from the shared component's density/region modes.
|
||||
const value = new Function('mode', 'isPreload', 'dense', 'isDomestic', 'isOverseas', 'workbench', 'embedded', `return (${prop.exp.content})`)(preload ? 'preload' : 'confirmed', preload, dense, region === 'DOMESTIC', region === 'OVERSEAS', workbench, embedded) as Record<string, boolean>
|
||||
const flatten = (value: unknown): string[] => typeof value === 'string' ? value.split(/\s+/) : Array.isArray(value) ? value.flatMap(flatten) : value && typeof value === 'object' ? Object.entries(value).filter(([, enabled]) => enabled).flatMap(([names]) => names.split(/\s+/)) : []
|
||||
return flatten(value)
|
||||
})
|
||||
const elementsOf = (source: string, tag?: string): ElementNode[] => {
|
||||
const parsed = parse(source)
|
||||
expect(parsed.errors).toEqual([])
|
||||
const result: ElementNode[] = []
|
||||
const visit = (nodes: TemplateNode[]) => {
|
||||
for (const node of nodes) {
|
||||
if (node.type !== 1) continue
|
||||
if (!tag || node.tag === tag) result.push(node)
|
||||
visit(node.children)
|
||||
}
|
||||
}
|
||||
visit(parsed.descriptor.template!.ast!.children)
|
||||
return result
|
||||
}
|
||||
const expectWorkbenchDialogs = (source: string) => {
|
||||
const dialogs = elementsOf(source, 'AppDialog')
|
||||
expect(dialogs.length).toBeGreaterThan(0)
|
||||
for (const dialog of dialogs) {
|
||||
expect(classesOf(dialog), dialog.loc.source.split('>')[0]).toEqual(expect.arrayContaining(['admin-density-dialog', 'admin-workbench', 'is-dialog']))
|
||||
}
|
||||
return dialogs
|
||||
}
|
||||
const confirmationClasses = (source: string): string[][] => {
|
||||
const script = source.includes('<script') ? parse(source).descriptor.scriptSetup!.content : source
|
||||
const ast = ts.createSourceFile('confirmation.ts', script, ts.ScriptTarget.Latest, true)
|
||||
const result: string[][] = []
|
||||
const visit = (node: ts.Node) => {
|
||||
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.expression.getText(ast) === 'ElMessageBox') {
|
||||
const options = node.arguments[2]
|
||||
expect(options && ts.isObjectLiteralExpression(options)).toBe(true)
|
||||
const customClass = options && ts.isObjectLiteralExpression(options) ? options.properties.find(prop => ts.isPropertyAssignment(prop) && prop.name.getText(ast) === 'customClass') : undefined
|
||||
expect(customClass && ts.isPropertyAssignment(customClass) && ts.isStringLiteral(customClass.initializer)).toBe(true)
|
||||
if (customClass && ts.isPropertyAssignment(customClass) && ts.isStringLiteral(customClass.initializer)) result.push(customClass.initializer.text.split(/\s+/))
|
||||
}
|
||||
ts.forEachChild(node, visit)
|
||||
}
|
||||
visit(ast)
|
||||
return result
|
||||
}
|
||||
const styles = [
|
||||
...parse(read('shared/components/BatchImportDialog.vue')).descriptor.styles.map(style => ({ file: 'BatchImportDialog.vue', css: style.content })),
|
||||
...consumers.flatMap(file => parse(read(`modules/${file}`)).descriptor.styles.map(style => ({ file, css: style.content }))),
|
||||
@@ -178,6 +217,24 @@ const cssRoot = (css: string) => {
|
||||
}
|
||||
|
||||
describe('approved Admin density ownership', () => {
|
||||
it('keeps sailing cutoff controls compact and delegates editor borders to the shared opt-in', () => {
|
||||
const view = parse(read('modules/sailing-calendar/pages/SailingCalendarView.vue')).descriptor
|
||||
const rules = new Map<string, Record<string, string>>()
|
||||
for (const style of view.styles) cssRoot(style.content).walkRules(rule => {
|
||||
const values: Record<string, string> = {}
|
||||
rule.walkDecls(decl => { values[decl.prop] = decl.value })
|
||||
rules.set(rule.selector, values)
|
||||
})
|
||||
expect(rules.get('.sailing-entry-label')).toEqual({ width: '116px' })
|
||||
expect(rules.get('.cutoff-presets')).toEqual({ flex: '0 0 auto' })
|
||||
expect(rules.get('.sailing-date-editor')).toMatchObject({ width: '280px', 'max-width': '100%' })
|
||||
expect(rules.get('.cutoff-rule-row, .cutoff-time-row')).toMatchObject({ 'flex-wrap': 'wrap' })
|
||||
expect(view.template!.content).toContain('density-table-editor density-table-editor--outlined cutoff-days-editor')
|
||||
expect(view.template!.content).toContain('density-table-editor--outlined cutoff-time-editor')
|
||||
expect(view.template!.content).toContain('role="status" aria-live="polite"')
|
||||
expect(view.styles.map(style => style.content).join('\n')).not.toContain('--el-input-border-color')
|
||||
})
|
||||
|
||||
it('outlines only the three opted-in customer billing editors without overriding native focus or disabled styles', () => {
|
||||
const rules = new Map<string, Record<string, string>>()
|
||||
cssRoot(shared).walkRules(rule => {
|
||||
@@ -362,7 +419,8 @@ describe('approved Admin density ownership', () => {
|
||||
it('opts transfer approval into the shared centered confirmation appearance', () => {
|
||||
const dialog = read('modules/overseas-warehouse/components/WarehouseTransferReviewDialog.vue')
|
||||
const css = read('styles/adminDensity.css')
|
||||
expect(dialog).toContain('class="admin-density-dialog density-confirm-dialog"')
|
||||
const [frame] = expectWorkbenchDialogs(dialog)
|
||||
expect(classesOf(frame!)).toContain('density-confirm-dialog')
|
||||
expect(dialog).toContain('align-center')
|
||||
expect(css).toContain('.admin-density-dialog.density-confirm-dialog.el-dialog:not(.is-fullscreen) { margin: auto; }')
|
||||
expect(css).toContain('.admin-density-dialog.density-confirm-dialog.el-dialog .el-dialog__header { border-bottom: 0; }')
|
||||
@@ -399,7 +457,8 @@ describe('approved Admin density ownership', () => {
|
||||
expect(dialogs).toHaveLength(3)
|
||||
for (const dialog of dialogs) { expect(dialog).toContain('admin-density-dialog'); expect(dialog).toContain('fullscreenable') }
|
||||
expect(view.template!.content).toContain('density-table density-table--editable')
|
||||
expect(view.template!.content).toContain('label-position="left" label-width="110px"')
|
||||
expect(view.template!.content).toContain('label-position="left" label-width="150px"')
|
||||
expect(view.template!.content).toContain('<el-date-picker v-model="plannedAt" type="datetime"')
|
||||
expect(view.styles.map(style => style.content).join('\n')).not.toContain('arrival-field')
|
||||
expect(create.template!.content).toContain('aria-label="预约保存回执"')
|
||||
expect(create.template!.content).not.toContain('<FbaAppointmentFields')
|
||||
@@ -421,7 +480,8 @@ describe('approved Admin density ownership', () => {
|
||||
expect(page.template!.content).toMatch(/class="[^"]*density-status-tabs[^"]*" role="tablist"/)
|
||||
expect(page.styles.map((style) => style.content).join('\n')).not.toMatch(/\.(status-tabs?|supplier-tabs|container-scope-tabs)\s*[{:.]/)
|
||||
}
|
||||
expect(read('modules/overseas-warehouse/pages/ReturnInventoryManagementView.vue')).toContain('class="density-element-tabs density-status-tabs"')
|
||||
const returnTabs = elementsOf(read('modules/overseas-warehouse/pages/ReturnInventoryManagementView.vue'), 'el-tabs')
|
||||
expect(returnTabs.some(node => ['density-element-tabs', 'density-status-tabs'].every(name => classesOf(node).includes(name)))).toBe(true)
|
||||
const selectors: string[] = []
|
||||
cssRoot(shared).walkRules((rule) => { selectors.push(...rule.selectors) })
|
||||
expect(selectors).toContain('.admin-density .density-status-tabs > button.is-active::after')
|
||||
@@ -436,15 +496,21 @@ describe('approved Admin density ownership', () => {
|
||||
|
||||
it('keeps dashboard visualizations outside detail-field table styling', () => {
|
||||
const dashboard = read('modules/dashboard/pages/DashboardView.vue')
|
||||
expect(dashboard).toContain('class="dashboard-metrics"')
|
||||
expect(dashboard).toContain('class="dashboard-metric-mark"')
|
||||
const metrics = elementsOf(dashboard, 'div').filter(node => classesOf(node).includes('dashboard-metrics'))
|
||||
expect(metrics).toHaveLength(1)
|
||||
const cards = elementsOf(dashboard, 'article').filter(node => classesOf(node).includes('dashboard-metric'))
|
||||
expect(cards).toHaveLength(1)
|
||||
expect(classesOf(cards[0]!)).toEqual(expect.arrayContaining(['workbench-metric', 'workbench-tone']))
|
||||
const icon = elementsOf(dashboard, 'span').find(node => classesOf(node).includes('workbench-icon'))
|
||||
expect(icon).toBeDefined()
|
||||
expect(icon!.children.some(node => node.type === 1 && node.tag === 'component')).toBe(true)
|
||||
expect(dashboard).not.toContain('density-fields')
|
||||
})
|
||||
|
||||
it('registers the self-operated dashboard with an explicit density root and chart layout', () => {
|
||||
const source = read('modules/self-operated/pages/OverviewView.vue')
|
||||
expect(source).toContain("@/styles/adminDensity.css")
|
||||
expect(source).toContain('<AdminPage class="admin-density dashboard-page">')
|
||||
expect(source).toContain('<AdminPage class="admin-density admin-workbench dashboard-page">')
|
||||
expect(source).toContain('class="dashboard-kpis"')
|
||||
expect(source).toContain('class="dashboard-main-charts"')
|
||||
expect(source).not.toContain('density-fields')
|
||||
@@ -521,7 +587,8 @@ describe('approved Admin density ownership', () => {
|
||||
const source = read('modules/warehouses/pages/WarehousesView.vue')
|
||||
expect(source).toContain('class="density-form density-dialog-sections"')
|
||||
expect(source).toContain('density-table density-table--editable warehouse-editor-table')
|
||||
expect(source).toContain('class="warehouse-import-dialog admin-density-dialog"')
|
||||
const importer = expectWorkbenchDialogs(source).find(node => classesOf(node).includes('warehouse-import-dialog'))
|
||||
expect(importer).toBeDefined()
|
||||
expect(source).toContain('class="density-table warehouse-import-summary"')
|
||||
expect(source).toContain('class="density-actions density-actions--footer"')
|
||||
expect(source).not.toContain('<FormSection')
|
||||
@@ -591,7 +658,7 @@ describe('approved Admin density ownership', () => {
|
||||
it('keeps download task detail on shared facts, error and footer primitives', () => {
|
||||
const source = read('modules/downloads/pages/DownloadCenterView.vue')
|
||||
const dialog = source.slice(source.indexOf('<AppDialog'), source.indexOf('</AppDialog>'))
|
||||
expect(dialog).toContain('class="admin-density-dialog"')
|
||||
expectWorkbenchDialogs(source)
|
||||
expect(dialog).toContain('fullscreenable')
|
||||
expect(dialog).toContain('data-tone="summary"')
|
||||
expect(dialog).toContain('class="task-detail-grid density-fields"')
|
||||
@@ -606,7 +673,7 @@ describe('approved Admin density ownership', () => {
|
||||
const list = read('modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue')
|
||||
const detail = read('modules/fba-pricing/carrier-rates/pages/CarrierRateDetailView.vue')
|
||||
const dialog = list.slice(list.indexOf('<AppDialog'), list.indexOf('</AppDialog>'))
|
||||
expect(dialog).toContain('class="admin-density-dialog"')
|
||||
expectWorkbenchDialogs(list)
|
||||
expect(dialog).toContain('width="min(560px, calc(100vw - 28px))"')
|
||||
expect(dialog).toContain(':confirm-loading="uploading"')
|
||||
expect(dialog).toContain('class="density-table density-table--editable"')
|
||||
@@ -621,7 +688,9 @@ describe('approved Admin density ownership', () => {
|
||||
const editor = read('modules/overseas-master-data/components/FleetQuoteEditor.vue')
|
||||
const importer = read('modules/overseas-master-data/components/FleetQuoteImport.vue')
|
||||
for (const source of [editor, importer]) {
|
||||
expect(source).toContain('class="admin-density-dialog" fullscreenable :confirm-loading="saving"')
|
||||
const [dialog] = expectWorkbenchDialogs(source)
|
||||
expect(dialog!.props.some(prop => prop.type === 6 && prop.name === 'fullscreenable')).toBe(true)
|
||||
expect(dialog!.props.some(prop => prop.type === 7 && prop.name === 'bind' && prop.arg?.type === 4 && prop.arg.content === 'confirm-loading' && prop.exp?.type === 4 && prop.exp.content === 'saving')).toBe(true)
|
||||
expect(source).toContain('density-table--editable')
|
||||
expect(source).toContain('data-tone="work"')
|
||||
expect(source).toContain('data-tone="source"')
|
||||
@@ -632,19 +701,20 @@ describe('approved Admin density ownership', () => {
|
||||
}
|
||||
expect(editor).toContain('v-if="readonly"')
|
||||
expect(editor).toContain('class="density-fields fleet-quote-facts"')
|
||||
expect(read('modules/overseas-master-data/pages/FleetQuotesView.vue')).toContain("customClass: 'admin-density-confirm'")
|
||||
const confirmations = confirmationClasses(read('modules/overseas-master-data/pages/FleetQuotesView.vue'))
|
||||
expect(confirmations.length).toBeGreaterThan(0)
|
||||
for (const classes of confirmations) expect(classes).toContain('admin-density-confirm')
|
||||
})
|
||||
|
||||
it('keeps pricing dialogs on shared tables and sections without local form paint', () => {
|
||||
const rate = read('modules/overseas-master-data/pages/ExchangeRatesView.vue')
|
||||
const quote = read('modules/overseas-master-data/pages/OverseasQuotesView.vue')
|
||||
for (const source of [rate, quote]) {
|
||||
const dialogs = parse(source).descriptor.template!.content.match(/<AppDialog[\s\S]*?<\/AppDialog>/g)!
|
||||
const dialogs = expectWorkbenchDialogs(source)
|
||||
expect(dialogs.length).toBeGreaterThan(0)
|
||||
for (const dialog of dialogs) {
|
||||
expect(dialog).toContain('class="admin-density-dialog"')
|
||||
expect(dialog).not.toContain('label-position="top"')
|
||||
expect(dialog).not.toContain('#header')
|
||||
expect(dialog.loc.source).not.toContain('label-position="top"')
|
||||
expect(dialog.loc.source).not.toContain('#header')
|
||||
}
|
||||
expect(source).toContain('density-table--editable')
|
||||
expect(source).not.toContain('line-grid')
|
||||
@@ -660,10 +730,13 @@ describe('approved Admin density ownership', () => {
|
||||
|
||||
it('keeps the supplier license dialog styled at its own teleported root', () => {
|
||||
const source = read('modules/suppliers/components/SupplierLicenseDialog.vue')
|
||||
expect(source).toContain('<AppDialog class="admin-density-dialog"')
|
||||
expectWorkbenchDialogs(source)
|
||||
expect(source).toContain('width="min(560px, calc(100vw - 24px))"')
|
||||
expect(source).toContain('aria-label="营业执照信息"')
|
||||
expect(source).toContain('class="density-dialog-section" data-tone="source"')
|
||||
const sections = elementsOf(source, 'section')
|
||||
expect(sections).toHaveLength(1)
|
||||
expect(classesOf(sections[0]!)).toEqual(expect.arrayContaining(['density-dialog-section', 'workbench-evidence']))
|
||||
expect(sections[0]!.props.some(prop => prop.type === 6 && prop.name === 'data-tone' && prop.value?.content === 'source')).toBe(true)
|
||||
expect(source).toContain('class="density-table license-info-table"')
|
||||
expect(source).not.toContain('license-card')
|
||||
expect(source).not.toContain('box-shadow')
|
||||
@@ -731,10 +804,16 @@ describe('approved Admin density ownership', () => {
|
||||
expect(source).toContain('dense?: boolean')
|
||||
const ast = parse(source).descriptor.template!.ast!
|
||||
const root = ast.children.find(node => node.type === 1) as ElementNode
|
||||
expect(classesOf(root, false, true).some(name => name.startsWith('admin-density')), file).toBe(true)
|
||||
expect(classesOf(root, false, false).some(name => name.startsWith('admin-density')), file).toBe(false)
|
||||
for (const workbench of [false, true]) {
|
||||
expect(classesOf(root, false, true, 'DOMESTIC', workbench).some(name => name.startsWith('admin-density')), file).toBe(true)
|
||||
expect(classesOf(root, false, false, 'DOMESTIC', workbench).some(name => name.startsWith('admin-density')), file).toBe(false)
|
||||
if (file.endsWith('OverseasDetailShell.vue')) {
|
||||
for (const dense of [false, true]) expect(classesOf(root, false, dense, 'DOMESTIC', workbench).includes('admin-workbench')).toBe(workbench)
|
||||
}
|
||||
}
|
||||
}
|
||||
expect(read('modules/overseas-warehouse/components/OverseasReadOnlyDetail.vue')).toContain(':dense="dense"')
|
||||
expect(read('modules/overseas-warehouse/components/OverseasReadOnlyDetail.vue')).toContain(':workbench="workbench"')
|
||||
expect(read('modules/overseas-warehouse/pages/InventoryTransactionsView.vue')).toContain('<InboundCodeRelationshipDialog dense')
|
||||
expect(read('modules/inbounds/pages/InboundOrdersView.vue')).toContain('<InboundCodeRelationshipDialog dense')
|
||||
for (const file of ['CartonDetailView', 'ProductDetailView']) expect(read('modules/overseas-warehouse/pages/' + file + '.vue')).not.toContain(' dense')
|
||||
@@ -761,8 +840,14 @@ describe('approved Admin density ownership', () => {
|
||||
for (const file of ['loading-lists/components/LoadingListDetailDrawer.vue', 'port-schedules/components/CarrierScheduleQueryPanel.vue']) {
|
||||
const ast = parse(read(`modules/${file}`)).descriptor.template!.ast!
|
||||
const root = ast.children.find(node => node.type === 1) as ElementNode
|
||||
expect(classesOf(root, false, true)).toContain('admin-density')
|
||||
expect(classesOf(root, false, false)).not.toContain('admin-density')
|
||||
for (const embedded of [false, true]) {
|
||||
expect(classesOf(root, false, true, 'DOMESTIC', false, embedded)).toContain('admin-density')
|
||||
expect(classesOf(root, false, false, 'DOMESTIC', false, embedded)).not.toContain('admin-density')
|
||||
if (file.includes('LoadingListDetail')) {
|
||||
expect(classesOf(root, false, true, 'DOMESTIC', false, embedded).includes('workbench-panel')).toBe(!embedded)
|
||||
expect(classesOf(root, false, true, 'DOMESTIC', false, embedded).includes('is-compact')).toBe(!embedded)
|
||||
}
|
||||
}
|
||||
if (file.includes('CarrierSchedule')) {
|
||||
const dialog = root.children.find(node => node.type === 1 && node.tag === 'AppDialog') as ElementNode
|
||||
expect(classesOf(dialog, false, true)).toContain('admin-density-dialog')
|
||||
@@ -883,11 +968,12 @@ describe('approved Admin density ownership', () => {
|
||||
it('keeps the collection monitor in the Admin theme without legacy list controls', () => {
|
||||
const page = read('modules/self-operated/pages/CollectionView.vue')
|
||||
const monitor = read('modules/self-operated/components/CollectionAccountMonitor.vue')
|
||||
expect(page).toContain('class="admin-density"')
|
||||
expect(page).toContain('class="admin-density admin-workbench"')
|
||||
expect(page).toContain('@/styles/adminDensity.css')
|
||||
expect(page).toContain('@/styles/adminWorkbench.css')
|
||||
expect(page).toContain('<CollectionAccountMonitor')
|
||||
expect(page).not.toContain('<DataTable')
|
||||
expect(monitor).toContain('background: var(--el-bg-color)')
|
||||
expect(monitor).toContain('workbench-panel')
|
||||
expect(monitor).not.toMatch(/--el-[\w-]+\s*:/)
|
||||
})
|
||||
it('opts the confirmed self-operated pages into integrated text actions without changing older outlined consumers', () => {
|
||||
@@ -940,6 +1026,8 @@ describe('approved Admin density ownership', () => {
|
||||
})
|
||||
expect(rules.get('.admin-density .el-table__body tr.el-table__row--striped td.el-table__cell')?.background).toBe('var(--admin-row-stripe)')
|
||||
expect(rules.get('.admin-density-dialog .el-descriptions__label.el-descriptions__cell')?.background).toBe('var(--admin-label-bg)')
|
||||
expect(rules.get('.admin-density-dialog .el-form--inline .el-form-item__label')?.['align-items']).toBe('center')
|
||||
expect(rules.get('.admin-density-dialog.el-dialog.admin-density-workspace > .el-dialog__body')?.flex).toBe('1 1 auto')
|
||||
for (const tone of ['warning', 'purple', 'primary', 'success', 'danger']) {
|
||||
expect(rules.get(`:is(.admin-density, .admin-density-dialog) .density-action[data-tone="${tone}"]`)?.['--action-hover-bg']).toBe(`var(--admin-action-${tone}-hover)`)
|
||||
}
|
||||
@@ -1055,6 +1143,7 @@ describe('approved Admin density ownership', () => {
|
||||
expect(read('modules/loading-lists/components/LoadingListsView.vue')).toContain('class="business-page loading-lists-page admin-density"')
|
||||
expect(read('modules/loading-lists/components/PalletLabelPrintDialog.vue')).toContain("'admin-density-dialog': dense")
|
||||
expect(read('modules/container-loading/components/ContainerSimulationCreate.vue')).toContain("'admin-density-dialog': dense")
|
||||
expect(read('modules/container-loading/components/ContainerSimulationCreate.vue')).toContain("dense ? 'min(1000px, calc(100vw - 28px))' : 'min(560px, calc(100vw - 28px))'")
|
||||
for (const file of ['loading-lists/components/LoadingListDetailDrawer.vue', 'loading-lists/components/PalletLabelPrintDialog.vue', 'container-loading/components/ContainerSimulationCreate.vue']) {
|
||||
const template = parse(read(`modules/${file}`)).descriptor.template!.ast!
|
||||
const visit = (nodes: typeof template.children) => {
|
||||
@@ -1123,7 +1212,12 @@ describe('approved Admin density ownership', () => {
|
||||
expect(source).toContain('density-table density-table--editable dispatch-create-table')
|
||||
expect(source).toContain('<DispatchResourceFields continuous')
|
||||
expect(source).toContain('label-position="left" label-width="130px"')
|
||||
for (const tone of ['summary', 'source', 'work']) expect(source).toContain(`data-tone="${tone}"`)
|
||||
expect(source).toContain('class="density-dialog-section dispatch-setup"')
|
||||
expect(source).toContain('class="density-dialog-section dispatch-draft-toolbar"')
|
||||
expect(source).toContain('class="density-form dispatch-setup-fields"')
|
||||
expect(source).not.toContain('data-tone="work"')
|
||||
expect(source).not.toContain('data-tone="summary"')
|
||||
expect(source).not.toContain('data-tone="source"')
|
||||
expect(source).toContain('class="cargo-workspace"')
|
||||
expect(source).toContain('<LineClampText')
|
||||
expect(source).toContain('class="dispatch-source-group"')
|
||||
@@ -1233,7 +1327,7 @@ describe('approved Admin density ownership', () => {
|
||||
it('keeps discard readonly sections and confirmation compact while retaining photo geometry', () => {
|
||||
const content = read('modules/overseas-warehouse/pages/CargoDiscardsView.vue')
|
||||
const dialog = content.slice(content.indexOf('<AppDialog'))
|
||||
expect(dialog).toContain('class="admin-density-dialog"')
|
||||
expectWorkbenchDialogs(content)
|
||||
expect(dialog).toContain('fullscreenable')
|
||||
expect(dialog).toContain('920px')
|
||||
expect(dialog).toContain('data-tone="summary"')
|
||||
@@ -1242,7 +1336,9 @@ describe('approved Admin density ownership', () => {
|
||||
expect(dialog).toContain('preview-teleported')
|
||||
expect(dialog).toContain('<LineClampText')
|
||||
expect(dialog).not.toContain('<el-timeline')
|
||||
expect(content).toContain("customClass: 'admin-density-confirm'")
|
||||
const confirmations = confirmationClasses(content)
|
||||
expect(confirmations).toHaveLength(1)
|
||||
expect(confirmations[0]).toEqual(expect.arrayContaining(['admin-density-confirm', 'admin-workbench', 'is-dialog']))
|
||||
expect(content).toContain('height: 150px')
|
||||
const styles = parse(content).descriptor.styles.map(style => style.content).join('\n')
|
||||
expect(styles).not.toMatch(/background:|border-left:|font-size:|border-radius:/)
|
||||
@@ -1250,14 +1346,16 @@ describe('approved Admin density ownership', () => {
|
||||
it('keeps overseas location editing and native confirmations on the shared dialog contract', () => {
|
||||
const content = read('modules/overseas-warehouse/pages/LocationsView.vue')
|
||||
const dialog = content.slice(content.indexOf('<AppDialog'))
|
||||
expect(dialog).toContain('class="admin-density-dialog"')
|
||||
expectWorkbenchDialogs(content)
|
||||
expect(dialog).toContain('fullscreenable')
|
||||
expect(dialog).toContain('density-table density-table--editable')
|
||||
expect(dialog).toContain('label-position="left" label-width="110px" :disabled="formLocked"')
|
||||
expect(dialog).toContain('data-tone="work"')
|
||||
expect(dialog).not.toContain('label-position="top"')
|
||||
expect(content).not.toContain('editor-grid')
|
||||
expect(content.match(/customClass: 'admin-density-confirm'/g)).toHaveLength(2)
|
||||
const confirmations = confirmationClasses(content)
|
||||
expect(confirmations).toHaveLength(2)
|
||||
for (const classes of confirmations) expect(classes).toEqual(expect.arrayContaining(['admin-density-confirm', 'admin-workbench', 'is-dialog']))
|
||||
expect(parse(content).descriptor.styles).toHaveLength(0)
|
||||
})
|
||||
it('keeps overseas pallet editing on one shared continuous table with native fullscreen', () => {
|
||||
@@ -1426,4 +1524,16 @@ describe('approved Admin density ownership', () => {
|
||||
expect(customs).toContain('class="confirmation-history-note"')
|
||||
})
|
||||
|
||||
it('keeps container detail spacing compact and uses shared table styling for dense fulfillment records', () => {
|
||||
const detail = read('modules/container-loading/pages/ContainerDetailView.vue')
|
||||
const carrier = read('modules/port-schedules/components/CarrierScheduleQueryPanel.vue')
|
||||
expect(detail).toContain('<AdminPage spacing="compact" class="container-detail-page admin-density admin-workbench">')
|
||||
expect(detail).toContain('class="density-element-tabs" @tab-change="rememberWorkbenchTab"')
|
||||
expect(detail).toContain('<header class="detail-section__heading"><h2 id="container-voyage-heading">船名航次信息</h2><ContainerPortSchedulePanel')
|
||||
expect(carrier).toContain('class="fulfillment-table density-table"')
|
||||
expect(carrier).toContain('v-if="dense && fulfillmentEvents.length"')
|
||||
expect(carrier).toContain('v-else-if="fulfillmentEvents.length" class="fulfillment-timeline"')
|
||||
expect(carrier).not.toMatch(/\.fulfillment-table\s+[^{}]*\{[^{}]*(?:font-size|background|padding|border):/)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user