From 25825685c3f78d2e45b0e7d6579843bfc77e80c7 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 14 Sep 2026 17:54:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 5 +- .../components/CustomerAuditLogsPanel.vue | 16 +- .../CustomerOverseasStorageFeePanel.vue | 6 +- .../components/CustomerBillingRulesPanel.vue | 28 +- src/modules/customers/customerDensity.css | 142 ++++----- .../customers/overseasStorageFee.test.ts | 2 +- .../customers/pages/CustomerDetailView.vue | 61 ++-- .../customers/pages/CustomersView.test.ts | 3 +- src/modules/customers/pages/CustomersView.vue | 128 ++++---- .../pages/OverseasStorageFeesView.vue | 16 +- ...mesticContainerInventoryDetailView.test.ts | 5 +- .../DomesticContainerInventoryDetailView.vue | 25 +- .../pages/DomesticContainersView.test.ts | 2 +- .../pages/DomesticContainersView.vue | 6 +- .../pages/domesticContainersSummary.css | 10 +- .../inbounds/components/InboundTaskList.vue | 21 +- .../InboundMeasurementDialog.test.ts | 5 +- .../measurement/InboundMeasurementDialog.vue | 10 +- .../InboundMeasurementPanel.test.ts | 2 +- .../measurement/InboundMeasurementPanel.vue | 78 ++--- .../measurement/measurementDensity.css | 46 +-- .../review/MeasurementReviewPanel.vue | 44 +-- .../weight/components/WeightOcrPanel.test.ts | 2 +- .../weight/components/WeightOcrPanel.vue | 40 +-- .../components/LoadingListDetailDrawer.vue | 60 ++-- .../components/LoadingListsView.test.ts | 7 +- .../components/LoadingListsView.vue | 10 +- .../components/PalletLabelPrintDialog.vue | 4 +- .../pages/PreloadPlanDetailView.test.ts | 2 +- .../pages/PreloadPlanDetailView.vue | 10 +- .../pages/UnifiedOrdersView.test.ts | 15 +- .../pages/UnifiedOrdersView.vue | 280 ++++++++---------- .../unified-orders/styles/orderDensity.css | 37 ++- .../locations/pages/LocationsView.test.ts | 16 +- .../locations/pages/LocationsView.vue | 42 ++- .../pallets/pages/PalletsView.test.ts | 12 +- .../pallets/pages/PalletsView.vue | 43 ++- src/styles/adminDensity.css | 125 +++++--- src/styles/adminDensity.test.ts | 147 +++++++++ src/styles/adminDensityTokens.css | 42 +++ 40 files changed, 850 insertions(+), 705 deletions(-) create mode 100644 src/styles/adminDensity.test.ts create mode 100644 src/styles/adminDensityTokens.css diff --git a/AGENTS.md b/AGENTS.md index ba52b116..ca1c9501 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ 1. 用“模块快速路由”选择最小业务模块,进入后读取该目录最近的 `AGENTS.md`;按 `routes.ts → pages/ → api/types/stores/composables` 下钻,不先扫描全部 `src/`。 2. 页面、布局或交互任务同时读取 `../../docs/Admin-Client前端原型还原验收规则.md` 和后台原型 `../../docs/悦/货代SAAS平台后台/AGENTS.md`。 - 订单样板和国内仓样式统一还须读取 `../../docs/Admin高密度界面规范.md`;以其已确认密度与彩色页签为视觉基线,逐操作保留业务语义和承载方式,公共样式按已确认菜单范围接入。 + 订单样板、国内仓和客户管理样式还须读取 `../../docs/Admin高密度界面规范.md`,包含“样式维护边界”;以其已确认密度与彩色页签为视觉基线,逐操作保留业务语义和承载方式,公共样式按已确认菜单范围接入。 3. 标准列表或公共组件任务读取 `src/shared/components/AGENTS.md`;国内/海外 HTTP、Token 或刷新任务读取 `src/shared/api/AGENTS.md`;Finance 任务读取 `src/modules/finance/AGENTS.md`;海外仓全流程任务先读 `../../docs/海外仓业务/README.md`。 4. 平台/客户层级与权限公共语义读取 `../../docs/平台客户层级与权限契约.md`;双区域 API、海外 Token 和跨区事件读取 `../../docs/跨区域认证与服务通信契约.md`。 @@ -106,6 +106,9 @@ ## 命令与质量门禁 +- 国内仓、客户管理密度默认值统一维护在 `src/styles/adminDensityTokens.css`,通用按钮/页签/描述表/弹框规则统一维护在 `adminDensity.css`;页面只选择公共类与语义参数、保留业务布局,不复制通用外观或在页面重新定义 `--admin-*` 默认值。修改前沿实际引用读取模块 CSS,接管后删除冲突旧声明。 +- 修改密度样式或接入消费者时更新并运行 `src/styles/adminDensity.test.ts` 维护合同;不得为通过检查删除权限、业务提交或错误处理断言。未接入菜单通过显式密度类隔离。 + 在 `apps/admin-web` 执行: ```bash diff --git a/src/modules/audit/components/CustomerAuditLogsPanel.vue b/src/modules/audit/components/CustomerAuditLogsPanel.vue index 466b7475..4bf42081 100644 --- a/src/modules/audit/components/CustomerAuditLogsPanel.vue +++ b/src/modules/audit/components/CustomerAuditLogsPanel.vue @@ -144,7 +144,7 @@ watch([page, pageSize], ([nextPage, nextSize], [previousPage, previousSize]) => - + diff --git a/src/modules/customers/CustomerOverseasStorageFeePanel.vue b/src/modules/customers/CustomerOverseasStorageFeePanel.vue index 782f9a42..2f5744c7 100644 --- a/src/modules/customers/CustomerOverseasStorageFeePanel.vue +++ b/src/modules/customers/CustomerOverseasStorageFeePanel.vue @@ -81,15 +81,15 @@ onMounted(load)
当前客户暂无海外仓费用配置
-

