@dreamor/atlas-cli 0.7.11 → 0.7.13
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 +11 -0
- 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/compare/index.js +2 -2
- package/dist/adapters/atlas/commands/project/index.js +3 -3
- package/dist/adapters/atlas/util/version.js +1 -1
- package/package.json +1 -1
|
@@ -146,6 +146,17 @@ function registerProjectCommands(program) {
|
|
|
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
|
+
mp-type 搜索人力类型字典值(例: "商机后-研发项目立项通过"、"研发相关" 等)
|
|
155
|
+
line-plan-type 搜索人力基线角色字典值(例: "开发"、"产品"、"测试"、"PM" 等)
|
|
156
|
+
area-code 搜索地域字典值(仅有: "北上杭"、"合肥"、"武汉"、"西南" 四条)
|
|
157
|
+
|
|
158
|
+
注意: mp-type / line-plan-type / area-code 为字典数据,来源于同一字典 API,
|
|
159
|
+
搜索范围是该字典所有条目的 attrName 字段。`)
|
|
149
160
|
.action(async (kind, query, opts) => {
|
|
150
161
|
try {
|
|
151
162
|
await findCmd(kind, query, opts);
|
|
@@ -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
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createClient } from '../../http/client.js';
|
|
2
2
|
import { isJsonMode, jsonOk, log } from '../../util/output.js';
|
|
3
3
|
import { ConfigError, SessionExpiredError } from '../../util/errors.js';
|
|
4
|
-
import { expandMonths } from '../../util/months.js';
|
|
4
|
+
import { expandMonths, expandMonthsDefault } from '../../util/months.js';
|
|
5
5
|
import { monthTsToKey } from '../../util/time.js';
|
|
6
6
|
import { groupByAxis, mergeBaselineActual, } from './_logic.js';
|
|
7
7
|
import { resolveProjectId, resolveProjectInfo } from '../../util/env.js';
|
|
@@ -10,7 +10,7 @@ function getProjectId(opts) {
|
|
|
10
10
|
}
|
|
11
11
|
export async function compareCmd(opts) {
|
|
12
12
|
const pid = getProjectId(opts);
|
|
13
|
-
const months = opts.month ? [opts.month] : expandMonths(opts.from, opts.to);
|
|
13
|
+
const months = opts.month ? [opts.month] : (opts.from || opts.to ? expandMonths(opts.from, opts.to) : expandMonthsDefault());
|
|
14
14
|
const allBl = [];
|
|
15
15
|
const allAc = [];
|
|
16
16
|
const client = createClient();
|
|
@@ -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
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ATLAS_VERSION = '0.7.
|
|
1
|
+
export const ATLAS_VERSION = '0.7.13';
|