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

41 lines
4.2 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.
# 项目长期记忆(tms-erp-web-ws / Saber3
配套后端:`/Users/gxwebsoft/JAVA/tms-api`(不是 tms-erp-api-ws,后者功能滞后)。
## 列表 + 独立表单页 + 独立详情页(同一组件分流)
- 路由:`/xxx`(菜单)、`/xxx/form``/xxx/detail` 指向同一 .vueform/detail 为 `component: Layout` + 空 children`meta:{keepAlive:false}`detail 带 `activeMenu:'/xxx'`
- 组件内按 `$route.path` 分流,列表部分统一 `v-if="!isStandalonePage"` 隐藏。
- 路由记录不同但组件相同 → 必须 `watch:{$route}` 里重新 init`mounted` 只覆盖直接打开/刷新。
- 跳转 `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-dialog``v-model` 仍为 true`append-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.vue``transport-reconciliation-editor.vue``pageMode ? 'div':'el-dialog'`)、`waybill-import-dialog.vue``standalone`/`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__title`18px/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.vue`option 经 `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` 被沙箱敏感内容保护中断(环境问题),不能作为唯一校验手段。
- dev`VITE_APP_API=/api`,代理 `172.16.203.228:8000`
## 导出(后端 FastExcel
- 前端 `exportColumns` 后端未使用,导出列以 `XxxExportExcel.java` 为准。
- BladeX `BeanUtil` 类型不兼容时静默跳过(`Date createTime``LocalDateTime` 丢值),须 Service 内 `DateUtil.fromDate(...)` 赋值。
- 排查导出文件用 Python `zipfile``xl/worksheets/sheet1.xml`