@dreamor/atlas-cli 0.7.13 → 0.7.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -142,7 +142,7 @@ function registerProjectCommands(program) {
|
|
|
142
142
|
// atlas find
|
|
143
143
|
program
|
|
144
144
|
.command('find <kind> <query>')
|
|
145
|
-
.description('搜索项目/部门/字典值(kind: project|department|
|
|
145
|
+
.description('搜索项目/部门/字典值(kind: project|department|manpower-type|role|area)')
|
|
146
146
|
.option('--json', '输出 JSON 信封')
|
|
147
147
|
.option('--refresh', '刷新字典/部门/项目缓存')
|
|
148
148
|
.option('--limit <n>', '最多返回 N 个候选(默认 20)')
|
|
@@ -151,12 +151,9 @@ kind 说明:
|
|
|
151
151
|
|
|
152
152
|
project 搜索有权限的项目列表(从 API 实时查询)
|
|
153
153
|
department 搜索部门树中的部门名称(1500+ 部门节点)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
area
|
|
157
|
-
|
|
158
|
-
注意: mp-type / line-plan-type / area-code 为字典数据,来源于同一字典 API,
|
|
159
|
-
搜索范围是该字典所有条目的 attrName 字段。`)
|
|
154
|
+
manpower-type 搜索人力类型(例: "斑马"、"智软",baseline --manpower-type 用)
|
|
155
|
+
role 搜索人力基线角色(例: "开发"、"产品"、"测试"、"PM"、"设计" 等)
|
|
156
|
+
area 搜索地域(例: "北上杭"、"合肥"、"武汉"、"西南")`)
|
|
160
157
|
.action(async (kind, query, opts) => {
|
|
161
158
|
try {
|
|
162
159
|
await findCmd(kind, query, opts);
|
|
@@ -223,8 +220,8 @@ function registerBaselineCommands(program) {
|
|
|
223
220
|
.option('--json', '输出 JSON')
|
|
224
221
|
.option('--department <name>', '按部门名称/ID 筛选(子串,不区分大小写)')
|
|
225
222
|
.option('--role <name>', '按角色/备注筛选(子串,不区分大小写)')
|
|
226
|
-
.option('--area
|
|
227
|
-
.option('--
|
|
223
|
+
.option('--area <code>', '按地域筛选(子串,不区分大小写)')
|
|
224
|
+
.option('--manpower-type <type>', '按人力类型筛选(子串,不区分大小写)')
|
|
228
225
|
.option('--month <yyyymm>', '查询月份(YYYY-MM,与 --from/--to 互斥)')
|
|
229
226
|
.option('--from <yyyymm>', '起始月份(YYYY-MM,包含)')
|
|
230
227
|
.option('--to <yyyymm>', '结束月份(YYYY-MM,包含)')
|
|
@@ -244,8 +241,8 @@ function registerBaselineCommands(program) {
|
|
|
244
241
|
.option('--by <axis>', 'month | department | role', 'month')
|
|
245
242
|
.option('--department <name>', '按部门名称/ID 筛选(子串,不区分大小写)')
|
|
246
243
|
.option('--role <name>', '按角色/备注筛选(子串,不区分大小写)')
|
|
247
|
-
.option('--area
|
|
248
|
-
.option('--
|
|
244
|
+
.option('--area <code>', '按地域筛选(子串,不区分大小写)')
|
|
245
|
+
.option('--manpower-type <type>', '按人力类型筛选(子串,不区分大小写)')
|
|
249
246
|
.option('--from <yyyymm>', '起始月份(YYYY-MM,包含)')
|
|
250
247
|
.option('--to <yyyymm>', '结束月份(YYYY-MM,包含)')
|
|
251
248
|
.option('--json', '输出 JSON')
|
|
@@ -26,15 +26,24 @@ function isMonthKey(v) {
|
|
|
26
26
|
&& typeof v.month === 'number'
|
|
27
27
|
&& Number.isFinite(v.month);
|
|
28
28
|
}
|
|
29
|
+
/** mpType 值映射:0=斑马 1=智软 */
|
|
30
|
+
const MP_TYPE_MAP = { '0': '斑马', '1': '智软' };
|
|
31
|
+
function filterBaseline(details, opts) {
|
|
32
|
+
return details.filter(d => (!opts.department || (d.departmentName && d.departmentName.includes(opts.department)))
|
|
33
|
+
&& (!opts.role || (d.role && d.role.includes(opts.role)))
|
|
34
|
+
&& (!opts.area || (d.areaCode && d.areaCode.includes(opts.area)))
|
|
35
|
+
&& (!opts.manpowerType || (d.mpType && MP_TYPE_MAP[d.mpType]?.includes(opts.manpowerType))));
|
|
36
|
+
}
|
|
29
37
|
export async function monthCmd(opts) {
|
|
30
38
|
const pid = getProjectId(opts);
|
|
31
39
|
const months = opts.month ? [opts.month] : expandMonths(opts.from, opts.to);
|
|
32
40
|
const allDetails = [];
|
|
33
41
|
for (const m of months) {
|
|
34
42
|
const data = await fetchBaselineMonth(pid, m);
|
|
35
|
-
// data 是数组,每项含 linePlanMonthDetailList
|
|
36
43
|
for (const item of (data ?? [])) {
|
|
37
44
|
const details = (item.linePlanMonthDetailList ?? []);
|
|
45
|
+
const mpType = String(item.mpType ?? '');
|
|
46
|
+
const areaCode = item.areaCode;
|
|
38
47
|
for (const d of details) {
|
|
39
48
|
if (isMonthKey(d)) {
|
|
40
49
|
allDetails.push({
|
|
@@ -42,14 +51,15 @@ export async function monthCmd(opts) {
|
|
|
42
51
|
manpower: d.manpower ?? 0,
|
|
43
52
|
role: item.role,
|
|
44
53
|
departmentName: item.departmentName,
|
|
54
|
+
mpType,
|
|
55
|
+
areaCode,
|
|
45
56
|
});
|
|
46
57
|
}
|
|
47
58
|
}
|
|
48
59
|
}
|
|
49
60
|
}
|
|
50
|
-
// Apply
|
|
51
|
-
const filtered = allDetails
|
|
52
|
-
&& (!opts.role || (d.role && d.role.includes(opts.role))));
|
|
61
|
+
// Apply filters
|
|
62
|
+
const filtered = filterBaseline(allDetails, opts);
|
|
53
63
|
// 聚合
|
|
54
64
|
const byMonth = new Map();
|
|
55
65
|
for (const d of filtered) {
|
|
@@ -74,16 +84,17 @@ export async function summaryCmd(opts) {
|
|
|
74
84
|
for (const m of months) {
|
|
75
85
|
const data = await fetchBaselineMonth(pid, m);
|
|
76
86
|
for (const item of (data ?? [])) {
|
|
87
|
+
const mpType = String(item.mpType ?? '');
|
|
88
|
+
const areaCode = item.areaCode;
|
|
77
89
|
for (const d of (item.linePlanMonthDetailList ?? [])) {
|
|
78
90
|
if (isMonthKey(d)) {
|
|
79
|
-
allDetails.push({ month: monthTsToKey(d.month), manpower: d.manpower ?? 0, role: item.role, departmentName: item.departmentName });
|
|
91
|
+
allDetails.push({ month: monthTsToKey(d.month), manpower: d.manpower ?? 0, role: item.role, departmentName: item.departmentName, mpType, areaCode });
|
|
80
92
|
}
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
|
-
// Apply
|
|
85
|
-
const filtered = allDetails
|
|
86
|
-
&& (!opts.role || (d.role && d.role.includes(opts.role))));
|
|
96
|
+
// Apply filters
|
|
97
|
+
const filtered = filterBaseline(allDetails, opts);
|
|
87
98
|
const axis = opts.by ?? 'month';
|
|
88
99
|
const groups = new Map();
|
|
89
100
|
for (const d of filtered) {
|
|
@@ -91,7 +91,16 @@ export async function findCmd(kind, query, opts) {
|
|
|
91
91
|
else {
|
|
92
92
|
const dictData = await client.post('/yuntu-service/dictionary/select.json', { dictType: kind });
|
|
93
93
|
const entries = Array.isArray(dictData) ? dictData : [];
|
|
94
|
-
|
|
94
|
+
// 字典 API 忽略 dictType 参数,始终返回全部 181 条。
|
|
95
|
+
// 按 typeDesc 字段在各 kind 间精确过滤
|
|
96
|
+
const kindTypeDesc = {
|
|
97
|
+
'manpower-type': '人力类型',
|
|
98
|
+
'role': '人力基线角色',
|
|
99
|
+
'area': '地域',
|
|
100
|
+
};
|
|
101
|
+
const desc = kindTypeDesc[kind];
|
|
102
|
+
const filtered = desc ? entries.filter(e => e.typeDesc === desc) : entries;
|
|
103
|
+
results = filtered
|
|
95
104
|
.filter((e) => (e.attrName ?? '').includes(query))
|
|
96
105
|
.map((e) => ({ id: e.attrValue ?? '', name: e.attrName ?? '', kind }));
|
|
97
106
|
}
|
|
@@ -7,9 +7,9 @@ const RULES = [
|
|
|
7
7
|
{ pattern: /项目.*列表|列出.*项目|projects/i, command: 'atlas projects', description: '列出所有项目', weight: 10, requiresAuth: true, exitCodes: [0, 2] },
|
|
8
8
|
{ pattern: /绑定|link|关联/i, command: 'atlas link <project>', description: '绑定项目(可省后续 --project-id)', weight: 10, requiresAuth: true, exitCodes: [0, 4, 5] },
|
|
9
9
|
{ pattern: /解绑|unlink/i, command: 'atlas unlink', description: '解绑项目', weight: 10, requiresAuth: true, exitCodes: [0] },
|
|
10
|
-
{ pattern: /搜索|找|find|查询项目/i, command: 'atlas find project <query>', description: '搜索项目(也支持 department/
|
|
10
|
+
{ pattern: /搜索|找|find|查询项目/i, command: 'atlas find project <query>', description: '搜索项目(也支持 department/manpower-type/role/area)', weight: 10, requiresAuth: true, exitCodes: [0, 2] },
|
|
11
11
|
{ pattern: /部门|department/i, command: 'atlas find department <query>', description: '搜索部门', weight: 7, requiresAuth: true, exitCodes: [0, 2] },
|
|
12
|
-
{ pattern: /字典|类型|mp.type|line.plan/i, command: 'atlas find
|
|
12
|
+
{ pattern: /字典|类型|mp.type|line.plan/i, command: 'atlas find manpower-type <query>', description: '搜索 MP 类型字典值', weight: 7, requiresAuth: true, exitCodes: [0, 2] },
|
|
13
13
|
// ── 基线人力 ────────────────────────────
|
|
14
14
|
{ pattern: /基线|计划|baseline|人月.*计划/i, command: 'atlas baseline month --month YYYY-MM', description: '查看指定月份基线人力', weight: 5, requiresAuth: true, exitCodes: [0, 2, 3, 4, 5] },
|
|
15
15
|
{ pattern: /基线.*汇总|baseline.*summar/i, command: 'atlas baseline summary [--by month|department|role]', description: '按月/部门/角色汇总基线人力', weight: 5, requiresAuth: true, exitCodes: [0, 2, 3] },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ATLAS_VERSION = '0.7.
|
|
1
|
+
export const ATLAS_VERSION = '0.7.15';
|