986feff7b7
- 页面形态状态(列表/独立表单页/独立详情页)在实例创建时锁定,避免随路由变化切换导致弹窗残留 - 模板中形态相关所有判定改为使用锁定状态变量,保证渲染一致性 - 修改 detailContainer、crudContainer、pageFormOption 等方法使用锁定状态,避免缓存实例 option 变形 - 新增 closeInnerDialogs 方法,在组件 deactivated 和 beforeUnmount 生命周期关闭所有 append-to-body 弹窗 - 解决标签页 keep-alive 机制下弹窗 Teleport 持续遗留导致界面异常的问题 - 对运单管理页面多处弹窗和视图控制做统一修复,提升页面稳定性和体验
35 lines
4.3 KiB
Markdown
35 lines
4.3 KiB
Markdown
# 项目长期记忆(tms-erp-web-ws / Saber3)
|
||
|
||
配套后端:`/Users/gxwebsoft/JAVA/tms-api`(不是 tms-erp-api-ws,后者功能滞后)。
|
||
|
||
## 列表 + 独立表单页 + 独立详情页(同一组件分流)
|
||
- `/xxx`、`/xxx/form`、`/xxx/detail` 指向同一 .vue;form/detail 为 `component: Layout` + 空 children、`meta:{keepAlive:false}`,detail 带 `activeMenu:'/xxx'`。
|
||
- 组件内按 `$route.path` 分流,列表部分 `v-if="!isStandalonePage"` 隐藏;路由不同但组件相同 → 必须 `watch:{$route}` 重新 init。
|
||
- 跳转 `push({path:'/xxx/form',query:{mode,id,name}})`,标签标题取 `query.name`;只读详情底栏「关闭」,表单页「关闭/暂存/确认」。
|
||
|
||
## ⚠️ keep-alive 缓存引起的两个同源坑(`tab.js` + `layout.vue`)
|
||
`tab.js` 按 fullPath 建 wrapper,`layout.vue` 用 `<keep-alive :include="tagsKeep">` 缓存,**每标签一实例且永不销毁**;实例 deactivate 后**仍会随全局 `$route` 重渲染**。由此:
|
||
|
||
**坑一:独立页容器禁止用 `<component :is>` 在 div 与 el-dialog 间切换**
|
||
- 机制:`:is` 由 div 翻回 `el-dialog` + `v-model` 仍 true + `append-to-body` → 弹窗 Teleport 进 body;`TeleportImpl.move` 忽略 `moveType`,**不会把 teleport 的 DOM 搬回 storage container** → 点左侧菜单又冒出旧弹窗。
|
||
- 修法:独立页固定 `<div v-if="isXxxPage">`;另加 `deactivated(){closeInnerDialogs()}` + `beforeUnmount()` 收起页内 append-to-body 二级弹窗(子组件里写 `deactivated` 也有效)。
|
||
- 已修:loading-manage、project-apply、waybill-manage-page(2026-09-18,后者用 `formPageLocked/detailPageLocked/formModeLocked` 锁形态)。未修:`settlement/components/{pre,formal}-settlement-editor.vue`、`transport-reconciliation-editor.vue`、`waybill-import-dialog.vue`。
|
||
|
||
**坑二:宿主 view 把全局 `$route.query.*` 直接绑给子组件 prop**
|
||
- 现象:打开 A 页详情却弹「运单管理不存在」这类**用错 id** 的后端报错(可重复多条),还莫名多出别的标签。
|
||
- 机制:`waybill-manage-detail.vue` 写 `:detail-id="$route.query.id"` → 旧缓存实例把「当前页的 id」灌进来 → 触发 `openDetail` → 用别人的 id 查自己的接口 → 后端「XX 不存在」→ 全局 axios 拦截器红字弹出(几个旧标签就几条)。其 `isStandaloneXxxPage` 是 live computed(false) → 还会误 `push` 出新标签。
|
||
- 修法:`created()` 锁 `routePathLocked = $route.path`,watcher/跳转方法先判 `if ($route.path !== routePathLocked) return;`;宿主 view 绑定也加路径守卫。
|
||
- 同理:按 id 批量查详情处(如 `restoreWaybillRows`)虽有 `.catch`,但**拦截器已弹过提示**,catch 拦不住。
|
||
## 样式硬规则
|
||
- 底栏:`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`;分组用全局 `<section-card>`;上传证件区 `width:100%; max-width:240px` + `.el-upload{height:151px}`。
|
||
- ⚠️ `<style scoped lang="scss">` **顶层禁 `//` 注释**(Vite5+sass 报 `Unexpected '/'` → 样式模块 500),顶层用 `/* */`。
|
||
- 其余细则见 `src/styles/element-ui.scss` 与 AGENTS.md 4.4。
|
||
|
||
## 表单文案 / 自检 / 导出
|
||
- placeholder 只写 `请输入`/`请选择`;例外:`请输入或选择车辆`、日期区间 `起/止`、示例值。校验 message 必须带字段名。
|
||
- `business-crud-page.vue`:option 经 `cloneOption` 克隆,独立表单页走 `PageAvueForm`。
|
||
- 自检:dev(2889) 时 `curl "localhost:2889/src/xxx.vue"` 与 `"...?vue&type=style&index=0&scoped=true&lang.scss"`,200 通过、500 报错。`vite build` 会在 `facelogin.vue` 被沙箱中断,不能作唯一校验。dev:`VITE_APP_API=/api`,代理 `172.16.203.228:8000`。
|
||
- 导出:前端 `exportColumns` 后端未用,以 `XxxExportExcel.java` 为准;BladeX `BeanUtil` 类型不兼容静默跳过(`Date` → `LocalDateTime` 丢值,须 `DateUtil.fromDate(...)`)。
|