@dreamor/atlas-cli 0.7.12 → 0.7.14
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.
- package/dist/adapters/atlas/cli.js +13 -5
- package/dist/adapters/atlas/commands/actual/index.js +17 -8
- package/dist/adapters/atlas/commands/baseline/index.js +8 -2
- package/dist/adapters/atlas/commands/project/index.js +13 -4
- package/dist/adapters/atlas/commands/suggest.js +2 -2
- package/dist/adapters/atlas/util/version.js +1 -1
- package/package.json +1 -1
|
@@ -142,10 +142,18 @@ 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)')
|
|
149
|
+
.addHelpText('after', `
|
|
150
|
+
kind 说明:
|
|
151
|
+
|
|
152
|
+
project 搜索有权限的项目列表(从 API 实时查询)
|
|
153
|
+
department 搜索部门树中的部门名称(1500+ 部门节点)
|
|
154
|
+
manpower-type 搜索人力类型(仅有: "斑马"、"智软" 两条,baseline --manpower-type 用)
|
|
155
|
+
role 搜索人力基线角色(例: "开发"、"产品"、"测试"、"PM"、"设计" 等)
|
|
156
|
+
area 搜索地域(仅有: "北上杭"、"合肥"、"武汉"、"西南" 四条)`)
|
|
149
157
|
.action(async (kind, query, opts) => {
|
|
150
158
|
try {
|
|
151
159
|
await findCmd(kind, query, opts);
|
|
@@ -212,8 +220,8 @@ function registerBaselineCommands(program) {
|
|
|
212
220
|
.option('--json', '输出 JSON')
|
|
213
221
|
.option('--department <name>', '按部门名称/ID 筛选(子串,不区分大小写)')
|
|
214
222
|
.option('--role <name>', '按角色/备注筛选(子串,不区分大小写)')
|
|
215
|
-
.option('--area
|
|
216
|
-
.option('--
|
|
223
|
+
.option('--area <code>', '按地域筛选(子串,不区分大小写)')
|
|
224
|
+
.option('--manpower-type <type>', '按人力类型筛选(子串,不区分大小写)')
|
|
217
225
|
.option('--month <yyyymm>', '查询月份(YYYY-MM,与 --from/--to 互斥)')
|
|
218
226
|
.option('--from <yyyymm>', '起始月份(YYYY-MM,包含)')
|
|
219
227
|
.option('--to <yyyymm>', '结束月份(YYYY-MM,包含)')
|
|
@@ -233,8 +241,8 @@ function registerBaselineCommands(program) {
|
|
|
233
241
|
.option('--by <axis>', 'month | department | role', 'month')
|
|
234
242
|
.option('--department <name>', '按部门名称/ID 筛选(子串,不区分大小写)')
|
|
235
243
|
.option('--role <name>', '按角色/备注筛选(子串,不区分大小写)')
|
|
236
|
-
.option('--area
|
|
237
|
-
.option('--
|
|
244
|
+
.option('--area <code>', '按地域筛选(子串,不区分大小写)')
|
|
245
|
+
.option('--manpower-type <type>', '按人力类型筛选(子串,不区分大小写)')
|
|
238
246
|
.option('--from <yyyymm>', '起始月份(YYYY-MM,包含)')
|
|
239
247
|
.option('--to <yyyymm>', '结束月份(YYYY-MM,包含)')
|
|
240
248
|
.option('--json', '输出 JSON')
|
|
@@ -49,15 +49,18 @@ export async function monthCmd(opts) {
|
|
|
49
49
|
log(`月 ${m} 拉取失败: ${e instanceof Error ? e.message : e}`);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
// Apply --department / --role filter
|
|
53
|
+
const filtered = all.filter(p => (!opts.department || (p.departmentName && p.departmentName.includes(opts.department)))
|
|
54
|
+
&& (!opts.role || (p.role && p.role.includes(opts.role))));
|
|
52
55
|
if (opts.json || isJsonMode()) {
|
|
53
|
-
jsonOk({ projectId: pid, entries:
|
|
56
|
+
jsonOk({ projectId: pid, entries: filtered }, { failedMonths });
|
|
54
57
|
return;
|
|
55
58
|
}
|
|
56
|
-
if (
|
|
59
|
+
if (filtered.length === 0) {
|
|
57
60
|
log('无实际工时数据');
|
|
58
61
|
return;
|
|
59
62
|
}
|
|
60
|
-
for (const p of
|
|
63
|
+
for (const p of filtered) {
|
|
61
64
|
log(` ${p.staffName}: ${p.manpower.toFixed(2)} (${p.role ?? ''})`);
|
|
62
65
|
}
|
|
63
66
|
}
|
|
@@ -77,8 +80,11 @@ export async function summaryCmd(opts) {
|
|
|
77
80
|
log(`月 ${m} 拉取失败: ${e instanceof Error ? e.message : e}`);
|
|
78
81
|
}
|
|
79
82
|
}
|
|
83
|
+
// Apply --department / --role filter
|
|
84
|
+
const filtered = all.filter(p => (!opts.department || (p.departmentName && p.departmentName.includes(opts.department)))
|
|
85
|
+
&& (!opts.role || (p.role && p.role.includes(opts.role))));
|
|
80
86
|
const axis = (opts.by ?? 'month');
|
|
81
|
-
const rows = aggregateByAxis(
|
|
87
|
+
const rows = aggregateByAxis(filtered, axis);
|
|
82
88
|
if (opts.json || isJsonMode()) {
|
|
83
89
|
jsonOk({ rows }, { failedMonths });
|
|
84
90
|
return;
|
|
@@ -104,14 +110,17 @@ export async function exportCmd(opts) {
|
|
|
104
110
|
log(`月 ${m} 拉取失败: ${e instanceof Error ? e.message : e}`);
|
|
105
111
|
}
|
|
106
112
|
}
|
|
113
|
+
// Apply --department / --role filter
|
|
114
|
+
const filteredRows = rows.filter(p => (!opts.department || (p.departmentName && p.departmentName.includes(opts.department)))
|
|
115
|
+
&& (!opts.role || (p.role && p.role.includes(opts.role))));
|
|
107
116
|
const content = opts.format === 'csv'
|
|
108
|
-
? (await import('papaparse')).default.unparse(
|
|
109
|
-
: JSON.stringify(
|
|
117
|
+
? (await import('papaparse')).default.unparse(filteredRows)
|
|
118
|
+
: JSON.stringify(filteredRows, null, 2);
|
|
110
119
|
enforceOutputLimit(content);
|
|
111
120
|
const safePath = resolveSecureExportPath(opts.out);
|
|
112
121
|
await secureWriteFile(safePath, content);
|
|
113
|
-
log(`已导出 ${
|
|
122
|
+
log(`已导出 ${filteredRows.length} 条记录`);
|
|
114
123
|
if (opts.json || isJsonMode()) {
|
|
115
|
-
jsonOk({ exported:
|
|
124
|
+
jsonOk({ exported: filteredRows.length, format: opts.format, out: safePath }, { failedMonths });
|
|
116
125
|
}
|
|
117
126
|
}
|
|
@@ -47,9 +47,12 @@ export async function monthCmd(opts) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
// Apply --department / --role filter
|
|
51
|
+
const filtered = allDetails.filter(d => (!opts.department || (d.departmentName && d.departmentName.includes(opts.department)))
|
|
52
|
+
&& (!opts.role || (d.role && d.role.includes(opts.role))));
|
|
50
53
|
// 聚合
|
|
51
54
|
const byMonth = new Map();
|
|
52
|
-
for (const d of
|
|
55
|
+
for (const d of filtered) {
|
|
53
56
|
byMonth.set(d.month, (byMonth.get(d.month) ?? 0) + d.manpower);
|
|
54
57
|
}
|
|
55
58
|
const monthKeys = [...byMonth.keys()].sort();
|
|
@@ -78,9 +81,12 @@ export async function summaryCmd(opts) {
|
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
}
|
|
84
|
+
// Apply --department / --role filter
|
|
85
|
+
const filtered = allDetails.filter(d => (!opts.department || (d.departmentName && d.departmentName.includes(opts.department)))
|
|
86
|
+
&& (!opts.role || (d.role && d.role.includes(opts.role))));
|
|
81
87
|
const axis = opts.by ?? 'month';
|
|
82
88
|
const groups = new Map();
|
|
83
|
-
for (const d of
|
|
89
|
+
for (const d of filtered) {
|
|
84
90
|
const k = axis === 'month' ? d.month : axis === 'department' ? (d.departmentName ?? '其他') : (d.role ?? '其他');
|
|
85
91
|
groups.set(k, (groups.get(k) ?? 0) + d.manpower);
|
|
86
92
|
}
|
|
@@ -74,13 +74,13 @@ export async function findCmd(kind, query, opts) {
|
|
|
74
74
|
}
|
|
75
75
|
else if (kind === 'department') {
|
|
76
76
|
const data = await client.post('/yuntu-service/department/tree/select.json', {});
|
|
77
|
-
// 需要确认实际响应格式
|
|
78
77
|
const nodes = Array.isArray(data) ? data : [];
|
|
79
78
|
const flatten = (items) => {
|
|
80
79
|
const r = [];
|
|
81
80
|
for (const n of items) {
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const name = n.deptName ?? '';
|
|
82
|
+
if (name.includes(query))
|
|
83
|
+
r.push({ id: String(n.id ?? n.deptCode ?? ''), name, kind: 'department' });
|
|
84
84
|
if (n.children)
|
|
85
85
|
r.push(...flatten(n.children));
|
|
86
86
|
}
|
|
@@ -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.14';
|