986feff7b7
- 页面形态状态(列表/独立表单页/独立详情页)在实例创建时锁定,避免随路由变化切换导致弹窗残留 - 模板中形态相关所有判定改为使用锁定状态变量,保证渲染一致性 - 修改 detailContainer、crudContainer、pageFormOption 等方法使用锁定状态,避免缓存实例 option 变形 - 新增 closeInnerDialogs 方法,在组件 deactivated 和 beforeUnmount 生命周期关闭所有 append-to-body 弹窗 - 解决标签页 keep-alive 机制下弹窗 Teleport 持续遗留导致界面异常的问题 - 对运单管理页面多处弹窗和视图控制做统一修复,提升页面稳定性和体验
4.3 KiB
4.3 KiB
项目长期记忆(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为准;BladeXBeanUtil类型不兼容静默跳过(Date→LocalDateTime丢值,须DateUtil.fromDate(...))。