@dreamor/atlas-cli 0.7.9 → 0.7.11

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.
@@ -1,15 +1,13 @@
1
1
  import { createClient } from '../../http/client.js';
2
2
  import { isJsonMode, jsonOk, log } from '../../util/output.js';
3
3
  import { enforceOutputLimit } from '../../util/output-limit.js';
4
- import { ConfigError, SessionExpiredError } from '../../util/errors.js';
5
- import { expandMonths } from '../../util/months.js';
4
+ import { SessionExpiredError } from '../../util/errors.js';
5
+ import { expandMonths, expandMonthsDefault } from '../../util/months.js';
6
6
  import { resolveSecureExportPath, secureWriteFile } from '../../util/secure-fs.js';
7
7
  import { annotateWithMonth, aggregateByAxis, filterByStaff, } from './_logic.js';
8
+ import { resolveProjectId } from '../../util/env.js';
8
9
  function getProjectId(opts) {
9
- const pid = opts.projectId ?? process.env.BANMA_PROJECT_ID ?? '';
10
- if (!pid)
11
- throw new ConfigError('请指定 --project-id 或设置 BANMA_PROJECT_ID 环境变量');
12
- return pid;
10
+ return resolveProjectId(opts.projectId);
13
11
  }
14
12
  async function fetchActual(pid, month) {
15
13
  const client = createClient();
@@ -18,7 +16,7 @@ async function fetchActual(pid, month) {
18
16
  }
19
17
  export async function showCmd(staffId, opts) {
20
18
  const pid = getProjectId(opts);
21
- const m = opts.month ?? expandMonths()[0];
19
+ const m = opts.month ?? expandMonthsDefault()[0];
22
20
  const data = await fetchActual(pid, m);
23
21
  const filtered = filterByStaff(data, staffId);
24
22
  if (opts.json || isJsonMode()) {
@@ -35,7 +33,8 @@ export async function showCmd(staffId, opts) {
35
33
  }
36
34
  export async function monthCmd(opts) {
37
35
  const pid = getProjectId(opts);
38
- const months = opts.month ? [opts.month] : expandMonths(opts.from, opts.to);
36
+ // 不传月份时默认最近 12 个月,与 baseline month 行为一致
37
+ const months = opts.month ? [opts.month] : (opts.from || opts.to ? expandMonths(opts.from, opts.to) : expandMonthsDefault());
39
38
  const all = [];
40
39
  const failedMonths = [];
41
40
  for (const m of months) {
@@ -64,7 +63,7 @@ export async function monthCmd(opts) {
64
63
  }
65
64
  export async function summaryCmd(opts) {
66
65
  const pid = getProjectId(opts);
67
- const months = opts.month ? [opts.month] : expandMonths(opts.from, opts.to);
66
+ const months = opts.month ? [opts.month] : (opts.from || opts.to ? expandMonths(opts.from, opts.to) : expandMonthsDefault());
68
67
  const all = [];
69
68
  const failedMonths = [];
70
69
  for (const m of months) {
@@ -1,15 +1,16 @@
1
1
  import { createClient } from '../../http/client.js';
2
2
  import { isJsonMode, jsonOk, log } from '../../util/output.js';
3
3
  import { enforceOutputLimit } from '../../util/output-limit.js';
4
- import { ConfigError } from '../../util/errors.js';
5
4
  import { expandMonths } from '../../util/months.js';
6
5
  import { monthTsToKey } from '../../util/time.js';
7
6
  import { resolveSecureExportPath, secureWriteFile } from '../../util/secure-fs.js';
7
+ import { resolveProjectId, resolveProjectInfo } from '../../util/env.js';
8
+ function getProjectDisplay(opts) {
9
+ const info = resolveProjectInfo(opts.projectId);
10
+ return info.name ?? info.id;
11
+ }
8
12
  function getProjectId(opts) {
9
- const pid = opts.projectId ?? process.env.BANMA_PROJECT_ID ?? '';
10
- if (!pid)
11
- throw new ConfigError('请指定 --project-id 或设置 BANMA_PROJECT_ID 环境变量');
12
- return pid;
13
+ return resolveProjectId(opts.projectId);
13
14
  }
14
15
  /**
15
16
  * 月基线 API 返回 data 为数组,每项含 linePlanMonthDetailList
@@ -57,7 +58,7 @@ export async function monthCmd(opts) {
57
58
  jsonOk({ projectId: pid, months: monthKeys, entries: allDetails, totalManpower: Math.round(total * 100) / 100 });
58
59
  return;
59
60
  }
60
- log(`项目 ${pid} 基线人力:`);
61
+ log(`项目 ${getProjectDisplay(opts)} 基线人力:`);
61
62
  for (const m of monthKeys) {
62
63
  log(` ${m}: ${(byMonth.get(m) ?? 0).toFixed(2)} 人月`);
63
64
  }
@@ -4,11 +4,9 @@ import { ConfigError, SessionExpiredError } from '../../util/errors.js';
4
4
  import { expandMonths } from '../../util/months.js';
5
5
  import { monthTsToKey } from '../../util/time.js';
6
6
  import { groupByAxis, mergeBaselineActual, } from './_logic.js';
7
+ import { resolveProjectId, resolveProjectInfo } from '../../util/env.js';
7
8
  function getProjectId(opts) {
8
- const pid = opts.projectId ?? process.env.BANMA_PROJECT_ID ?? '';
9
- if (!pid)
10
- throw new ConfigError('请指定 --project-id 或设置 BANMA_PROJECT_ID 环境变量');
11
- return pid;
9
+ return resolveProjectId(opts.projectId);
12
10
  }
13
11
  export async function compareCmd(opts) {
14
12
  const pid = getProjectId(opts);
@@ -63,7 +61,8 @@ export async function compareCmd(opts) {
63
61
  jsonOk({ rows }, { failedMonths });
64
62
  return;
65
63
  }
66
- log(`项目 ${pid} 对比:${axis === 'month' ? '按月份' : axis === 'department' ? '按部门' : '按角色'}`);
64
+ const pinfo = resolveProjectInfo(opts.projectId);
65
+ log(`项目 ${pinfo.name ?? pid} 对比:${axis === 'month' ? '按月份' : axis === 'department' ? '按部门' : '按角色'}`);
67
66
  for (const r of rows) {
68
67
  const flag = opts.flagOverrun && r.actualManpower > r.baselineManpower ? ' ⚠️' : '';
69
68
  log(` ${String(r[axis])}: 基线 ${r.baselineManpower} / 实际 ${r.actualManpower} / 差异 ${r.diff > 0 ? '+' : ''}${r.diff}${flag}`);
@@ -1,7 +1,55 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { getLinkFile } from './paths.js';
3
+ import { ConfigError } from './errors.js';
1
4
  /** 获取 BANMA_PROJECT_ID 环境变量 */
2
5
  export function getBanmaProjectId() {
3
6
  return process.env.BANMA_PROJECT_ID;
4
7
  }
8
+ /**
9
+ * 解析项目 ID,优先级:
10
+ * 1. 命令行 --project-id 参数
11
+ * 2. BANMA_PROJECT_ID 环境变量
12
+ * 3. ~/.atlas/link.json(atlas link 绑定的项目)
13
+ */
14
+ export function resolveProjectId(cliProjectId) {
15
+ if (cliProjectId)
16
+ return cliProjectId;
17
+ if (process.env.BANMA_PROJECT_ID)
18
+ return process.env.BANMA_PROJECT_ID;
19
+ try {
20
+ const linkFile = getLinkFile();
21
+ if (existsSync(linkFile)) {
22
+ const link = JSON.parse(readFileSync(linkFile, 'utf-8'));
23
+ if (link.projectId)
24
+ return link.projectId;
25
+ }
26
+ }
27
+ catch {
28
+ // ignore
29
+ }
30
+ throw new ConfigError('请指定 --project-id、设置 BANMA_PROJECT_ID、或先用 atlas link <project> 绑定项目');
31
+ }
32
+ /**
33
+ * 解析项目信息(ID + 名称),优先级同上。名称仅从 link 文件获取。
34
+ */
35
+ export function resolveProjectInfo(cliProjectId) {
36
+ if (cliProjectId)
37
+ return { id: cliProjectId };
38
+ if (process.env.BANMA_PROJECT_ID)
39
+ return { id: process.env.BANMA_PROJECT_ID };
40
+ try {
41
+ const linkFile = getLinkFile();
42
+ if (existsSync(linkFile)) {
43
+ const link = JSON.parse(readFileSync(linkFile, 'utf-8'));
44
+ if (link.projectId)
45
+ return { id: link.projectId, name: link.projectName };
46
+ }
47
+ }
48
+ catch {
49
+ // ignore
50
+ }
51
+ throw new ConfigError('请指定 --project-id、设置 BANMA_PROJECT_ID、或先用 atlas link <project> 绑定项目');
52
+ }
5
53
  /** 是否禁用自动升级 */
6
54
  export function isUpdateDisabled() {
7
55
  return process.env.ATLAS_DISABLE_UPDATE === '1';
@@ -39,3 +39,27 @@ export function expandMonths(from, to) {
39
39
  }
40
40
  return months;
41
41
  }
42
+ /**
43
+ * 不传月份时的默认范围:当前月及前后各 12 个月(最多 25 个月,低于 MAX_MONTHS)。
44
+ * 使 actual month 无参数时与 baseline month 行为一致。
45
+ */
46
+ export function expandMonthsDefault() {
47
+ const now = new Date();
48
+ const cy = now.getFullYear();
49
+ const cm = now.getMonth() + 1;
50
+ // 12 个月前
51
+ let fy = cy, fm = cm - 12;
52
+ while (fm < 1) {
53
+ fm += 12;
54
+ fy--;
55
+ }
56
+ // 12 个月后
57
+ let ty = cy, tm = cm + 12;
58
+ while (tm > 12) {
59
+ tm -= 12;
60
+ ty++;
61
+ }
62
+ const from = `${fy}-${String(fm).padStart(2, '0')}`;
63
+ const to = `${ty}-${String(tm).padStart(2, '0')}`;
64
+ return expandMonths(from, to);
65
+ }
@@ -1 +1 @@
1
- export const ATLAS_VERSION = '0.7.9';
1
+ export const ATLAS_VERSION = '0.7.11';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreamor/atlas-cli",
3
- "version": "0.7.9",
3
+ "version": "0.7.11",
4
4
  "description": "Atlas CLI - 斑马云图人力基线管理工具",
5
5
  "type": "module",
6
6
  "bin": {