20260802220544

This commit is contained in:
oneao committed 2026-08-02 22:05:44 +08:00
1 parent c00329b5a4
commit 4fc9040a8a
60 files changed
+6273 -908

No files matched your search

+166
View File
@@ -0,0 +1,166 @@
# 2026-08-02
## 项目分析 + Skill 创建
- 深入分析了 fms-api(Spring Boot + SQL Server 通用数据接口)和 fms-vue(Vue 3 + antdv-next)的完整架构
- 创建了项目级 CodeBuddy Skill:`fms-dev`,位置 `.workbuddy/skills/fms-dev/`
- Skill 包含:
- `SKILL.md` — 开发模式速查(后端 3 种模式、前端 4 种页面模式、迁移脚本模板、踩坑清单、后端/前端代码约定、多语言规范)+ **ERP 前端样式规范**(三条禁令、间距/颜色/字体体系、弹窗规则、组件选型表,共 8 个子章节)
- `references/schema.md` — 模块管理六表 + 扩展配置表完整 schema
- `references/api-reference.md` — 所有通用端点详细参数文档
## fms-file 组件 UI 重构
- 第一次误删了卡片网格和预览面板,用户指出只要改 UI 风格不要砍功能 → 回退后重新改造。
### 正确改造(保留全部功能,仅调 UI)
**FileCard.vue** — 缩略图 110→80px,背景 gradient→纯色,去掉 transition/box-shadow/backdrop-filter/hover 遮罩,按钮始终可见,选中态改用 1px 描边
**FilePreviewPanel.vue** — 工具栏 44→36px,背景色调浅,图片去阴影、图标缩 96→72px
**FileListPanel.vue** — Header/Footer 44→36px,grid gap 12→8px,padding 收紧
**FmsFile.vue** — 三面板 default-size 各缩 10%(240→220, 700→660),border-radius 6→4px
**FmsFileModal.vue** — 宽 1400→1200px,高 620→580px,标题改"附件管理"
**Dashboard** — 演示按钮文案更新
- 编译验证通过(vite build: 833ms, 0 errors)。
### 追加:卡片/列表双模式 + 缩略图自适应
**FileCard.vue** — `object-fit: cover` → `contain`,图片在固定卡片尺寸内完整展示不裁剪
**FileListPanel.vue** — 新增 `viewMode`(grid/list)双模式切换:
- Header 右侧加 LayoutGrid/List 两个图标按钮,active 态高亮
- 列表模式用 `a-table`(size=small),列:文件名(可点击预览)/大小/类型(tag)/操作(下载+删除)
- 列表与卡片共享同一 `selectedFileIds`,切换模式时选中状态保持
- 列表模式待上传文件显示"待上传"tag,checkbox 禁用
- `ResizeObserver` 自适应表格滚动高度
- 编译验证通过(vite build: 822ms, 0 errors)
### 追加:Modal 百分比布局 + 待上传文件 checkbox
**FmsFileModal.vue** — 宽度 `80%`,高度 `calc(70vh - 55px)`,自适应屏幕分辨率
**FileCard.vue** — 去掉待上传文件 checkbox 的 `v-if="!isPending"` 限制,待上传文件也显示 checkbox
**FileListPanel.vue** — 修复 5 处阻止待上传文件选中的逻辑:
- `allChecked` 基于全部 `displayFiles` 而非仅 `uploadedFiles`
- `listRowSelection` 去掉 `disabled: !!record._pending`
- `toggleAll` 全选包含待上传
- `onFileSelect` 去掉 `if (file._pending) return` 拦截
- 模板 `:selected` 去掉 `!f._pending &&` 条件
- `deleteSelected` 拆分为已上传(调接口)和待上传(从队列移除),降序删除防索引漂移
- 编译验证通过(vite build: 792ms, 0 errors)
### 追加:UI 优化(按钮默认大小、模式切换右移、空状态居中、拖拽/粘贴/点击上传)
- 所有按钮去掉 `size="small"`(FileListPanel header/footer/列表 + FileCard 删除/下载),header/footer 高度 36→40px
- 模式切换按钮移到 header 最右侧(位于删除按钮之后)
- 空状态仅显示"暂无相关文件"居中,去掉"选择文件"按钮和 `#description` 模板
- 新增拖拽上传:`fl-main` 区域监听 dragenter/dragover/dragleave/drop,含蓝色虚线遮罩提示"释放文件到此处"
- 新增粘贴上传:`document.addEventListener("paste", handlePaste)` 检测剪贴板文件
- 提取 `addFiles(fileList)` 统一处理点击/拖拽/粘贴文件的入队逻辑
- 编译验证通过(vite build: 783ms, 0 errors)
### fms-file 视觉优化(frontend-design skill 驱动,用户确认"全部落地")
- 新增 `fileVisual.js`:集中 EXT_COLOR 扩展名语义配色映射、extColor/extFromName/isImageType/formatSize,消除 FileCard/FileListPanel/FilePreviewPanel 三处重复
- `main.scss` 补充令牌:`--fms-primary:#1677ff --fms-danger:#ff4d4f --fms-warning:#fa8c16`
- **令牌统一**:fms-file 全部组件硬编码灰/蓝(#e5e7eb/#fafafa/#8b8f96/#1677ff/#cf1322/#91caff)替换为 `--fms-*`,与全站设计语言对齐
- **三栏顶部对齐**:FilePreviewPanel 工具栏 36→44px;FileCategoryPanel 新增 44px"分类"标题条;三栏顶部齐平
- **FileCard 去噪音**:缩略图只留 checkbox;删除/下载改为 hover/选中才显现的底部操作条(不再四角浮动);"待上传"去掉 opacity 降透明度改左侧琥珀色边角标 + 文件名旁琥珀 tag;选中改 inset 2px 实色描边
- **彩色类型方块(签名元素)**:按扩展名语义着色(PDF红/DOC蓝/XLS绿/IMG紫/ZIP橙…),卡片缩略图、列表 ext chip、预览通用图标三处一致复用
- **间距/排版**:`.fl-main` 四边统一 12px;网格 gap 8→10px;消灭 10–11px 极小字,卡片名 13px/500、meta 12px/400;空态 height:100% 居中
- 拖拽遮罩改 `--fms-primary` 虚线 + color-mix 底色
- 编译验证通过(vite build: 769ms, 0 errors)
### fms-file 允许重复上传同一文件
- 问题:上传一次后无法再次上传相同文件。排查结论:后端 `FileService` 无任何同名去重(每次 INSERT 新 subid + UUID 磁盘名),唯一拦截点是前端 `addFiles()` 内的 `pendingFiles.some(name+size+lastModified)` 跨调用去重。
- 改动:移除 `addFiles()` 中去重比较,允许同一文件在多次独立操作(重新选/再拖一次)里反复加入待上传队列并提交。拖拽重复入栈问题此前已由 dragenter/dragleave 的 `currentTarget` 判断修好,无需保留该去重。
- 验证:vite build 756ms 0 errors。
### fms-file 修复 `--fms-border is not defined` + 删除分类标题节点
- 根因:`a-modal` 默认把内容 teleport 到 `<body>`,脱离了 `.theme-root`;而 `--fms-*` 令牌原先只定义在 `.theme-root`,导致模态框内全部令牌未定义 → 报 "--fms-border is not defined",且卡片/面板边框、颜色全部失效(这也解释了上一轮用户问"卡片怎么没边框")。
- 修复 `main.scss`:把 10 个 `--fms-*` 令牌从 `.theme-root` 提升到 `:root`,全局可用;`.theme-root` 仅保留 color/background/overflow。
- 按要求删除 FileCategoryPanel.vue 的 `<div class="fc-panel__header">分类</div>` 标题节点及其 `&__header` 样式块(该节点仅含未定义令牌引用,删除后 `fc-panel__tree` 以 flex:1 撑满,布局完整)。
- 验证:vite build 777ms 0 errors。
### fms-file 卡片删除多余黄色竖线
- 来源:FileCard.vue 的 `.fcard__stripe`(width:3px / background:var(--fms-warning) 左侧琥珀竖条,仅待上传卡片渲染),表现为多余黄色线条。
- 删除模板 `<span class="fcard__stripe" />` 节点及其 `.fcard__stripe` 样式块;待上传状态仍由「待上传」amber 文字标签(.fcard__tag)表达。
- 其余黄色(待上传 tag、ZIP/RAR ext 配色)为语义标记保留;无伪元素黄色线条。
- 验证:vite build 758ms 0 errors。
### fms-file 卡片加常驻「下载/删除/更多」操作栏
- FileCard.vue:移除原本 hover/选中才出现的半透明浮层 `.fcard__actions`;改为卡片底部常驻 `.fcard__footer` 操作栏(下载 / 删除 / 更多 三等分,顶部 1px 分隔线,删除与更多之间加竖向分隔线)。
- 「更多」用 `a-dropdown` + `a-menu`,当前含「预览」一项(可扩展);`onMoreClick` 按 menu key 分发。
- 待上传卡片:下载/更多 disabled,删除按钮文案变「移除」。
- 图标新增 Eye、ChevronDown。
- 验证:vite build 766ms 0 errors。
### fms-file 卡片底部操作栏 hover 闪烁/错位修复
- 现象:hover 卡片「下载/删除/更多」操作栏时出现闪烁、错位、疑似多出边框。
- 根因:antdv-next 按钮自带的 `::before`/`::after` 波纹伪元素 hover/点击时出现边框状残影并闪烁;按钮默认 `outline` 焦点环也表现为边框;且 `.ant-btn` 默认 `transition: all` 会在 hover 时引发微重排。
- 修复 FileCard.vue `.fcard__footer`:关闭 `.ant-btn` 的 `::before`/`::after`(`display:none !important`)、`outline:none`,固定 `box-sizing:border-box`,并将 transition 限缩为 `background-color,color`(去掉 all),hover 仅做纯背景/颜色切换。
- 验证:vite build 1.06s 0 errors。
### fms-file 卡片取消 hover 放大 + 选中去 box-shadow
- 现象:hover 卡片时看似「放大」(实为 `.fcard:hover` 边框由浅灰变蓝,视觉上像被框大);选中态 `box-shadow: inset 0 0 0 2px` 描边用户不想要。
- 改动 FileCard.vue:删除 `.fcard` 的 `transition: border-color` 与 `&:hover { border-color: primary }`(hover 不再改边框,仅 footer 按钮给反馈);`&--selected` 去掉 `box-shadow`,仅保留 `border-color: var(--fms-primary)` 纯蓝 1px 边框区分选中(不引起 1px 位移)。
- 验证:vite build 783ms 0 errors。
### fms-file 卡片操作按钮 hover 收缩修复
- 现象:hover 底部操作栏「下载/移除」按钮时感觉收缩。
- 根因:上一轮去闪烁时把按钮基线 `border` 设为 `none`(宽度 0);而 antdv 按钮默认预留 `border: 1px solid transparent`,hover 时边框宽度被补回 → `box-sizing:border-box` 下内容区被挤 1px,视觉收缩。
- 修复 FileCard.vue `.fcard__footer`:基线改为 `border: 1px solid transparent` 恒定预留;hover 显式 `border-color: transparent`;分隔线按钮仅改 `border-left-color`,宽度始终恒定,不再收缩。
- 验证:vite build 778ms 0 errors。
### fms-file 空状态「暂无相关文件」垂直水平居中(两次修正)
- 现象:空状态仅在自身盒子内居中、贴顶,未在文件区整体垂直居中。
- 第一版(无效):`.fl-empty--fill` 改 `position:absolute; inset:0`。错误假设定位上下文是 `.fl-main`。
- 真实根因(查 antdv 编译 CSS 确认):`.ant-spin-container` 默认 `position:relative` 且高度 `auto`。空状态绝对定位就近解析到 `.ant-spin-container`(而非 `.fl-main`),而它高度 auto → inset:0 只填满内容高度,仍贴顶。
- 正确修复:在 `.fl-spin` 中追加 `:deep(.ant-spin-container){ height:100% }`,让容器撑满(高度链:`.fl-main`确定高 → `.ant-spin`/`.fl-spin` height:100% → `.ant-spin-container` height:100%),空状态 inset:0 才真正铺满文件区并居中。`.fl-empty--fill` 保持 `position:absolute; inset:0`。
- 教训:antdv `a-spin` 的 `.ant-spin-container` 自带 relative + auto 高度,绝对定位子元素会被它截胡,必须显式撑满该容器。
- 验证:vite build 758ms 0 errors。
### fms-file toolbar 重构:下载/删除移到左侧 + 模式切换改 a-segmented 图标模式
- FileListPanel.vue header:把「下载」「删除」两个按钮从右侧(spacer 之后)移到「全选」checkbox 之后(左侧);`fl-header__spacer`(flex:1)保留在按钮之后、把右侧推给模式切换。
- 右侧模式切换:去掉原先两个 `a-button`+`a-tooltip` 文字按钮,改为 `a-segmented`(`v-model:value="viewMode"`、`:options="modeOptions"`、`size="small"`);`modeOptions` 仅含 `{ value, icon }`(grid→LayoutGrid、list→List),不含 label → 仅图标。
- 脚本:`import { h } from "vue"`,`modeOptions` 用 `() => h(LayoutGrid,{size:14})` 渲染图标项(antdv-next 1.4.2 的 Segmented 支持 options 的 icon 字段,无 label 时仅渲染图标)。
- 样式:`.fl-header__modes` 去掉原 `is-active` 文字按钮激活样式,改为 `:deep(.ant-segmented-item-selected){ color: var(--fms-primary) }` 同步选中态主题色。
- 验证:vite build 798ms 0 errors。
- 后续修复:仅图标模式下 segmented 图标顶部被裁。根因:antdv `.ant-segmented-item-label` 默认 `overflow:hidden` + 基线对齐,inline svg 上移 1~2px 被裁。修复:对该 label 加 `:deep(.ant-segmented-item-label){ display:flex; align-items:center; justify-content:center; overflow:visible }`(仅作用于 `.fl-header__modes` 内 segmented)。验证 vite build 802ms 0 errors。
- **按官方写法重做**:用户要求不要特意改样式、参考 antdv 官方 Segmented 案例。改用 antdv 自带图标 `AppstoreOutlined`(grid)/`BarsOutlined`(list)(来自 `@antdv-next/icons`),`options` 直接 `icon: h(AppstoreOutlined)` 不传固定 size(图标按 1em 缩放,天然不裁切);删除上一版的 `.ant-segmented-item-label` overflow 兜底样式与选中色覆盖,回归官方无定制外观。
- 依赖处理:`@antdv-next/icons` 原先只是 antdv-next 的传递依赖(pnpm 严格模式顶层无软链,裸导入会失败),已加入 `package.json` dependencies(`^1.1.1`);本机 pnpm 不可用(`corepack pnpm install` 报 "packages field missing or empty" 环境错误),改用 PowerShell `New-Item -ItemType Junction` 把 store 内包软链到 `node_modules/@antdv-next/icons` 使其可解析。lockfile 已含该包,无需下载。验证 vite build 801ms 0 errors。
- **环境教训**:本仓库 fms-vue 用 pnpm 但本机 pnpm 跑不起来(workspace 配置报错),需要新增/链接依赖时优先用 junction 软链到 `.pnpm` store,而非强跑 pnpm install。
- **分区配色优化(fl-header/fl-footer/fp-toolbar/fp-content)**:用户反馈这些区域背景/文字色过近、边界模糊、融为一体。原状:三个工具条都用 `--fms-hover`(#f2f3f5 浅灰)、文件内容区白底、预览内容区 `--fms-bg`(#f5f7fa),不一致且灰条贴白底对比弱。改法(ERP 克制、靠对比不靠重阴影):工具条统一改白 `--fms-surface` + 1px `--fms-border` 分隔线(浮起条),内容区统一改浅灰画布 `--fms-bg`(文件区 `.fl-main` 显式加 bg,预览区 `.fp-content` 本就灰)。白条夹灰画布,层次分明且整体协调。同步把 `.fl-main--dragover` 拖拽底色从混白改为混 `--fms-bg`。验证 vite build 788ms 0 errors。
- **fl-header/fp-toolbar 高度统一 + 面板分隔**:① `fp-toolbar` height 44→48px,与 `fl-header`/`fl-footer`(均48px) 对齐;② 先给 `.fl-panel` 加了 `border-right` 做面板分隔,但用户指出不必逐个加边框,直接改 antdv splitter 分割条中线更通用。改法:撤回 `.fl-panel` 的 border-right,`FmsFile.vue` 的 `.ff-splitter` 作用域内用 `:deep` 覆盖 `.ant-splitter-bar .ant-splitter-bar-dragger::before`(及其 hover 态)的 background,由默认 `--ant-control-item-bg-hover`(近乎隐形) 改为 `var(--fms-border)`,hover 也覆盖以免悬停时分隔变淡。验证 vite build 812ms 0 errors。
- **修正:splitter 分隔线全局 scss 方案**:上一轮 scoped :deep 没生效的真因——a-splitter 渲染后 .ff-splitter 与 .ant-splitter 是同一元素(class 合并),选择器写成 .ff-splitter :deep(.ant-splitter > ...) 要求祖先-后代关系,同一节点永远匹配不上。用户要求改用全局 scss。做法:① 删除 FmsFile.vue 中失效的 :deep 块;② 在 main.scss 末尾追加全局规则,直接定位 .ant-splitter-bar .ant-splitter-bar-dragger::before(含 hover 态)background: var(--fms-border) !important。未采用全局改 --ant-control-item-bg-hover 令牌——该令牌被 19 处控件共用(级联菜单/树节点/上传列表/标签页下拉等),全局改会把这些 hover 底色全染灰,影响面过大。验证 vite build 784ms 0 errors。
- **fl-main 回白底 + 网格回两列 + 卡片操作栏纯图标**:用户反馈三处:① 文件内容区背景不必灰色,`.fl-main` background 从 `--fms-bg` 改回 `--fms-surface`(白),dragover 混色同步改 surface;② 宫格从一行三个(`repeat(3,…)`)改回一行两个(`repeat(2,…)`);③ 卡片底部操作栏(下载/删除/更多)原用中文文字按钮,等宽三列在其它语言下文字更长会撑破布局,对多语言不友好。改为纯图标按钮(Download/Trash2/MoreHorizontal,去掉文字),图标固定尺寸、等宽列不依赖文字长度,语言无关。`更多`触发器图标由 ChevronDown 换 MoreHorizontal。下拉菜单的「预览」仍为文字(菜单项属次级,不在本次操作行布局问题范围内)。验证 vite build 762ms 0 errors。
- **FmsFileModal 加边界约束**:用户确认 modal 用百分比宽高(width 80% + body height calc(70vh-55px))而非固定值,但纯百分比在超宽屏/极小屏/矮屏有坑。在 `.ff-modal` 作用域(.ant-modal)加 `max-width:1440px`(超宽封顶)、`min-width:960px`(极小屏三栏保底),(.ant-modal-body)加 `min-height:520px`(矮屏保底)。保留用户明确的 80%/70vh 不变。验证 vite build 811ms 0 errors。
- **卡片 checkbox 去重感**:用户觉得 `.fcard__check` 套层白底+阴影太重。移除该包裹层的 background(rgba白0.92) 和 box-shadow,及固定 20x20 圆角方框,改为仅绝对定位的透明壳,checkbox 直接浮在缩略图左上角。验证 vite build 790ms 0 errors。
- **fl-main 滚动失效修复**:用户反馈上传多文件后 fl-main 不出现 Y 轴滚动条、底部 padding 像失效。根因:`.fl-spin` 与 `.ant-spin-container` 都被设成 `height:100%`,把内层盒子锁死成等于 fl-main 可视高的固定盒,超长 `.fl-grid` 只是靠 `overflow:visible` 溢出绘制而不撑大盒子,fl-main(overflow:auto) 收不到超出高度 → 不滚动、底部留白也贴盒底。修复(FileListPanel.vue `.fl-spin`):① 去掉 `height:100%`,改 `min-height:100%`(内容短仍撑满、内容长自然溢出);② `.ant-spin-container` 改 `height:auto; position:static`(取消固定高度、把定位上下文让回 `.fl-main` position:relative),使空态 `.fl-empty--fill`(position:absolute;inset:0) 正确铺满居中、且 grid 溢出时由 fl-main 统一滚动。注意:改 position:static 后加载遮罩 `::after` 会绑定到 fl-main(覆盖整个文件区,属预期更佳效果);spinner 指示器 `.ant-spin-section` 仍绑定 `.ant-spin`(fl-spin, antdv 自带 position:relative) 居中。验证 vite build 793ms 0 errors。
### fms-file segmented 图标换 lucide + 居中修复 + 分隔线深浅答疑
- **segmented 图标换 @lucide/vue**:用户要求把右侧模式切换(`a-segmented`)的图标从 `@antdv-next/icons`(AppstoreOutlined/BarsOutlined) 换成 `@lucide/vue`(LayoutGrid/List)。改动 FileListPanel.vue:移除 antdv 图标导入,改用 `h(LayoutGrid,{size:16})` / `h(List,{size:16})` 渲染图标项(size:16 保证在 segmented 内尺寸合适)。验证 vite build 769ms 0 errors。
- **lucide 图标在 segmented 内顶部被裁/偏上根因与修复**:antdv `.ant-segmented-item-label` 用固定 `minHeight`+`lineHeight` 做垂直居中并带 `overflow:hidden`;而 `@antdv-next/icons` 的 svg 自带 `display:inline-block`/`vertical-align:-0.125em` 专为基线坐定,lucide 的裸 `<svg>` 无这些属性、按默认 `vertical-align:baseline` 对齐 → 顶部溢出被裁。先给 `.ant-segmented-item-icon` 加 inline-flex 居中(仍偏上,因 icon span 在 label 内仍基线对齐);最终让 `.ant-segmented-item-label` 自身 `display:flex; align-items:center; justify-content:center` 解决(此处仅放图标无文字,不影响文字模式)。
- **居中规则进 main.scss(opt-in 工具类)**:用户问是否把 `.ant-segmented-item-label{flex居中}` 写进 main.scss 全局。结论:不直接 blanket 全局——该规则本质是 lucide 裸 svg 的 workaround,全局化会影响所有(含图文/纯文字)segmented 的 `overflow:hidden` 截断与横排方式。折中:在 main.scss 末尾加 opt-in 类 `.ant-segmented.fms-seg-icon .ant-segmented-item-label{display:flex;align-items:center;justify-content:center}`,组件里去掉 scoped `:deep` 块、给 `<a-segmented>` 加 `fms-seg-icon` 类。既一处定义、零波及面,以后别处用图标模式只需加该类。验证 vite build 0 errors。
- **splitter 分隔线 vs fl-header 边框"深浅不一"答疑**:两者同用 `--fms-border`,颜色值一致,差异来自线宽+发丝线抗锯齿:分隔条中线 `.ant-splitter-bar-dragger::before` 是 2px 实心色带(splitBarSize 默认 2),fl-header 是 1px solid 发丝线——同色下实心 2px 接收更多纯色像素读起来更"实";1px 边框在 DPR=1 屏被抗锯齿淡化。Retina 下差异明显变小。结论:合理层次表现,非 bug,无需修;若强一致性可把 ::before 降 1px。
### fms-file Splitter 默认宽度(像素固定 + 预览占余)
- 用户最终确认布局:分类区固定 `220` px、文件列表固定 `420` px、预览区不指定 `default-size`(autoPtgSizes 自动占剩余,min440 保底)。相对最初 220/420/660,实际只把预览区从固定 660 改为自动占剩余。
- 根因确认(读 antdv `useSizes.js`+`sizeUtil.js`):Splitter 的 `default-size` 数字=px(折算 px/容器宽 的百分比)、字符串"%"=直接百分比、不传=由 `autoPtgSizes` 把 `1−已定义比例之和` 均分给未定义面板;混用 px+% 不溢出(超 100% 时按 scale 缩放、未定义项归 0)。
- 改动 FmsFile.vue 三面板:① 分类 `:default-size="220"`(min160/max320);② 文件列表 `:default-size="420"`(min280);③ 预览去掉 `:default-size`,仅留 `:min="440" collapsible`。showTree=false 时仅剩列表 420px + 预览占剩余。
- 注意:最小屏(模态 min-width 960 − 两条分隔条≈4px)下 220+420=640 固定,预览得约 316px,会短暂低于其 440 min(仅出现在最小模态宽度);常规/较宽屏预览正常占余、主导显示。
- 验证 vite build 779ms 0 errors。
### fms-file 空状态「暂无相关文件」可点击选择文件
- 用户要求:显示「暂无相关文件」时空状态要 cursor:pointer,点击即可选择文件。
- 改动 FileListPanel.vue:① 空状态 div(`.fl-empty.fl-empty--fill`,仅 `!hasFiles && !loading` 渲染、本就 `position:absolute;inset:0` 铺满文件区)加 `@click="!readonly && triggerSelect()"`——复用隐藏 `uploadInputRef` 唤起文件框(与底部「选择」按钮同一入口),点击文件区任意空白都能触发;② 新增 `.fl-empty--clickable{cursor:pointer}`,并用 `:class="{ 'fl-empty--clickable': !readonly }` 仅非只读时显示手型、点击才生效,只读模式不误导。
- 验证 vite build 777ms 0 errors。
### fms-file 卡片操作列禁用态样式优化
- 用户反馈:卡片操作列(下载/更多按钮)在 pending(`_pending=true`)禁用时,"禁用样式不明显"。
- 根因:`.fcard__footer :deep(.ant-btn)` 里无条件写了 `color: var(--fms-text-secondary)` 与恒定透明边框,把 antdv 自带 `:disabled`(变淡灰 + not-allowed)覆盖掉;lucide 图标用 `currentColor`,禁用与启用图标同色、且鼠标仍 pointer → 看不出禁用。
- 改动:① `main.scss` :root 新增令牌 `--fms-disabled: #c9cdd4`(浅灰,常见禁用色);② `FileCard.vue` footer 的 `:deep(.ant-btn)` 内新增 `&:disabled, &[disabled]` 规则:`color:var(--fms-disabled); background:transparent; border-color:transparent; cursor:not-allowed; opacity:1`(特异性 `.fcard__footer .ant-btn:disabled`=0,3,0 高于通用 `.ant-btn`=0,2,0 与 antdv 默认,稳定生效)。图标因 currentColor 自动变浅灰。删除按钮(danger)始终启用不受影响;禁用时的竖向分隔线(border-left-color:var(--fms-border))保留。
- 验证 vite build 791ms 0 errors。
### fms-file 卡片操作列「删除|更多」分隔线消失修复
- 用户反馈:下载|删除分隔线可见,但删除|更多分隔线看不到(尤其在 pending 卡片上)。
- 根因:原分隔线挂在按钮左边框上(`.ant-btn-dangerous` 命中删除、`.ant-dropdown-trigger` 命中更多)。「更多」按钮在 pending 时禁用,而禁用规则 `&:disabled{border-color:transparent}` 特异性 (0,3,0) 高于分隔线 `.ant-dropdown-trigger` (0,2,0),把其左边框也抹成透明 → 分隔线消失;且「更多」被 a-dropdown 包裹结构更脆。
- 修复:弃用按钮类名/border 方案,在模板 `fcard__footer` 内下载/删除、删除/更多之间各插入独立 `<span class="fcard__divider" />`;新增 `.fcard__divider{flex:none;width:1px;align-self:stretch;background:var(--fms-border)}`(随 footer 撑满高度);删除原先 `:deep(.ant-btn-dangerous),:deep(.ant-dropdown-trigger){border-left-color}` 规则。分隔线不再受按钮禁用态/类名影响,稳定显示。
- 验证 vite build 784ms 0 errors。
+18
View File
@@ -0,0 +1,18 @@
# FMS 项目长期记忆
## 设计令牌作用域(重要踩坑)
- `--fms-*` 设计令牌必须在 `:root` 上定义(全局),不能只放在 `.theme-root`。
- 原因:`a-modal` 等 antdv 组件默认 teleport 到 `<body>`,脱离 `.theme-root`,令牌在其内部全部失效,表现为 "var(--fms-border) is not defined" 报错 + 边框/颜色丢失。
- 现状:`fms-vue/src/styles/main.scss` 的 `:root` 已声明全部令牌;`.theme-root` 仅保留 color/background/overflow。
## fms-file 附件组件关键约定
- 宫格/列表双模式由 `FileListPanel.vue` 的 `viewMode`(grid/list)控制。
- 上传:点击/拖拽/粘贴均汇入 `addFiles()`,允许重复上传同一文件(前端已移除去重,后端无同名约束)。
- 拖拽重复入栈防护在 `handleDragEnter/Leave` 的 `e.currentTarget !== e.target` 判断,非靠去重。
- 待上传文件虚拟 id 形如 `_pending_N`,`deleteSelected` 需降序删除防索引漂移。
## 项目结构速查
- 后端 `fms-api/` Spring Boot 4.1 + Java 21 + SQL Server(Druid 多组织路由);端口 8088,context-path `/api`。
- 前端 `fms-vue/` Vue 3 + Vite + Pinia + antdv-next;dev `:5180`,代理 `/api`→`127.0.0.1:8088`。
- 通用数据接口:`/data/loaddata`、`/data/page`、`/data/saveobjt`、`/data/nextid`、`/auth/login`、`/file/upload`。勿新增业务端点。
- 开发纪律:改完不自行 build/起服务,除非用户要求;可用 `vite build`(或 `--mode development --emptyOutDir false` 规避 dist 清理权限问题)验证。