Skip to content

Commit 32ceb9a

Browse files
committed
同步: SmartAdmin 项目: 完善测试点引用与报表筛选口径
源仓库: zoujingli/SmartAdminDeveloper 源提交: 75dbf93eb99b 同步分支: master 源提交说明: - 617972f 安全: 脱敏标准响应路径令牌 标准响应体的 path 字段可能包含分享、评价或回调路径中的一次性凭证,返回前统一经过 SensitiveDataFilter 脱敏。 补充 BaseResponseException 路径 token 脱敏单测,锁定公共入口响应不泄漏真实 token。 - 7da6f25 入口: 优先进入插件管理登录 模块引导入口跳转抽出 entry-targets 工具,并在插件声明 login_path 时优先打开独立登录入口,避免先进入后台首页再切换身份。 优化模块引导卡片为显式登录按钮,补充 vitest 覆盖路径规范化、login_path 优先级和 fallback 行为。 同步 Asset、Material、Website 登录页和菜单文案为管理登录口径,保持入口展示一致。 - aaee4d6 客情: 优化管理入口与业务闭环体验 重组 Customer 后台与用户端菜单为基础资料、项目确权、案例赋能、接待执行、结算风控和运营配置,并让模块引导直达 /customer/login。 通用页面支持远程搜索选择器和关系名称回填,列表默认展示经销商、客户、项目、展厅、预约、负责人等业务名称,减少裸 ID 操作。 公共分享、评价和登录入口支持浏览器直接返回 SPA shell,公共 token 固定 48 位校验并补充响应 path 脱敏说明。 收紧接待完成、暂缓结算恢复、违规影响和演示数据恢复规则,补充 CustomerContractTest 与客情接口文档。 - 75dbf93 项目: 完善测试点引用与报表筛选口径 Bug 来源支持测试单下的测试点,按父级类型回填任务、测试单和子任务链路,避免测试点被普通子任务校验误拦截。 报表参数统一清洗正整数 ID 和 Bug 聚合白名单,修正 blocker、状态、来源字段进入统计 SQL 的口径。 引用弹层和前端跳转区分测试点、测试单与普通任务,上级主数据状态统一为进行中、验收中和已完成展示。 优化 Project 门户和活动流展示,并同步 Project 单测与项目接口文档。 目标变更文件(5 个): - M "docs/\346\216\245\345\217\243\345\217\202\350\200\203/\351\241\271\347\233\256\347\256\241\347\220\206\346\216\245\345\217\243.md" - M tests/Unit/System/Service/DataServiceModuleGuideTest.php - A web/apps/web-antd/src/views/_core/module-guide/__tests__/entry-targets.test.ts - A web/apps/web-antd/src/views/_core/module-guide/entry-targets.ts - M web/apps/web-antd/src/views/_core/module-guide/index.vue
1 parent 356529e commit 32ceb9a

5 files changed

Lines changed: 242 additions & 180 deletions

File tree

