Files
tms-erp-web/.workbuddy/memory/MEMORY.md
T
gxwebsoft 3e7110ca8c fix(waybill-manage): 修复运单详情弹窗残留问题
- 页面形态状态(列表/独立表单页/独立详情页)在实例创建时锁定,避免随路由变化切换导致弹窗残留
- 模板中形态相关所有判定改为使用锁定状态变量,保证渲染一致性
- 修改 detailContainer、crudContainer、pageFormOption 等方法使用锁定状态,避免缓存实例 option 变形
- 新增 closeInnerDialogs 方法,在组件 deactivated 和 beforeUnmount 生命周期关闭所有 append-to-body 弹窗
- 解决标签页 keep-alive 机制下弹窗 Teleport 持续遗留导致界面异常的问题
- 对运单管理页面多处弹窗和视图控制做统一修复,提升页面稳定性和体验
2026-09-18 11:17:50 +08:00

4.2 KiB
Raw Blame History

项目长期记忆(tms-erp-web-ws / Saber3

配套后端:/Users/gxwebsoft/JAVA/tms-api(不是 tms-erp-api-ws,后者功能滞后)。

列表 + 独立表单页 + 独立详情页(同一组件分流)

  • 路由:/xxx(菜单)、/xxx/form/xxx/detail 指向同一 .vueform/detail 为 component: Layout + 空 childrenmeta:{keepAlive:false}detail 带 activeMenu:'/xxx'
  • 组件内按 $route.path 分流,列表部分统一 v-if="!isStandalonePage" 隐藏。
  • 路由记录不同但组件相同 → 必须 watch:{$route} 里重新 initmounted 只覆盖直接打开/刷新。
  • 跳转 push({path:'/xxx/form',query:{mode,id,name:'新增xxx'}}),标签标题取 query.name
  • 底栏:只读详情页「关闭」;表单页「关闭/暂存/确认」。

⚠️ 独立页容器禁止用 <component :is> 在 div 与 el-dialog 间切换

  • 现象:改成独立整页后,点左侧菜单又弹出旧弹窗,且永久盖在页面上。
  • 根因src/router/tab.js 按 fullPath 建 wrapper 组件,layout.vue<keep-alive :include="tagsKeep"> 缓存,每个标签一个实例。实例被 deactivate 后仍会随 $route 重新渲染;此时 :is 由 div 变回 el-dialogv-model 仍为 trueappend-to-body 的弹窗经 Teleport 渲染进 body——而 KeepAlive.deactivate → Teleport.move 只做 reorder不会把 teleport 出去的 DOM 搬回 storage container,于是弹窗永久残留。
  • 正确写法:独立页固定 <div v-if="isXxxPage"> 普通容器,绝不按路由回退成 el-dialog;列表页分支另写或只保留弹窗一种形态。
  • 兜底:页面内其它 append-to-body 的二级弹窗,加 deactivated(){closeInnerDialogs()} + beforeUnmount(){closeInnerDialogs()} 把 v-model 置 false。
  • 已按此修法落地:loading-manage、project-apply2026-09-18)、waybill-manage-page(同日,锁 detailPage/formPage/formMode 三个标志)。
  • 未修同类风险:settlement/components/{pre,formal}-settlement-editor.vuetransport-reconciliation-editor.vuepageMode ? 'div':'el-dialog')、waybill-import-dialog.vuestandalone/createPage)。

样式硬规则

  • 底栏:flex; justify-content:flex-end不写 gap(间距靠 EP 默认 .el-button+.el-button{margin-left:12px})。浮动底栏必须 position:fixed(祖先 overflow:hidden 使 sticky 失效)+ :global(.avue--collapse .x){left:60px}:global(.avue-layout--horizontal .x){left:0}:global() 要包住整个选择器。
  • 按钮层级:次要=不写 type;中间步骤=primary plain;主操作=primary(禁绿色、禁两个蓝实心)。顺序 [辅助][取消][保存草稿][提交]
  • 独立页标题 .archive-page-form__title18px/600 + 4px 主色竖条);分组用全局 <section-card>;弹窗灰底 #f5f6fa
  • 上传证件区:width:100%; max-width:240px + .el-upload{height:151px},禁写死 px。
  • ⚠️ <style scoped lang="scss"> 顶层禁 // 注释Vite5+sass 报 Unexpected '/' → 样式模块 500),顶层用 /* */
  • 其余全站细则见 src/styles/element-ui.scss 与 AGENTS.md 4.4。

表单文案

  • placeholder 只写 请输入/请选择;例外保留:请输入或选择车辆、日期区间 起/止、示例值(如:京A12345)。校验 message 必须带字段名。

复用与自检

  • business/components/business-crud-page.vueoption 经 cloneOption 克隆;独立表单页走 PageAvueForm;详情弹窗 detailButton + detailSections
  • 自检:dev(2889) 时 curl "localhost:2889/src/xxx.vue"curl "...?vue&type=style&index=0&scoped=true&lang.scss",200 通过、500 返回带堆栈错误页。
  • ⚠️ vite build 会在 src/page/login/facelogin.vue 被沙箱敏感内容保护中断(环境问题),不能作为唯一校验手段。
  • devVITE_APP_API=/api,代理 172.16.203.228:8000

导出(后端 FastExcel

  • 前端 exportColumns 后端未使用,导出列以 XxxExportExcel.java 为准。
  • BladeX BeanUtil 类型不兼容时静默跳过(Date createTimeLocalDateTime 丢值),须 Service 内 DateUtil.fromDate(...) 赋值。
  • 排查导出文件用 Python zipfilexl/worksheets/sheet1.xml