refactor(project): 重构权限常量定义并移除需求进度聚合功能

- 将产品和项目查询权限码统一提取到常量类中
- 移除需求进度聚合计算的相关实现代码
- 更新权限验证注解使用新的常量定义
- 清理相关的单元测试代码
- 更新错误码注释说明
This commit is contained in:
2026-06-11 09:17:21 +08:00
parent 10b7ccdeb0
commit 79591e66be
30 changed files with 1598 additions and 41 deletions

View File

@@ -0,0 +1,266 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>项目列表按产品分组:后端待确认事项与接口诉求</title>
<style>
:root {
--bg: #f6f7f9;
--panel: #ffffff;
--border: #e5e7eb;
--border-strong: #d1d5db;
--text: #1f2937;
--text-soft: #6b7280;
--text-muted: #9ca3af;
--primary: #2563eb;
--primary-soft: #dbeafe;
--ok: #047857;
--ok-bg: #d1fae5;
--warn: #b45309;
--warn-bg: #fef3c7;
--bad: #b91c1c;
--bad-bg: #fee2e2;
--code: #b45309;
--code-bg: #f3f4f6;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif;
background: var(--bg);
color: var(--text);
font-size: 14px;
line-height: 1.7;
}
.wrap {
max-width: 980px;
margin: 0 auto;
padding: 32px 28px 80px;
}
.head { margin-bottom: 22px; }
.head h1 { margin: 0 0 6px; font-size: 24px; font-weight: 700; line-height: 1.4; }
.head .sub { color: var(--text-soft); font-size: 13px; }
section { margin-top: 28px; }
section > h2 {
font-size: 18px;
font-weight: 700;
margin: 0 0 14px;
padding-bottom: 8px;
border-bottom: 2px solid var(--border);
}
section h3 { font-size: 15px; font-weight: 700; margin: 18px 0 8px; }
.card {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
padding: 18px 22px;
margin-bottom: 14px;
}
table.cmp {
width: 100%;
border-collapse: collapse;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
font-size: 13px;
margin: 10px 0 14px;
}
table.cmp th, table.cmp td {
border: 1px solid var(--border);
padding: 8px 12px;
text-align: left;
vertical-align: top;
}
table.cmp th { background: #f9fafb; font-weight: 700; white-space: nowrap; }
table.cmp td code, p code, li code {
font-family: "JetBrains Mono", Consolas, monospace;
font-size: 12.5px;
color: var(--code);
background: var(--code-bg);
padding: 1px 5px;
border-radius: 4px;
}
pre {
background: #1f2937;
color: #e5e7eb;
border-radius: 8px;
padding: 14px 16px;
overflow-x: auto;
font-family: "JetBrains Mono", Consolas, monospace;
font-size: 12.5px;
line-height: 1.6;
}
pre .c { color: #9ca3af; }
.tag-ok, .tag-warn, .tag-bad {
display: inline-block;
font-size: 11px;
font-weight: 700;
border-radius: 999px;
padding: 1px 10px;
vertical-align: 1px;
white-space: nowrap;
}
.tag-ok { color: var(--ok); background: var(--ok-bg); }
.tag-warn { color: var(--warn); background: var(--warn-bg); }
.tag-bad { color: var(--bad); background: var(--bad-bg); }
ul, ol { margin: 8px 0; padding-left: 22px; }
li { margin: 4px 0; }
.note { color: var(--text-soft); font-size: 13px; }
</style>
</head>
<body>
<div class="wrap">
<div class="head">
<h1>项目列表按产品分组:后端待确认事项与接口诉求</h1>
<div class="sub">2026-06-10 · 前端发起 · 涉及模块project/project项目、system/dict字典</div>
</div>
<section>
<h2>0. 背景</h2>
<div class="card">
<p>项目列表页将从"平铺分页"改为"按所属产品聚合展示":同一产品下的项目(基线/合同/技术支持等类型)需要聚拢在一起查看,不能被分页切散。现有 <code>GET /project/project/page</code> 平铺分页无法支撑该口径,需要后端补充以下能力。</p>
<p>前端已按本文档第 2~4 节的契约<b>先行开发</b>(过渡期用现有平铺接口在前端聚合模拟),后端接口就绪后联调切换,<b>不阻塞后端排期</b>,但请反馈预计时间点。</p>
</div>
</section>
<section>
<h2>1. 待查询确认rdms_project_type 字典数据 <span class="tag-warn">请尽快回复,阻塞前端一处常量</span></h2>
<div class="card">
<p>请提供字典 <code>rdms_project_type</code>(项目类型)的<b>完整字典数据清单</b>(每项的 value / label / 启用状态),特别是:</p>
<ul>
<li><b>"基线"类型对应的字典 value 是什么</b>(前端需写入常量,用于"建立基线"入口预填与缺基线判定);</li>
<li>除 基线 / 合同 / 技术支持 外是否还有其他在用类型值。</li>
</ul>
<p class="note">补充确认(口头已确认,烦请最终对齐):"基线项目每产品唯一"由后端在创建/更新项目时做唯一性校验兜底,前端仅做体验层提示。</p>
</div>
</section>
<section>
<h2>2. 接口诉求一:项目按产品分组分页查询(新增) <span class="tag-bad">核心依赖</span></h2>
<h3>2.1 建议路径</h3>
<div class="card">
<p><code>GET /project/project/group-page</code>(路径可由后端按规范调整,前端只在 service 层适配一处)</p>
<p>数据权限口径与现有 <code>/project/project/page</code> 一致:只返回当前用户可见的项目,按其归属产品聚合。</p>
</div>
<h3>2.2 入参</h3>
<table class="cmp">
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
<tr><td><code>pageNo</code> / <code>pageSize</code></td><td>int</td><td></td><td><b>产品组维度</b>分页:一页返回 pageSize 个产品组(含组内项目),不是项目行分页。前端当前 pageSize=10。</td></tr>
<tr><td><code>keyword</code></td><td>string</td><td></td><td>项目编码 / 名称模糊匹配(口径同现有 page 接口)。</td></tr>
<tr><td><code>productId</code></td><td>string</td><td></td><td>限定单个产品。</td></tr>
<tr><td><code>projectType</code></td><td>string</td><td></td><td>项目类型字典 value。</td></tr>
<tr><td><code>statusCode</code></td><td>string</td><td></td><td>单状态过滤。<b>不传 = "全部"口径pending / active / paused / completed 四种状态,不含 cancelled / archived。</b></td></tr>
<tr><td><code>orphanOnly</code></td><td>boolean</td><td></td><td>true = 仅返回"游离组"productId 为空的项目聚合为一个特殊组)。</td></tr>
<tr><td><code>topN</code></td><td>int</td><td></td><td>每组返回的项目条数上限,建议默认 5前端当前固定取 5</td></tr>
</table>
<h3>2.3 返回结构(示例)</h3>
<pre>{
"total": 12, <span class="c">// 当前筛选口径下产品组总数(分页 total含游离组</span>
"projectTotal": 47, <span class="c">// 当前筛选口径下项目总数</span>
"directionCount": 3, <span class="c">// 可见产品去重后的方向directionCode</span>
"orphanTotal": 3, <span class="c">// 游离项目数productId 为空)</span>
"list": [
{
"productId": "1923456789012345678", <span class="c">// 字符串!见 4.1</span>
"productName": "智能网关",
"productCode": "RDMS-P-001",
"directionCode": "platform",
"managerUserId": "1001",
"managerUserNickname": "张三",
"projectTotal": 6, <span class="c">// 当前筛选口径下该组项目总数</span>
"projects": [ /* 前 topN 条,字段同现有 page 接口的项目行 */ ],
"typeCounts": { "baseline值": 1, "合同值": 3, "技术支持值": 2 },
"hasBaseline": true,
"orphan": false
},
{
"productId": null, <span class="c">// 游离组:未挂产品的项目聚合</span>
"productName": "游离项目",
"productCode": null,
"directionCode": "",
"managerUserId": null,
"managerUserNickname": null,
"projectTotal": 3,
"projects": [ /* ... */ ],
"typeCounts": { "合同值": 2, "技术支持值": 1 },
"hasBaseline": false,
"orphan": true
}
]
}</pre>
<h3>2.4 口径约定(关键,请逐条确认)</h3>
<table class="cmp">
<tr><th>#</th><th>约定</th><th>说明</th></tr>
<tr><td>1</td><td>组内项目排序</td><td><code>updateTime</code> 倒序,返回前 topN 条;<code>projectTotal</code> 为该口径下组内全量计数。</td></tr>
<tr><td>2</td><td>无命中组不返回</td><td>传了 <code>statusCode</code> / <code>keyword</code> / <code>projectType</code> 任一筛选时,组内无命中项目的产品组不返回。</td></tr>
<tr><td>3</td><td>零项目产品组</td><td>"全部"口径statusCode 缺省)且无 keyword / projectType 筛选时,<b>返回当前用户可见、状态为 active / paused 的零项目产品组</b>projectTotal=0、projects=[]),用于"该产品暂无项目"占位与新增引导。</td></tr>
<tr><td>4</td><td>typeCounts / hasBaseline 统计口径</td><td>这两个字段是"产品属性"<b>恒按"全部"口径(四种状态)统计</b>,不随 statusCode 入参变化——避免"基线项目已完成时被误判为缺基线"。</td></tr>
<tr><td>5</td><td>游离组位置</td><td>游离组productId 为空)作为列表中<b>最后一个组</b>返回;状态筛选下同样适用约定 2无命中则不返回该组</td></tr>
<tr><td>6</td><td>组的排序</td><td>同方向directionCode的产品组相邻返回方向间顺序、方向内产品顺序由后端按现有产品列表默认排序即可</td></tr>
</table>
<h3>2.5 组内"展开剩余"的数据来源</h3>
<div class="card">
<p>不需要新接口:前端用现有 <code>GET /project/project/page</code><code>productId + statusCode</code> 拉取该组剩余项目。前提是该接口的排序与本接口组内排序一致updateTime 倒序)——若现有 page 接口默认排序不是 updateTime 倒序,请告知或支持排序参数。</p>
</div>
</section>
<section>
<h2>3. 接口诉求二、三:存量接口小改 <span class="tag-warn">两处补充</span></h2>
<h3>3.1 平铺分页支持"未挂产品"筛选</h3>
<div class="card">
<p><code>GET /project/project/page</code> 需要能表达 <b>productId 为空</b>的筛选语义(如新增 <code>orphanOnly=true</code> 参数,或约定 productId 传特殊值),用于查询"游离项目"(未关联任何产品的项目)。具体参数形式由后端定,前端适配。</p>
</div>
<h3>3.2 概览统计补游离计数</h3>
<div class="card">
<p><code>GET /project/project/overview-summary</code> 返回体增加:</p>
<pre>{
"statusCounts": { "active": 10, "pending": 2, ... }, <span class="c">// 现有</span>
"orphanCount": 3 <span class="c">// 新增:未挂产品的项目数(按"全部"口径:四种状态)</span>
}</pre>
</div>
</section>
<section>
<h2>4. 公共约定</h2>
<table class="cmp">
<tr><th>#</th><th>约定</th><th>说明</th></tr>
<tr><td>4.1</td><td>ID 一律字符串 <span class="tag-bad">必须</span></td><td>所有 Long / 雪花 IDproductId、managerUserId、项目 id 等)在 JSON 中<b>按字符串返回</b>。Long 直接作为 JSON 数字返回会在前端丢精度。</td></tr>
<tr><td>4.2</td><td>"全部"状态集合</td><td>pending / active / paused / completedcancelled / archived 仅在显式传对应 statusCode 时返回。</td></tr>
<tr><td>4.3</td><td>项目行字段</td><td>分组接口 <code>projects[]</code> 内的项目对象字段与现有 <code>/project/project/page</code> 返回行保持一致(含 productId / productName / managerUserNickname / progressRate / statusCode / updateTime 等),避免前端双口径。</td></tr>
</table>
</section>
<section>
<h2>5. 需要后端反馈的清单</h2>
<div class="card">
<ol>
<li><b>第 1 节</b><code>rdms_project_type</code> 字典数据清单 + "基线"的 value<span class="tag-warn">最优先</span>,一条查询即可,阻塞前端一处常量)。</li>
<li><b>第 2 节</b>:分组分页接口的可行性确认 + 2.4 六条口径逐条确认(有异议请直接批注替代方案)+ 排期。</li>
<li><b>第 3 节</b>page 接口游离筛选的参数形式 + overview-summary 补 orphanCount 的排期。</li>
<li><b>第 2.5 节</b>:现有 page 接口的默认排序是什么;是否支持/计划支持按 updateTime 倒序。</li>
</ol>
</div>
</section>
</div>
</body>
</html>