Files
tms-erp-web/.workbuddy/memory/2026-08-21.md
T
gxwebsoft 039a08a86a feat(settlement): 优化“正式结算”和“运输对账”页面表格结构及样式
- 将正式结算页面中的表格及工具栏整体封装为子组件 formal-settlement-table-panel
- 正式结算页通过 tabs 展示应付/应收,分别引入封装表格组件,保证功能完整性和切换时的数据刷新
- 正式结算表格子组件支持行操作、工具栏按钮和分页,提升代码复用和维护性
- 运输对账页面同样改用 transport-reconciliation-table-panel 封装表格与工具栏
- 调整预结算单弹窗“结算汇率”输入框为左对齐,改善字段显示
- 清理有关表格页面的旧样式与冗余代码,确保样式统一
- 修改本地开发服务器端口及代理配置,切换到 2889 端口并更新代理目标地址
2026-08-21 14:37:36 +08:00

109 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-08-21
## process-config 弹窗卡片间隔(对齐 project-apply 风格)
- 需求:process-config 新增/编辑弹窗内三张 `<section-card>`(基本信息 / 现行过程节点 / 节点设置)要像 project-apply 表单页一样独立成卡、卡间露出灰底(12px)。
- 根因:全站规则 `.el-dialog .avue-form { background:#fff; padding:8px 16px 4px }`element-ui.scss ~246 行)把 Avue 弹窗表单整体包成一张白卡,section-card 白卡叠在其上看不出间隔。
- 改动(仅 2 文件):
1. `src/option/business/process-config.js`option 顶层加 `dialogCustomClass: 'process-config-dialog'`
2. `src/styles/element-ui.scss`contract-manage-dialog 规则块后新增):
- `.process-config-dialog .avue-form { background:transparent; box-shadow:none; padding:0 }` —— 白卡透明化,灰底(.el-dialog__body 全局 #f2f2f2)露出,section-card 自带 margin-bottom:12px 形成卡距。
- `.process-config-dialog .avue-form__group > .el-col > .el-form-item { margin-bottom:0 }` —— formslot 外层 form-item margin 与卡片 margin 叠加会拉大卡距,归零统一 12px。
- `.process-config-dialog .avue-dialog__footer` + `.avue-crud__dialog .process-config-dialog .avue-dialog__footer { margin-top:0 !important }` —— 抵消全局 947 行 `.avue-crud__dialog .avue-dialog__footer { margin-top:-30px !important }`(form 透明化后会上移压卡)。双选择器兼顾 dialog 未 teleport / teleport 两种挂载。
- 已验证:Vite 2889 编译通过、HMR 生效。
- 备注:`menu-form-before` 插槽(保存草稿/保存并启用按钮)渲染在 `.avue-dialog__footer` 内(avue 源码 dialog-form3.mjs 确认),不受 form 透明化影响,仍处白底底栏。
## 合同管理表单页:多分组卡片风格(对齐 project-apply 风格)
- 需求:合同管理新增/编辑表单页(`/business/contract-manage/form?mode=add|edit`)的 7 个业务分组(基本信息 / 合同文件 / 计费信息 / 结算单规则 / 付款比例设置 / 其它附件 / 变更记录)要像 project-apply 一样独立成白底卡、卡间 12px 间距、标题 4px 主色蓝条。
- 关键事实(容易踩坑):
- 合同表单走 `PageAvueForm` 组件(`src/views/business/components/business-crud-page.vue:5577`),render 函数 `h('div', { class: option.dialogCustomClass }, [h('avue-form', ...)])`**不包 el-dialog**(所以底部按钮天然不浮动贴底,会随内容滚动——这点与 project-apply 的 el-dialog #footer 浮动有差异)。
- `option` 顶层在 `isStandaloneFormPage` 时已设 `dialogCustomClass: 'contract-manage-form-dialog'``dialogAppendToBody: false``dialogModal: false``dialogTop: '0'``dialogWidth: '100%'`5897-5914 行)。
- 7 个分区标题列在 option.column 里以 `order` 升序分块(`basicInfoTitle=200``contractFileTitle=30``billingInfoTitle=10``settlementRuleTitle=-10``paymentRatioTitle=-30``attachmentTitle=-50``changeRecordTitle=-70`),其余字段 order 在每对标题列之间。
- 实施方案(已提交 63256a9):
1. `buildContractFormGroupOption(option)`business-crud-page.vue 新增方法):按 order 降序遍历 option.column,遇到 7 个 `*Title` 列就切片分组;`groups.length<=1` 时回退原 option(不影响其他业务弹窗)。返回 `{ ...option, column: groups[0], group: groups.slice(1).map(g=>({ label:'', arrow:false, column:g })) }`
2. `pageFormOption`6205 行)`isContractFormPage` 时调用上述方法。
3. CSSbusiness-crud-page.vue scoped 末尾):
- `.contract-manage-form-dialog``padding:20px 24px 96px; background:#f5f6fa; box-sizing:border-box;`(外层灰底)
- `.business-crud-page--contract-form .avue-form { background:transparent; padding:0 }`(表单白卡透明化)
- `.business-crud-page--contract-form .avue-form > .el-form > .avue-form__group``.avue-group` 都设白底 + 6px 圆角 + 0 1px 2px 阴影 + 12px margin-bottom + 14px 16px 4px padding(两张选择器分别覆盖第 1 组 column 与第 2-7 组 group 渲染)
- 验证(agent-browser + 系统 Chrome,已登录后截图核对):
- 合同表单 7 张白底卡清晰分隔,每张卡左侧 4px 主色蓝条 + 标题(基本信息 / 合同文件 / 计费信息 / 结算单规则 / 付款比例设置 / 其它附件 / 变更记录),卡间约 12px 灰底露白。
- 底部 5 个按钮(提交 / 关闭 / 保存 / 提交临时合同 / 提交正式合同)随内容滚动(非浮动贴底)。
- 与 project-apply 滚动后的"客户信息 / 承运商信息"卡风格完全一致。
- 与 project-apply 的已知差异(用户本次未要求改):
- 合同表单底部按钮非浮动贴底(PageAvueForm 不包 el-dialogavue-form 的 form_menu 渲染在内部)
- 合同表单无"返回"按钮(用"关闭"代替)
- 合同表单无独立页面标题(page-header 区域在 breadcrumb 处,不在 main 标题区)
- 行为验证码:登录页拼图/旋转求解基础设施已搭好——`/tmp/captcha_solve.py`CORS 修复后支持 puzzle+rotate 双模式)、`/tmp/ab-install/node_modules/.bin/agent-browser --browser-channel chrome`。登录流程:访问 → 切"账号密码登录" → 点登录 → 检测 `.puzzle-stage`/`.rotate-image` → POST 至 http://127.0.0.1:8765 → 取 xDisp/angle → JS PointerEvent 模拟拖动 .track-handle 即可。
- 提交:63256a9 feat(business-crud-page): 合同管理表单页改为多分组卡片风格(1 file, +86/-2)。未提交改动(process-config.js、element-ui.scss、master-order-editor.vue、loading-manage.vue、project-apply.vue、formal-settlement.vue、customer-archive.vue)与本任务无关,未纳入。
## shipping-template 独立表单页加 archive-page-form__title(参考 customer-archive
- 需求:独立表单页 `/business/shipping-template/form?mode=add&name=新运费发货模板` 顶部缺页面标题,参考 customer-archive 的 `.archive-page-form__title` 加标题。
- 改动(单文件 `src/views/business/components/business-crud-page.vue`):
1. `PageAvueForm`5578 行)声明 `props.formPageTitle`render 时若非空则先 push `<div class="archive-page-form__title">{{ title }}</div>` 再渲染 avue-formtitle 在表单容器 `shipping-template-dialog` 内、avue-form 之前)。
2. 模板 `<component :is="crudContainer">` 新增 `:form-page-title="isStandaloneFormPage ? formPageTitle : undefined"`
3. 新增 computed `formPageTitle()``isStandaloneFormPage && isShippingTemplatePage` 时返回 `this.$route.query.name || '新增'/'编辑' + config.title`,否则 ''。
4. 样式(scoped 末尾,用 `:global` 因为 title div 由 PageAvueForm 函数式组件渲染、无 scoped 属性):`:global(.business-crud-page--form-page .archive-page-form__title)` 复制 customer-archive 的 18px/600/#303133 + margin-bottom:20px::before 为空,与参考一致,仅纯文字标题)。
- 仅作用于 shipping-template 独立表单页;其他独立表单页(waybill/transport-plan/contract`formPageTitle` 返回 '',不受影响。
## transport-plan 独立表单页也加 archive-page-form__title
- 需求:`/business/transport-plan/form?mode=add&name=新运费运输计划` 也要同样的页面标题。
- 改动:`formPageTitle()` 条件由 `isStandaloneFormPage && isShippingTemplatePage` 改为 `isStandaloneFormPage && (isShippingTemplatePage || isTransportPlanPage)`(复用已有 `isTransportPlanPage` computed`config.permission==='transport_plan'`)。标题文案取 `this.$route.query.name`(「新运费运输计划」)或回退「新增/编辑运输计划」。
- 验证:Vite 2889 编译通过(HTTP 200,无错误)。
- 验证:Vite 2889 编译通过(HTTP 200,无 transform/syntax 错误),HMR 生效。如需扩展到其他独立表单页,去掉 `isShippingTemplatePage` 限定即可。
## 将 .archive-page-form__title 全局化,并再加 waybill / loading-manage / master-order 三页
- 需求:把页面标题扩展到 `/business/waybill-manage/form``/business/loading-manage/form``/business/master-order?mode=editor` 三页,并与 customer-archive / shipping-template / transport-plan 视觉统一。
- **全局化样式**`.archive-page-form__title` 原本分散在 `customer-archive.vue`scoped)与 `business-crud-page.vue``:global`,::before 为空纯文字)。现统一提取到 `src/styles/element-ui.scss`5b 段):18px/600/#303133 + margin-bottom:20px + `::before` 4px 主色竖条 + 8px 间距(补全竖条,与 section-card 卡头风格一致)。并删除上述两处本地重复定义。
- **waybill-manage/form**:在 `business-crud-page.vue``formPageTitle()` 条件再并入 `isWaybillDetailLayout``config.permission==='waybill_manage'`),复用既有 computed。标题取 `query.name || '新增/编辑运单管理'`
- **loading-manage/form**:该路由直接映射到 `loading-manage.vue`(非 business-crud-page)。新增 computed `formPageTitle()``query.name || '新增/编辑配载管理'`),并在独立表单页的 `<component>` 内、body 之前加 `<div v-if="isStandaloneFormPage" class="archive-page-form__title">{{ formPageTitle }}</div>`
- **master-order?mode=editor**`master-order.vue` 渲染 `master-order-editor.vue`。将 `<master-order-editor>` 包进 `<template v-else-if="mode==='editor'">`,前置 `<div class="archive-page-form__title">{{ masterEditorTitle }}</div>`;新增 computed `masterEditorTitle``routeId ? '编辑总单' : '新增总单'`)。
- 验证:4 个 SFC + element-ui.scss 经 Vite 2889 编译均 HTTP 200、无 transform/syntax 错误。
## 综合台账弹窗 & 临时额度查看弹窗 布局调整
- vehicle-ledger / ship-ledger/transportCapacity 车辆·船舶综合台账弹窗):把 `<el-table>`+分页从 `el-tabs` 外移入每个 `<el-tab-pane>` 内(切换 tab 表格跟着切换);ship-ledger 同步把三个蓝标内容块(船舶基本信息/船舶证书信息/证书附件)由 `<section>`+`.dialog-section-title` 改为全局 `<section-card :title>`,卡片间距 12px。两文件均加 `:deep(.el-tabs__content){padding:0}` 去 border-card 默认内边距。
- 临时额度查看弹窗改两列(/business/temporary-credit-limit):
- 原"查看"调 Avue 内置 `rowView`(列数复用 column.span,呈 3 列)。改用 business-crud-page 内置自定义详情弹窗。
- `src/option/business/temporary-credit-limit.js` config 加 `detailButton:true``detailButtonIgnoreDraftStatus:true``detailSections:[申请信息(申请单号/备注 span:2 整行,其余两列)、额度信息]`
- `business-crud-page.vue``showDetailButton``if(this.config.detailButtonIgnoreDraftStatus) return true`(仅放开草稿态也走自定义详情,不动其他页面)。
## contract-manage/form 独立表单页也加 archive-page-form__title
- 需求:`/business/contract-manage/form?mode=add&name=新运费合同管理` 也要同样顶部页面标题。
- 改动:`business-crud-page.vue``formPageTitle()` 条件再并入 `isContractConfig``config.permission==='contract_manage'`contract-manage 已用 `contract-form-page` prop 走 `PageAvueForm`)。标题取 `query.name`(「新运费合同管理」)或回退「新增/编辑合同管理」。
- 验证:Vite 2889 编译通过(HTTP 200,无错误),HMR 生效。至此 business-crud-page 系列(shipping-template / transport-plan / waybill-manage / contract-manage)独立表单页均已带统一标题。
- 渲染走 `detailSections` 分支(`section-card` + `el-descriptions(:column=2)`),值经 `formatDetailValue` 转字典 label。
- 验证:`temporary-credit-limit.js``node --check` 语法通过;business-crud-page.vue 仅 template 表达式改动。待用户在 2889 刷新核对两列效果。
## 合同管理详情弹窗 label 对齐修复
- 需求:`/business/contract-manage` 详情弹窗里两列 `el-descriptions` 的 label(尤其右边列 label)对齐不一致,长 label(如"是否需要加盖法人章")换行后行高/垂直位置错乱。
- 根因:`business-crud-page.vue``&__detail-content .section-card` 中对 `.el-descriptions__label` 只写了 `width: 140px``text-align: right`,缺 `min/max-width``vertical-align``line-height``box-sizing`;对 `.el-descriptions__content` 也缺垂直对齐,导致跨列/跨行 label 视觉上不齐。另外 `contract-manage.vue` 底部的 `<style>`(未加 `scoped`)把 `.el-dialog .el-form-item__label``.el-col` 全局覆盖,会污染全站弹窗。
- 改动:
1. `src/views/business/components/business-crud-page.vue`15440 行附近):
- label 与 content 统一加 `box-sizing:border-box``vertical-align:middle``line-height:1.4`、一致 paddinglabel 加 `min-width:140px; max-width:140px` 防止被内容撑开或压缩,content 保持 `min-height:42px`
- **新增 `:deep(.el-descriptions__table) { width:100%; table-layout:fixed }`**:强制表格按固定列宽渲染,label 占 140px 后,左右两个 content 列均分剩余宽度,解决用户截图里"合同期限"卡片左右内容区宽度不一致的问题。
2. `src/views/business/contract-manage.vue`:把底部无 scoped 的全局样式改为 `<style scoped>`,并把选择器限定到 `.contract-manage-dialog`;删除污染性更强的 `.el-col { margin-bottom:0 !important }` 全局覆盖。
- 验证:Vite 2889 编译通过(HTTP 200),HMR 生效。待用户在 2889 刷新核对详情弹窗两列 label 是否左右/上下对齐、左右内容区宽度是否均等。
## 应付明细调整弹窗:控件撑满单元格 + 表头居中
- 需求:`/settlement/payable-detail`(即 `receivable-payable-detail.vue`)"调整费用"弹窗中,里程 / 杂项 / 装卸费等列的 `el-input-number` 默认宽度 180px,超出窄列后被截断(见截图);同时要求所有表头居中。
- 改动(单文件 `src/views/settlement/receivable-payable-detail.vue`):
1. 给调整弹窗 `<el-table>``class="settlement-detail-page__adjust-table"`
2. 页面级表格样式 `.settlement-detail-page__table, .settlement-detail-page :deep(.el-table)``th.el-table__cell` 增加 `text-align: center !important;`,统一所有表头居中(覆盖金额列 `align: right` 导致的表头右偏)。
3. 新增 `.settlement-detail-page__adjust-table` 样式块:`.el-input-number``.el-input``.el-select` 全部 `width: 100% !important;`,使控件撑满单元格不被截断;`el-input-number` 内部输入保持右对齐。
- 验证:Vite 2889 编译通过(HTTP 200),HMR 生效。待用户在 2889 刷新核对调整弹窗输入框是否完整显示、表头是否全部居中。
## formal-settlement:把表格放进 tabs
- 需求:`/settlement/formal-settlement` 原本 `el-tabs`(应付/应收) 是空的 type 切换器,表格+工具栏在 tabs 外面;要求把表格放进 tabs 内。
- 改动:
1. 新建 `src/views/settlement/components/formal-settlement-table-panel.vue`:把工具栏(新增/付款申请/同步金蝶/打印结算单/导出 + 刷新) + `el-table` + 分页整体抽成子组件;props 收 `rows/columns/loading/page/hasPermission`emits `create/payment/sync/export/refresh/page-change/update:selection/action`;行操作(查看/编辑/删除/提交/通过/驳回/作废)经 `rowActions(row)` 计算可见项后 emit `action {type,row}`;工具栏"打印"经 `emitSingle('print')` 取选中单行后 emit action(与父 `selectedOne` 行为一致)。
2. `src/views/settlement/formal-settlement.vue`:删除原 toolbar+table+pagination 块与对应 scoped 样式(`__toolbar/__toolbar-right/__links/__pagination`),在 `el-tabs` 两个 `el-tab-pane` 内各放一个 `<formal-settlement-table-panel>`DRY,共用同一组件);新增 `handlePageChange({current,size})``handleAction({type,row})` 分发行操作;`handlePrint(row)` 改为接收行参数(不再用 selectedOne);删除无用 `handleSizeChange`
- 验证:Vite build 通过(EXIT=0),无编译错误。待用户在 2889 刷新核对:应付/应收两个 tab 各自带完整表格与工具栏、切换 tab 触发 reload。
## 预结算单结算汇率输入框居左
- 需求:`/settlement/pre-settlement` 弹窗中「结算汇率」字段(el-input-number)默认居中,要求改为居左。
- 改动:
1. `src/option/settlement/preSettlementForm.js``exchangeRate` 字段新增 `class: 'exchange-rate-input'`
2. `src/views/settlement/components/pre-settlement-editor.vue`
- `el-input-number` 上绑定 `:class="field.class"`
- scoped style 的 `&__form` 内增加 `:deep(.exchange-rate-input .el-input__inner) { text-align: left; }`
- 影响:仅针对「结算汇率」字段,不改动其他数字输入框对齐方式。