docs/接口参考/项目管理接口.md

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3511,7 +3511,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
35113511
"actual_start_at": "2026-05-29 10:00:00",
35123512
// actual_finish_at: 实际完成日期。
35133513
"actual_finish_at": "2026-05-29 10:00:00",
3514-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
3514+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
35153515
"work_status": "示例值",
35163516
// created_by: 创建者。
35173517
"created_by": 1,
@@ -4217,7 +4217,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
42174217
"actual_start_at": "2026-05-29 10:00:00",
42184218
// actual_finish_at: 实际完成日期。
42194219
"actual_finish_at": "2026-05-29 10:00:00",
4220-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
4220+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
42214221
"work_status": "示例值",
42224222
// created_by: 创建者。
42234223
"created_by": 1,
@@ -4788,7 +4788,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
47884788
"actual_start_at": "2026-05-29 10:00:00",
47894789
// actual_finish_at: 实际完成日期。
47904790
"actual_finish_at": "2026-05-29 10:00:00",
4791-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成,60已发布)。
4791+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成,60已发布)。
47924792
"work_status": "示例值",
47934793
// released_at: 发布时间。
47944794
"released_at": "2026-05-29 10:00:00",
@@ -4958,7 +4958,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
49584958
"actual_start_at": "2026-05-29 10:00:00",
49594959
// actual_finish_at: 实际完成日期。
49604960
"actual_finish_at": "2026-05-29 10:00:00",
4961-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成,60已发布)。
4961+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成,60已发布)。
49624962
"work_status": "示例值",
49634963
// released_at: 发布时间。
49644964
"released_at": "2026-05-29 10:00:00",
@@ -5595,7 +5595,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
55955595
"actual_start_at": "2026-05-29 10:00:00",
55965596
// actual_finish_at: 实际完成日期。
55975597
"actual_finish_at": "2026-05-29 10:00:00",
5598-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
5598+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
55995599
"work_status": "示例值",
56005600
// created_by: 创建者。
56015601
"created_by": 1,
@@ -5767,7 +5767,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
57675767
"actual_start_at": "2026-05-29 10:00:00",
57685768
// actual_finish_at: 实际完成日期。
57695769
"actual_finish_at": "2026-05-29 10:00:00",
5770-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
5770+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
57715771
"work_status": "示例值",
57725772
// created_by: 创建者。
57735773
"created_by": 1,
@@ -6441,7 +6441,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
64416441
"actual_start_at": "2026-05-29 10:00:00",
64426442
// actual_finish_at: 实际完成日期。
64436443
"actual_finish_at": "2026-05-29 10:00:00",
6444-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
6444+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
64456445
"work_status": "示例值",
64466446
// created_by: 创建者。
64476447
"created_by": 1,
@@ -9860,7 +9860,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
98609860
"actual_start_at": "2026-05-29 10:00:00",
98619861
// actual_finish_at: 实际完成日期。
98629862
"actual_finish_at": "2026-05-29 10:00:00",
9863-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
9863+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
98649864
"work_status": "示例值",
98659865
// created_by: 创建者。
98669866
"created_by": 1,
@@ -11978,7 +11978,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1197811978
"actual_start_at": "2026-05-29 10:00:00",
1197911979
// actual_finish_at: 实际完成日期。
1198011980
"actual_finish_at": "2026-05-29 10:00:00",
11981-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
11981+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
1198211982
"work_status": "示例值",
1198311983
// created_by: 创建者。
1198411984
"created_by": 1,
@@ -12678,7 +12678,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1267812678
"actual_start_at": "2026-05-29 10:00:00",
1267912679
// actual_finish_at: 实际完成日期。
1268012680
"actual_finish_at": "2026-05-29 10:00:00",
12681-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
12681+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
1268212682
"work_status": "示例值",
1268312683
// created_by: 创建者。
1268412684
"created_by": 1,
@@ -13245,7 +13245,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1324513245
"actual_start_at": "2026-05-29 10:00:00",
1324613246
// actual_finish_at: 实际完成日期。
1324713247
"actual_finish_at": "2026-05-29 10:00:00",
13248-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成,60已发布)。
13248+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成,60已发布)。
1324913249
"work_status": "示例值",
1325013250
// released_at: 发布时间。
1325113251
"released_at": "2026-05-29 10:00:00",
@@ -13403,7 +13403,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1340313403
"actual_start_at": "2026-05-29 10:00:00",
1340413404
// actual_finish_at: 实际完成日期。
1340513405
"actual_finish_at": "2026-05-29 10:00:00",
13406-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成,60已发布)。
13406+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成,60已发布)。
1340713407
"work_status": "示例值",
1340813408
// released_at: 发布时间。
1340913409
"released_at": "2026-05-29 10:00:00",
@@ -14030,7 +14030,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1403014030
"actual_start_at": "2026-05-29 10:00:00",
1403114031
// actual_finish_at: 实际完成日期。
1403214032
"actual_finish_at": "2026-05-29 10:00:00",
14033-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
14033+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
1403414034
"work_status": "示例值",
1403514035
// created_by: 创建者。
1403614036
"created_by": 1,
@@ -14188,7 +14188,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1418814188
"actual_start_at": "2026-05-29 10:00:00",
1418914189
// actual_finish_at: 实际完成日期。
1419014190
"actual_finish_at": "2026-05-29 10:00:00",
14191-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
14191+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
1419214192
"work_status": "示例值",
1419314193
// created_by: 创建者。
1419414194
"created_by": 1,
@@ -14850,7 +14850,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1485014850
"actual_start_at": "2026-05-29 10:00:00",
1485114851
// actual_finish_at: 实际完成日期。
1485214852
"actual_finish_at": "2026-05-29 10:00:00",
14853-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
14853+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
1485414854
"work_status": "示例值",
1485514855
// created_by: 创建者。
1485614856
"created_by": 1,
@@ -18205,7 +18205,7 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
1820518205
"actual_start_at": "2026-05-29 10:00:00",
1820618206
// actual_finish_at: 实际完成日期。
1820718207
"actual_finish_at": "2026-05-29 10:00:00",
18208-
// work_status: 业务状态(10已创建,20进行中,30测试中,40返工中,50已完成)。
18208+
// work_status: 业务状态(10已创建,20进行中,30验收中,50已完成)。
1820918209
"work_status": "示例值",
1821018210
// created_by: 创建者。
1821118211
"created_by": 1,
@@ -22514,7 +22514,8 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
2251422514
"query": {
2251522515
"type": "task",
2251622516
"id": 1,
22517-
"limit": 100
22517+
"limit": 100,
22518+
"subtask_only": 1
2251822519
},
2251922520
// body: Body 请求体,写接口按业务表单提交字段。
2252022521
"body": ""
@@ -22534,7 +22535,8 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
2253422535
"query": {
2253522536
"type": "task",
2253622537
"id": 1,
22537-
"limit": 100
22538+
"limit": 100,
22539+
"subtask_only": 1
2253822540
},
2253922541
"body": ""
2254022542
}
@@ -22805,7 +22807,8 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
2280522807
"query": {
2280622808
"type": "task",
2280722809
"id": 1,
22808-
"limit": 100
22810+
"limit": 100,
22811+
"subtask_only": 1
2280922812
},
2281022813
// body: Body 请求体,写接口按业务表单提交字段。
2281122814
"body": ""
@@ -22825,7 +22828,8 @@ Project 应用登录页 `/project/login`、前台路由范围和前台菜单由
2282522828
"query": {
2282622829
"type": "task",
2282722830
"id": 1,
22828-
"limit": 100
22831+
"limit": 100,
22832+
"subtask_only": 1
2282922833
},
2283022834
"body": ""
2283122835
}

