diff --git a/CLAUDE.md b/CLAUDE.md index 165da22..c94345b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -415,3 +415,17 @@ pnpm preview # preview server (9725) - 新建写接口 → 不用管,默认兜底;只有明确"允许短时间连发"才传 `dedupe: false` - 新建上传 / 下载流程 → FormData / Blob 天然不在去重范围,按原方式写即可 - 用户报"双击双发"复现不出来 → 检查目标按钮是否走了 `business-form-dialog`;若用的是 `ElMessageBox.confirm`,靠第二层就该挡住 + +--- + +## 20. 我生成文档的输出格式(强约束) + +- **superpowers 工作流(`docs/superpowers/plans/`、`docs/superpowers/specs/`)下输出的文档继续用 `.md`**——工作流以 markdown 为前提。 +- **其他**我生成的文档(设计方案、复盘、规约、技术经验沉淀等)**默认用 `.html`**,沿用 `docs/debt/` 现有 HTML 文档(参考 `token-刷新机制对齐分析.html`、`技术负债台账.html`)的样式骨架: + - 单文件、内联 CSS + - `max-width: 980px` 居中容器、`padding: 32px 28px 80px` + - 14px / `line-height: 1.7`、`PingFang SC` / `Microsoft YaHei` 中文字体优先 + - 模块化区块:`section` + 编号 h2、`card`、`table.cmp`、`pre`、`tag-ok/warn/bad/crit` + - 配色用 `--bg / --panel / --border / --text / --primary` 一套 CSS 变量 +- **`README.md`** 是目录索引约定文件,**保持 `.md`**(不强行 `.html`)。 +- **已有 `.md` 文档不主动改写**,等用户明确要求再转。 diff --git a/README.md b/README.md deleted file mode 100644 index 9207638..0000000 --- a/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# cn-rdms-web - -这是当前项目的前端工程仓库。 - -原开源模板项目的介绍内容已移除,这个 README 现在只保留当前项目自身所需的信息。 - -## 项目说明 - -待补充。 - -建议后续在这里补充: - -- 项目背景 -- 技术栈 -- 目录结构 -- 本地启动方式 -- 环境变量说明 -- 构建与发布流程 - -## 本地开发 - -```bash -pnpm install -pnpm dev -``` - -## 常用命令 - -```bash -pnpm dev -pnpm build -pnpm build:dev -pnpm typecheck -pnpm lint -``` diff --git a/docs/superpowers/specs/2026-04-23-product-overview-homepage-design.md b/docs/superpowers/specs/2026-04-23-product-overview-homepage-design.md deleted file mode 100644 index 58da0c6..0000000 --- a/docs/superpowers/specs/2026-04-23-product-overview-homepage-design.md +++ /dev/null @@ -1,292 +0,0 @@ -# 产品对象首页改版设计说明 - -日期:2026-04-23 - -## 1. 目标 - -本设计用于收敛 RDMS 产品对象上下文默认首页的改版方向。 - -本轮目标不是继续做“说明型占位页”,而是明确把当前 `/product/dashboard?objectId=...` 改成一个真正可用的产品对象首页: - -- 第一眼先让用户知道当前看的是什么产品 -- 第二眼能快速判断对象最近发生了什么 -- 第三眼能看出需求池现在的经营状态和最近变化 -- 底部为后续业务模块保留正式挂载位,而不是临时拼接入口 - -## 2. 已确认诉求 - -基于本轮对话,已确认以下用户诉求: - -1. 首页顶部必须先展示产品基础概述,而不是先铺统计卡片 -2. 基础概述至少包含:名称、编号、团队、产品经理等对象基础信息 -3. 页面需要一块明显的时间线,用于承接产品对象与团队变更动态 -4. 页面需要承接需求池管理情况,重点看总量、状态、待处理等统计信息 -5. 需求相关事件不要混入对象时间线,应单独作为需求池最近变化区域 -6. 快捷入口不要保留 -7. 底部允许保留后续扩展区,重点预留给里程碑、风险点管理、产品资料等模块 -8. 能接真实接口就接真实接口,当前没有稳定接口的区域允许先用假数据,但结构必须按正式首页来设计 - -## 3. 首页定位结论 - -本页定位不是: - -- 纯报表看板 -- 纯审计日志页 -- 设置页搬运版 -- 导航入口集合页 - -本页定位应当是: - -- 产品对象首页 -- 偏统计,也带审计 -- 但页面主语始终是“当前产品对象” - -换句话说,这个页面要同时回答三个问题: - -1. 我现在看的是什么产品? -2. 这个产品对象最近发生了什么? -3. 这个产品的需求池现在处于什么状态? - -## 4. 页面结构 - -### 4.1 桌面端结构 - -桌面端建议采用三层结构: - -1. 顶部 `对象基础概述横幅` -2. 中部 `左时间线 + 右需求池双模块` -3. 底部 `扩展信息区` - -推荐布局比例: - -- 顶部横幅:`24 / 24` -- 中部主区:左 `16 / 24`,右 `8 / 24` -- 底部扩展区:`24 / 24` - -中部左侧时间线高度应明显高于右侧任一单模块,形成首页主阅读区。 - -### 4.2 移动端结构 - -移动端统一退化为单列纵向布局,顺序为: - -1. 对象基础概述横幅 -2. 对象 / 团队动态时间线 -3. 需求池管理概览 -4. 需求池最近变化 -5. 扩展信息区 - -移动端不强撑左右栏并排,不做卡片墙式压缩。 - -## 5. 模块设计 - -### 5.1 对象基础概述横幅 - -顶部采用“档案横幅型”,不采用纯指标卡片型。 - -横幅左侧承接对象身份信息: - -- 产品名称 -- 产品编号 -- 当前状态标签 -- 产品经理 -- 团队规模 -- 团队角色摘要 -- 简短描述或备注 - -横幅右侧承接 4 个摘要指标: - -- 团队人数 -- 需求总量 -- 待处理需求 -- 最近动态时间 - -设计原则: - -- 左侧负责建立对象识别 -- 右侧负责快速判断当前概况 -- 右侧指标只保留 4 项,不堆成报表卡片墙 - -### 5.2 对象 / 团队动态时间线 - -该区域位于中部左侧,是首页的主阅读区。 - -这条时间线只承接对象与团队变化,不承接需求事件。 - -第一版事件范围收敛为: - -- 产品创建 -- 产品状态变更 -- 产品经理变更 -- 成员加入 -- 成员移出 -- 成员角色调整 - -每条时间线建议展示: - -- 事件标题 -- 事件类型标签 -- 发生时间 -- 操作摘要 -- 必要时展示原因或备注 - -表达目标是“业务时间线”,不是后台审计表格。 - -### 5.3 需求池管理概览 - -该区域位于中部右侧上半块,用于表达需求池的经营状态。 - -第一版首页需要优先看到的内容: - -- 需求总量 -- 各状态数量 -- 待处理数量 -- 高优先级待处理数量 - -展示方式建议为“摘要指标 + 状态分布列表”,不直接在首页展开完整需求表格。 - -这一块回答的是: - -- 需求池是否健康 -- 当前待处理压力大不大 -- 是否存在需要优先关注的积压 - -### 5.4 需求池最近变化 - -该区域位于中部右侧下半块,与需求池管理概览上下分层,但属于同一侧栏语义。 - -该区域不重复展示总量,而是展示需求池最近发生的变化。 - -第一版建议承接: - -- 最近新增需求 -- 最近状态流转 -- 最近关闭或完成 - -每条记录建议至少展示: - -- 需求标题 -- 动作类型 -- 时间 -- 当前状态或状态变更摘要 - -若当前没有真实数据,仍保留正式模块壳,不退化成“待开发”一句话。 - -### 5.5 扩展信息区 - -底部不再保留快捷入口,改为正式扩展信息区。 - -当前优先预留 3 类模块位: - -- 里程碑 -- 风险点管理 -- 产品资料 - -这一层的作用是: - -- 为后续对象级信息继续扩展留下稳定挂载位 -- 不把中部主结构挤成信息大杂烩 -- 避免为了未来模块提前做假导航入口 - -如果当前没有稳定接口,可先保留正式卡片结构与空态说明。 - -## 6. 数据策略 - -### 6.1 真实接口优先 - -当前首页优先消费现有真实接口: - -- `fetchGetProduct` -- `fetchGetProductSettings` -- `fetchGetProductMembers` - -这些接口足以支撑: - -- 对象基础概述中的名称、编号、状态、产品经理、描述 -- 团队人数与角色摘要 -- 最近动态中的产品创建、状态变化、成员加入/移出 - -### 6.2 假数据使用边界 - -当前没有稳定真实接口的区域,允许先用假数据,但边界必须明确: - -- 需求池管理概览 -- 需求池最近变化 -- 扩展信息区中的里程碑、风险点管理、产品资料摘要 - -假数据的使用原则: - -1. 只补“当前没有稳定接口”的区域 -2. 不反向污染对象基础信息 -3. 不把假数据混入对象上下文 store -4. 数据源要集中放在概览页自己的 mock 模块中,方便后续替换 - -### 6.3 不推荐的做法 - -以下做法应避免: - -- 把需求假数据散落写进页面组件 -- 用对象 demo 数据冒充真实产品详情 -- 把对象时间线和需求时间线混成一条 -- 用快捷入口伪装成首页内容 - -## 7. 空态规则 - -首页至少要区分三种状态: - -1. 能力未接入,只能先显示正式占位信息 -2. 能力已接入,但当前该产品暂无业务数据 -3. 当前用户无权限查看该模块 - -这三种状态不能共用一套模糊文案。 - -对需求池和扩展信息区,当前阶段更推荐“正式空态”而不是“待开发”。 - -## 8. 页面边界 - -首页明确不承接以下内容: - -- 快捷入口导航区 -- 完整团队成员表格 -- 完整需求列表表格 -- 设置页重表单 -- 完整审计日志明细页 - -首页要做的是概述、判断与阅读,不是重操作页。 - -## 9. 实施建议 - -第一阶段建议先完成结构性改造: - -1. 重做顶部横幅,建立对象档案感 -2. 保留中部左高右双块结构 -3. 用真实接口接通对象概述与对象 / 团队时间线 -4. 用局部 mock 数据先接通需求池两块和底部扩展区 - -第二阶段再逐步替换需求池与扩展区数据源: - -- 接真实需求池统计接口 -- 接真实需求动态接口 -- 接里程碑、风险点、产品资料摘要接口 - -## 10. 验证标准 - -本设计是否成立,可按以下标准判断: - -1. 进入首页后,第一眼能认出当前产品对象 -2. 用户能自然读到对象 / 团队最近发生了什么 -3. 右侧能快速判断需求池当前压力与最近变化 -4. 页面看起来像“对象首页”,而不是“普通后台卡片堆叠页” -5. 当前没有真实接口的区域也保留正式结构,不显得像临时占位 -6. 后续新增里程碑、风险点管理、产品资料等能力时,不需要推翻整页结构 - -## 11. 本轮设计结论 - -本轮最终设计结论如下: - -- 首页定位为“产品对象首页”,偏统计,也带审计,但不做纯报表页 -- 顶部采用档案横幅型,先立住对象身份信息 -- 中部左侧是高权重的对象 / 团队动态时间线 -- 中部右侧拆为“需求池管理概览 + 需求池最近变化”上下两块 -- 底部去掉快捷入口,改为正式扩展信息区 -- 当前有真实接口的模块优先接真实接口 -- 当前没有稳定接口的区域允许先用假数据,但必须隔离在概览页局部 mock 数据源中 diff --git a/src/components/custom/business-attachment-uploader.vue b/src/components/custom/business-attachment-uploader.vue index 0cff3f3..0cc1767 100644 --- a/src/components/custom/business-attachment-uploader.vue +++ b/src/components/custom/business-attachment-uploader.vue @@ -470,7 +470,7 @@ onBeforeUnmount(() => { { {{ item.name }} {{ formatSize(item.size) }} - 下载 + 下载 @@ -509,7 +509,7 @@ onBeforeUnmount(() => { { {{ item.name }} {{ formatSize(item.size) }} - 下载 + 下载 diff --git a/src/components/custom/dict-select.vue b/src/components/custom/dict-select.vue index ded9e89..7892093 100644 --- a/src/components/custom/dict-select.vue +++ b/src/components/custom/dict-select.vue @@ -14,6 +14,8 @@ interface Props { multiple?: boolean; collapseTags?: boolean; collapseTagsTooltip?: boolean; + /** 下拉项右侧追加字典 remark 中文释义(优先级等需要"P0 → 紧急"对照的场景) */ + showRemark?: boolean; } const props = withDefaults(defineProps(), { @@ -24,7 +26,8 @@ const props = withDefaults(defineProps(), { onlyEnabled: true, multiple: false, collapseTags: false, - collapseTagsTooltip: false + collapseTagsTooltip: false, + showRemark: false }); const model = defineModel | null | undefined>({ @@ -35,18 +38,27 @@ const { enabledDictData, dictData } = useDict(() => props.dictCode); const dictOptions = computed(() => { const source = props.onlyEnabled ? enabledDictData.value : dictData.value; - return source.map(item => ({ label: item.label, - value: item.value + value: item.value, + colorType: item.colorType ?? null, + remark: item.remark ?? null })); }); + +// 单选时取当前选中项的 colorType,用于触发器 prefix 色块 +const selectedColorType = computed(() => { + if (props.multiple) return null; + const value = model.value; + if (value === null || value === undefined || value === '') return null; + return dictOptions.value.find(opt => opt.value === value)?.colorType ?? null; +}); - + diff --git a/src/components/custom/dict-tag.vue b/src/components/custom/dict-tag.vue index 94b4ba4..e8aadc1 100644 --- a/src/components/custom/dict-tag.vue +++ b/src/components/custom/dict-tag.vue @@ -1,4 +1,6 @@