{{ groupIndex === 0 ? '仓租(CBM/天)' : '退货仓储费(托/天)' }} · {{ group.length }}档

新增阶梯
操作开始天数结束天数价格
删除以上
+

{{ groupIndex === 0 ? '仓租(CBM/天)' : '退货仓储费(托/天)' }} · {{ group.length }}档

新增阶梯
操作开始天数结束天数价格
删除以上
diff --git a/src/modules/domestic-containers/pages/DomesticContainersView.test.ts b/src/modules/domestic-containers/pages/DomesticContainersView.test.ts index d0488a20..fadb5e78 100644 --- a/src/modules/domestic-containers/pages/DomesticContainersView.test.ts +++ b/src/modules/domestic-containers/pages/DomesticContainersView.test.ts @@ -15,7 +15,7 @@ describe('DomesticContainersView', () => { for (const fact of ['summary.inboundBoxes', 'summary.outboundBoxes', 'summary.availableBoxes', 'summary.inboundVolumeCbm']) expect(source).toContain(fact) expect(source).toContain("import './domesticContainersSummary.css'") expect(summaryStyles).toContain('display: flex; flex-wrap: wrap') - expect(summaryStyles).toContain('font-size: 14px') + expect(summaryStyles).toContain('font-size: var(--admin-font-section, 14px)') expect(summaryStyles).not.toContain('position: absolute') }) it('does not offer an inventory detail action before an inbound has formed inventory', () => { expect(source).toContain("canViewInventory(row as ContainerOrder | InventoryRecord)"); expect(source).toContain("row.status === 'COMPLETED'") }) diff --git a/src/modules/domestic-containers/pages/DomesticContainersView.vue b/src/modules/domestic-containers/pages/DomesticContainersView.vue index 312f024e..b375a394 100644 --- a/src/modules/domestic-containers/pages/DomesticContainersView.vue +++ b/src/modules/domestic-containers/pages/DomesticContainersView.vue @@ -2,7 +2,7 @@ import '@/styles/adminDensity.css' import { computed, onMounted, reactive, ref, watch } from 'vue' import { ElMessage, type FormInstance, type FormRules } from 'element-plus' -import { Eye, Plus } from '@lucide/vue' +import { Plus } from '@lucide/vue' import { useRouter } from 'vue-router' import AdminPage from '@/shared/components/AdminPage.vue' import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue' @@ -74,7 +74,7 @@ watch([page, pageSize], load); onMounted(async () => { await Promise.all([loadWa - + diff --git a/src/modules/domestic-containers/pages/domesticContainersSummary.css b/src/modules/domestic-containers/pages/domesticContainersSummary.css index 82421555..0b979554 100644 --- a/src/modules/domestic-containers/pages/domesticContainersSummary.css +++ b/src/modules/domestic-containers/pages/domesticContainersSummary.css @@ -1,9 +1,9 @@ .domestic-containers-page .table-panel .inventory-summary { - display: flex; flex-wrap: wrap; gap: 6px 28px; margin: 0; - padding: 8px 12px; border: 0; border-bottom: 1px solid var(--cc-border); background: #fff; + display: flex; flex-wrap: wrap; gap: var(--admin-space-2, 6px) 28px; margin: 0; + padding: var(--admin-space-3, 8px) var(--admin-space-5, 12px); border: 0; border-bottom: 1px solid var(--cc-border); background: var(--admin-surface, #fff); } .domestic-containers-page .table-panel .inventory-summary > div { - display: flex; align-items: baseline; min-width: 0; gap: 8px; padding: 0; border: 0; + display: flex; align-items: baseline; min-width: 0; gap: var(--admin-space-3, 8px); padding: 0; border: 0; } -.domestic-containers-page .table-panel .inventory-summary span { color: var(--cc-muted); font-size: 12px; } -.domestic-containers-page .table-panel .inventory-summary strong { font-size: 14px; font-weight: 600; } +.domestic-containers-page .table-panel .inventory-summary span { color: var(--cc-muted); font-size: var(--admin-font-caption, 12px); } +.domestic-containers-page .table-panel .inventory-summary strong { font-size: var(--admin-font-section, 14px); font-weight: 600; } diff --git a/src/modules/inbounds/components/InboundTaskList.vue b/src/modules/inbounds/components/InboundTaskList.vue index b4612a97..b2bfce49 100644 --- a/src/modules/inbounds/components/InboundTaskList.vue +++ b/src/modules/inbounds/components/InboundTaskList.vue @@ -4,7 +4,7 @@ import '../measurement/measurementDensity.css' import { computed, onActivated, onBeforeUnmount, onMounted, ref, watch } from 'vue' import { useRouter } from 'vue-router' import { ElMessage, ElMessageBox } from 'element-plus' -import { CircleCheckBig, Eye, Ruler, SearchCheck } from '@lucide/vue' +import { CircleCheckBig } from '@lucide/vue' import { useAccessPreviewStore } from '@/core/access/accessPreview' import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam' import { listPlatformWarehouses } from '@/modules/warehouses' @@ -374,14 +374,12 @@ onBeforeUnmount(() => { disposed = true; requestSerial += 1; optionsRequestSeria diff --git a/src/modules/loading-lists/pages/PreloadPlanDetailView.test.ts b/src/modules/loading-lists/pages/PreloadPlanDetailView.test.ts index 3d0bbc0c..9904e3c2 100644 --- a/src/modules/loading-lists/pages/PreloadPlanDetailView.test.ts +++ b/src/modules/loading-lists/pages/PreloadPlanDetailView.test.ts @@ -10,7 +10,7 @@ describe('PreloadPlanDetailView prototype contract', () => { expect(source).toContain('') expect(source).toContain('@back="goBack"') expect(source).toContain("router.push({ name: 'loading-plans' })") - expect(source).toContain('@media (min-width: 1920px) { .preload-detail-page { width: 100%; max-width: none; gap: 12px; } }') + expect(source).toContain('@media (min-width: 1920px) { .preload-detail-page { width: 100%; max-width: none; gap: var(--admin-space-5, 12px); } }') expect(source).not.toContain('AppDrawer') }) diff --git a/src/modules/loading-lists/pages/PreloadPlanDetailView.vue b/src/modules/loading-lists/pages/PreloadPlanDetailView.vue index a1240fd2..18afb1d9 100644 --- a/src/modules/loading-lists/pages/PreloadPlanDetailView.vue +++ b/src/modules/loading-lists/pages/PreloadPlanDetailView.vue @@ -290,13 +290,13 @@ watch([planId, warehouseId], () => void loadDetail()) diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts index 10025636..1b2d4df4 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts @@ -6,6 +6,8 @@ import { unifiedOrderStatusOptions } from '../api/unifiedOrders' const source = readFileSync(resolve(process.cwd(), 'src/modules/unified-orders/pages/UnifiedOrdersView.vue'), 'utf8').replace(/\r\n/g, '\n') const routeSource = readFileSync(resolve(process.cwd(), 'src/modules/unified-orders/routes.ts'), 'utf8').replace(/\r\n/g, '\n') +const densitySource = readFileSync(resolve(process.cwd(), 'src/styles/adminDensity.css'), 'utf8') + describe('UnifiedOrdersView contract', () => { it('exposes desktop pallet printing only for one-click dropship orders', () => { expect(source).toContain("detail.value?.summary.fulfillmentType === 'ONE_CLICK_DROPSHIP'") @@ -637,8 +639,9 @@ describe('UnifiedOrdersView contract', () => { }) it('keeps detail tabs compact on one horizontally scrollable row', () => { - expect(source).toContain('.detail-tabs { display: flex; overflow-x: auto; overflow-y: hidden;') - expect(source).toContain('min-width: max-content; min-height: 38px; flex: 0 0 auto;') + expect(source).toContain('class="detail-tabs density-tabs"') + expect(densitySource).toContain('overflow-x: auto; overflow-y: hidden;') + expect(densitySource).toContain('min-height: var(--admin-tab-height)') expect(source).not.toContain('grid-template-columns: repeat(6, minmax(124px, 1fr))') expect(source).not.toContain('.detail-tabs { grid-template-columns: repeat(6, 132px); }') }) @@ -649,9 +652,9 @@ describe('UnifiedOrdersView contract', () => { expect(source).toContain('真实集装箱号') @@ -660,7 +663,7 @@ describe('UnifiedOrdersView contract', () => { it('uses outlined semantic buttons for row business actions while keeping detail navigation explicit', () => { const rowActions = source.slice(source.indexOf('