tests/Unit/System/Service/DataServiceModuleGuideTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ public function testModuleGuideIsEnabledWhenSwitchAndEntriesAreAvailable(): void
7676

7777
self::assertTrue($result['enabled']);
7878
self::assertSame('demo', $result['entries'][0]['code'] ?? null);
79+
self::assertSame('/demo/home', $result['entries'][0]['home_path'] ?? null);
80+
self::assertSame('/demo/login', $result['entries'][0]['login_path'] ?? null);
81+
self::assertSame('演示入口', $result['entries'][0]['name'] ?? null);
7982
});
8083
}
8184

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { ModuleGuideEntry } from '#/plugins/module-guide-provider';
2+
3+
import { describe, expect, it } from 'vitest';
4+
5+
import { moduleGuideHomeTarget, normalizeModuleGuidePath } from '../entry-targets';
6+
7+
function entry(value: Partial<ModuleGuideEntry>): ModuleGuideEntry {
8+
return {
9+
code: 'demo',
10+
description: '演示入口',
11+
enabled: true,
12+
home_path: '',
13+
icon: 'lucide:blocks',
14+
login_path: '',
15+
name: '演示',
16+
plugin: 'Demo',
17+
sort: 1,
18+
...value,
19+
};
20+
}
21+
22+
describe('module guide entry targets', () => {
23+
it('uses the independent plugin login as the only guide target when present', () => {
24+
const item = entry({
25+
home_path: '/partner/dashboard',
26+
login_path: '/partner/login',
27+
});
28+
29+
expect(moduleGuideHomeTarget(item, '/fallback/login')).toBe('/partner/login');
30+
});
31+
32+
it('falls back to the plugin home path when no independent login is declared', () => {
33+
const item = entry({
34+
home_path: '/project/portal/',
35+
});
36+
37+
expect(moduleGuideHomeTarget(item, '/fallback/login')).toBe('/project/portal');
38+
});
39+
40+
it('falls back to the current auth login path when an entry has no target path', () => {
41+
const item = entry({});
42+
43+
expect(moduleGuideHomeTarget(item, '/fallback/login')).toBe('/fallback/login');
44+
});
45+
46+
it('normalizes client routes without accepting empty relative display values', () => {
47+
expect(normalizeModuleGuidePath(' partner/login/ ')).toBe('/partner/login');
48+
expect(normalizeModuleGuidePath('/')).toBe('/');
49+
expect(normalizeModuleGuidePath('')).toBe('/');
50+
});
51+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { ModuleGuideEntry } from '#/plugins/module-guide-provider';
2+
3+
export function normalizeModuleGuidePath(value: string) {
4+
const path = `/${String(value || '').trim().replace(/^\/+/, '')}`;
5+
6+
return path === '/' ? '/' : path.replace(/\/+$/, '');
7+
}
8+
9+
export function moduleGuideHomeTarget(entry: ModuleGuideEntry, fallbackPath: string) {
10+
return normalizeModuleGuidePath(entry.login_path || entry.home_path || fallbackPath);
11+
}

0 commit comments

Comments
 (0)