@hangox/pm-cli 0.2.1 → 0.2.2

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/index.js CHANGED
@@ -495,49 +495,49 @@ function addKeyMappingToResult(result) {
495
495
  _key_mapping: mapping
496
496
  };
497
497
  }
498
- function outputToFile(data, filePath) {
498
+ function outputToFile(data, filePath, pretty = false) {
499
499
  const result = {
500
500
  success: true,
501
501
  data
502
502
  };
503
503
  const finalResult = addKeyMappingToResult(result);
504
- writeFileSync2(filePath, JSON.stringify(finalResult, null, 2), "utf-8");
504
+ writeFileSync2(filePath, JSON.stringify(finalResult, null, pretty ? 2 : 0), "utf-8");
505
505
  return filePath;
506
506
  }
507
507
  function smartOutput(data, options) {
508
508
  if (options.stdout) {
509
- outputSuccess(data);
509
+ outputSuccess(data, options.pretty);
510
510
  return void 0;
511
511
  }
512
512
  const filePath = options.output || generateOutputPath(options.command, options.identifier);
513
- outputToFile(data, filePath);
514
- console.log(JSON.stringify({ success: true, output: filePath }, null, 2));
513
+ outputToFile(data, filePath, options.pretty);
514
+ console.log(JSON.stringify({ success: true, output: filePath }, null, options.pretty ? 2 : 0));
515
515
  return filePath;
516
516
  }
517
- function outputSuccess(data) {
517
+ function outputSuccess(data, pretty = false) {
518
518
  const result = {
519
519
  success: true,
520
520
  data
521
521
  };
522
522
  const finalResult = addKeyMappingToResult(result);
523
- console.log(JSON.stringify(finalResult, null, 2));
523
+ console.log(JSON.stringify(finalResult, null, pretty ? 2 : 0));
524
524
  }
525
- function outputError(error) {
525
+ function outputError(error, pretty = false) {
526
526
  const result = {
527
527
  success: false,
528
528
  error
529
529
  };
530
530
  const finalResult = addKeyMappingToResult(result);
531
- console.log(JSON.stringify(finalResult, null, 2));
531
+ console.log(JSON.stringify(finalResult, null, pretty ? 2 : 0));
532
532
  }
533
533
 
534
534
  // src/commands/test.ts
535
535
  function createTestCommand() {
536
- const testCmd = new Command("test").description("\u6D4B\u8BD5\u7F51\u6613\u6613\u534F\u4F5C\u8FDE\u63A5").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
536
+ const testCmd = new Command("test").description("\u6D4B\u8BD5\u7F51\u6613\u6613\u534F\u4F5C\u8FDE\u63A5").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
537
537
  const creds = resolveCredentials(options);
538
538
  const validation = validateCredentials(creds);
539
539
  if (!validation.valid) {
540
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
540
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
541
541
  process.exit(1);
542
542
  }
543
543
  const result = await userService.testConnection(
@@ -551,9 +551,9 @@ function createTestCommand() {
551
551
  host: creds.host,
552
552
  project: creds.project,
553
553
  data: result.data
554
- });
554
+ }, options.pretty);
555
555
  } else {
556
- outputError(result.message || result.msg || result.api_error_msg || "\u8FDE\u63A5\u5931\u8D25");
556
+ outputError(result.message || result.msg || result.api_error_msg || "\u8FDE\u63A5\u5931\u8D25", options.pretty);
557
557
  process.exit(1);
558
558
  }
559
559
  });
@@ -564,40 +564,40 @@ function createTestCommand() {
564
564
  import { Command as Command2 } from "commander";
565
565
  function createConfigCommand() {
566
566
  const configCmd = new Command2("config").description("\u914D\u7F6E\u7BA1\u7406");
567
- configCmd.command("set <key> <value>").description("\u8BBE\u7F6E\u914D\u7F6E\u9879").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action((key, value, options) => {
567
+ configCmd.command("set <key> <value>").description("\u8BBE\u7F6E\u914D\u7F6E\u9879").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action((key, value, options) => {
568
568
  setConfigValue(key, value, options.config);
569
569
  outputSuccess({
570
570
  message: `\u914D\u7F6E\u9879 ${key} \u5DF2\u8BBE\u7F6E`,
571
571
  key,
572
572
  value,
573
573
  configPath: getConfigPath(options.config)
574
- });
574
+ }, options.pretty);
575
575
  });
576
- configCmd.command("get <key>").description("\u83B7\u53D6\u914D\u7F6E\u9879").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action((key, options) => {
576
+ configCmd.command("get <key>").description("\u83B7\u53D6\u914D\u7F6E\u9879").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action((key, options) => {
577
577
  const value = getConfigValue(key, options.config);
578
578
  if (value !== void 0) {
579
- outputSuccess({ key, value });
579
+ outputSuccess({ key, value }, options.pretty);
580
580
  } else {
581
- outputError(`\u914D\u7F6E\u9879 ${key} \u4E0D\u5B58\u5728`);
581
+ outputError(`\u914D\u7F6E\u9879 ${key} \u4E0D\u5B58\u5728`, options.pretty);
582
582
  process.exit(1);
583
583
  }
584
584
  });
585
- configCmd.command("list").description("\u5217\u51FA\u6240\u6709\u914D\u7F6E").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action((options) => {
585
+ configCmd.command("list").description("\u5217\u51FA\u6240\u6709\u914D\u7F6E").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action((options) => {
586
586
  const config = readConfig(options.config);
587
587
  outputSuccess({
588
588
  configPath: getConfigPath(options.config),
589
589
  config
590
- });
590
+ }, options.pretty);
591
591
  });
592
592
  const profileCmd = new Command2("profile").description("Profile \u7BA1\u7406");
593
- profileCmd.command("add <name>").description("\u6DFB\u52A0 profile").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--token <token>", "API Token").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(
593
+ profileCmd.command("add <name>").description("\u6DFB\u52A0 profile").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--token <token>", "API Token").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(
594
594
  (name, options) => {
595
595
  const profile = {};
596
596
  if (options.host) profile.host = options.host;
597
597
  if (options.project) profile.project = options.project;
598
598
  if (options.token) profile.token = options.token;
599
599
  if (Object.keys(profile).length === 0) {
600
- outputError("\u8BF7\u81F3\u5C11\u6307\u5B9A\u4E00\u4E2A\u914D\u7F6E\u9879 (--host, --project, --token)");
600
+ outputError("\u8BF7\u81F3\u5C11\u6307\u5B9A\u4E00\u4E2A\u914D\u7F6E\u9879 (--host, --project, --token)", options.pretty);
601
601
  process.exit(1);
602
602
  }
603
603
  setProfile(name, profile, options.config);
@@ -605,19 +605,19 @@ function createConfigCommand() {
605
605
  message: `Profile ${name} \u5DF2\u6DFB\u52A0`,
606
606
  name,
607
607
  profile
608
- });
608
+ }, options.pretty);
609
609
  }
610
610
  );
611
- profileCmd.command("remove <name>").description("\u5220\u9664 profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action((name, options) => {
611
+ profileCmd.command("remove <name>").description("\u5220\u9664 profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action((name, options) => {
612
612
  const removed = removeProfile(name, options.config);
613
613
  if (removed) {
614
- outputSuccess({ message: `Profile ${name} \u5DF2\u5220\u9664`, name });
614
+ outputSuccess({ message: `Profile ${name} \u5DF2\u5220\u9664`, name }, options.pretty);
615
615
  } else {
616
- outputError(`Profile ${name} \u4E0D\u5B58\u5728`);
616
+ outputError(`Profile ${name} \u4E0D\u5B58\u5728`, options.pretty);
617
617
  process.exit(1);
618
618
  }
619
619
  });
620
- profileCmd.command("list").description("\u5217\u51FA\u6240\u6709 profiles").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action((options) => {
620
+ profileCmd.command("list").description("\u5217\u51FA\u6240\u6709 profiles").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action((options) => {
621
621
  const profiles = listProfiles(options.config);
622
622
  const profileDetails = {};
623
623
  for (const name of profiles) {
@@ -626,7 +626,7 @@ function createConfigCommand() {
626
626
  outputSuccess({
627
627
  profiles: profileDetails,
628
628
  count: profiles.length
629
- });
629
+ }, options.pretty);
630
630
  });
631
631
  configCmd.addCommand(profileCmd);
632
632
  return configCmd;
@@ -636,6 +636,9 @@ function createConfigCommand() {
636
636
  import { Command as Command3 } from "commander";
637
637
 
638
638
  // src/services/issue-service.ts
639
+ function sleep(ms) {
640
+ return new Promise((resolve) => setTimeout(resolve, ms));
641
+ }
639
642
  var IssueService = class {
640
643
  /**
641
644
  * 获取问题详情
@@ -882,6 +885,241 @@ var IssueService = class {
882
885
  data: results
883
886
  };
884
887
  }
888
+ /**
889
+ * 同步子单:从源父单复制子单到目标父单
890
+ * @param sourceParentId 源父单 ID
891
+ * @param targetParentId 目标父单 ID
892
+ * @param assignedToMail 新子单的指派人邮箱
893
+ * @param options 选项
894
+ */
895
+ async syncChildIssues(token, host, project, sourceParentId, targetParentId, assignedToMail, options) {
896
+ const { dryRun = false, depth = 10, skipExisting = true } = options || {};
897
+ logger_default.info("\u5F00\u59CB\u540C\u6B65\u5B50\u5355", {
898
+ sourceParentId,
899
+ targetParentId,
900
+ assignedToMail,
901
+ dryRun,
902
+ depth,
903
+ skipExisting
904
+ });
905
+ const result = {
906
+ totalCreated: 0,
907
+ totalSkipped: 0,
908
+ totalFailed: 0,
909
+ created: [],
910
+ skipped: [],
911
+ failed: []
912
+ };
913
+ try {
914
+ logger_default.info("\u6B63\u5728\u83B7\u53D6\u6E90\u7236\u5355\u7684\u5B50\u5355\u6811\u5F62\u7ED3\u6784...");
915
+ const sourceResult = await this.getIssueWithChildren(token, host, project, sourceParentId, depth);
916
+ if (!sourceResult.success || !sourceResult.data) {
917
+ return {
918
+ success: false,
919
+ message: `\u83B7\u53D6\u6E90\u7236\u5355 #${sourceParentId} \u5931\u8D25: ${sourceResult.message || "\u672A\u77E5\u9519\u8BEF"}`
920
+ };
921
+ }
922
+ const sourceIssue = sourceResult.data;
923
+ logger_default.info("\u6B63\u5728\u83B7\u53D6\u76EE\u6807\u7236\u5355\u4FE1\u606F...");
924
+ const targetResult = await this.getIssue(token, host, project, targetParentId, false, false);
925
+ if (!targetResult.success || !targetResult.data) {
926
+ return {
927
+ success: false,
928
+ message: `\u83B7\u53D6\u76EE\u6807\u7236\u5355 #${targetParentId} \u5931\u8D25: ${targetResult.message || "\u672A\u77E5\u9519\u8BEF"}`
929
+ };
930
+ }
931
+ const targetParentInfo = targetResult.data;
932
+ let existingTaskNames = /* @__PURE__ */ new Set();
933
+ if (skipExisting) {
934
+ logger_default.info("\u6B63\u5728\u83B7\u53D6\u76EE\u6807\u7236\u5355\u5DF2\u6709\u7684\u5B50\u5355...");
935
+ const existingResult = await this.getIssueWithChildren(token, host, project, targetParentId, depth);
936
+ if (existingResult.success && existingResult.data) {
937
+ existingTaskNames = this.collectAllTaskNames(existingResult.data);
938
+ logger_default.info(`\u76EE\u6807\u7236\u5355\u5DF2\u6709 ${existingTaskNames.size} \u4E2A\u5B50\u5355`);
939
+ }
940
+ }
941
+ logger_default.info("\u5F00\u59CB\u9012\u5F52\u540C\u6B65\u5B50\u5355...");
942
+ await this.syncChildrenRecursive(
943
+ token,
944
+ host,
945
+ project,
946
+ sourceIssue,
947
+ targetParentId,
948
+ targetParentInfo,
949
+ existingTaskNames,
950
+ assignedToMail,
951
+ dryRun,
952
+ result
953
+ );
954
+ logger_default.info("\u540C\u6B65\u5B8C\u6210", {
955
+ totalCreated: result.totalCreated,
956
+ totalSkipped: result.totalSkipped,
957
+ totalFailed: result.totalFailed
958
+ });
959
+ return { success: true, data: result };
960
+ } catch (error) {
961
+ logger_default.error("\u540C\u6B65\u5B50\u5355\u65F6\u53D1\u751F\u9519\u8BEF", error);
962
+ return {
963
+ success: false,
964
+ message: `\u540C\u6B65\u5B50\u5355\u65F6\u53D1\u751F\u9519\u8BEF: ${error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"}`
965
+ };
966
+ }
967
+ }
968
+ /**
969
+ * 收集所有任务名称(递归)
970
+ */
971
+ collectAllTaskNames(issue) {
972
+ const names = /* @__PURE__ */ new Set();
973
+ if (issue.subject?.trim()) {
974
+ names.add(issue.subject.trim());
975
+ }
976
+ for (const child of issue.children || []) {
977
+ const childNames = this.collectAllTaskNames(child);
978
+ childNames.forEach((name) => names.add(name));
979
+ }
980
+ return names;
981
+ }
982
+ /**
983
+ * 递归同步子单
984
+ */
985
+ async syncChildrenRecursive(token, host, project, sourceNode, targetParentId, targetParentInfo, existingTaskNames, assignedToMail, dryRun, result) {
986
+ for (const child of sourceNode.children || []) {
987
+ const taskName = child.subject?.trim() || "\u672A\u547D\u540D\u4EFB\u52A1";
988
+ const sourceId = child.id;
989
+ if (existingTaskNames.has(taskName)) {
990
+ logger_default.info(`\u23ED\uFE0F \u8DF3\u8FC7\u5DF2\u5B58\u5728\u7684\u4EFB\u52A1: ${taskName}`);
991
+ result.totalSkipped++;
992
+ result.skipped.push({
993
+ sourceId,
994
+ subject: taskName,
995
+ reason: "\u76EE\u6807\u7236\u5355\u4E0B\u5DF2\u5B58\u5728\u540C\u540D\u4EFB\u52A1"
996
+ });
997
+ continue;
998
+ }
999
+ const isLeafNode = !child.children || child.children.length === 0;
1000
+ const createParams = {
1001
+ token,
1002
+ host,
1003
+ project,
1004
+ parent_issue_id: targetParentId,
1005
+ subject: taskName,
1006
+ // 继承自目标父单
1007
+ tracker: targetParentInfo.tracker?.name,
1008
+ status: "\u65B0\u5EFA",
1009
+ // 覆盖指派人为"我"
1010
+ assigned_to_mail: assignedToMail,
1011
+ // 只有叶子节点才设置工时
1012
+ estimated_hours: isLeafNode ? child.estimated_hours : void 0,
1013
+ // 保留原任务的优先级
1014
+ priority_id: child.priority?.id
1015
+ };
1016
+ const targetWithVersion = targetParentInfo;
1017
+ if (targetWithVersion.fixed_version?.name) {
1018
+ createParams.version = targetWithVersion.fixed_version.name;
1019
+ }
1020
+ const targetWithCustomFields = targetParentInfo;
1021
+ if (targetWithCustomFields.custom_fields && targetWithCustomFields.custom_fields.length > 0) {
1022
+ const customFieldMap = {};
1023
+ const followsMails = [];
1024
+ for (const field of targetWithCustomFields.custom_fields) {
1025
+ if (field.value !== null && field.value !== void 0 && field.value !== "") {
1026
+ if (field.identify === "IssuesQCFollow") {
1027
+ const followsValue = field.value;
1028
+ if (Array.isArray(followsValue)) {
1029
+ for (const item of followsValue) {
1030
+ if (item.user?.mail) {
1031
+ followsMails.push(item.user.mail);
1032
+ }
1033
+ }
1034
+ }
1035
+ } else {
1036
+ customFieldMap[field.id] = field.value;
1037
+ }
1038
+ }
1039
+ }
1040
+ if (Object.keys(customFieldMap).length > 0) {
1041
+ createParams.custom_field = JSON.stringify(customFieldMap);
1042
+ }
1043
+ if (followsMails.length > 0) {
1044
+ createParams.follows = followsMails;
1045
+ }
1046
+ }
1047
+ logger_default.info(`\u6B63\u5728\u521B\u5EFA\u5B50\u4EFB\u52A1: ${taskName}`, { sourceId, targetParentId, isLeafNode });
1048
+ if (dryRun) {
1049
+ logger_default.info(`[\u6A21\u62DF] \u5C06\u521B\u5EFA\u5B50\u4EFB\u52A1: ${taskName}`);
1050
+ result.totalCreated++;
1051
+ result.created.push({
1052
+ sourceId,
1053
+ newId: 0,
1054
+ // 模拟模式没有真实 ID
1055
+ subject: taskName,
1056
+ parentId: targetParentId
1057
+ });
1058
+ if (child.children && child.children.length > 0) {
1059
+ await this.syncChildrenRecursive(
1060
+ token,
1061
+ host,
1062
+ project,
1063
+ child,
1064
+ 0,
1065
+ // 模拟模式下没有真实的新 ID
1066
+ targetParentInfo,
1067
+ existingTaskNames,
1068
+ assignedToMail,
1069
+ dryRun,
1070
+ result
1071
+ );
1072
+ }
1073
+ } else {
1074
+ try {
1075
+ const createResult = await this.createIssue(createParams);
1076
+ if (createResult.success && createResult.data) {
1077
+ const newId = createResult.data.id;
1078
+ logger_default.info(`\u2705 \u6210\u529F\u521B\u5EFA\u5B50\u4EFB\u52A1: ID=${newId}, \u6807\u9898=${taskName}`);
1079
+ result.totalCreated++;
1080
+ result.created.push({
1081
+ sourceId,
1082
+ newId,
1083
+ subject: taskName,
1084
+ parentId: targetParentId
1085
+ });
1086
+ if (child.children && child.children.length > 0) {
1087
+ logger_default.info(`\u{1F4C1} \u53D1\u73B0\u5B50\u4EFB\u52A1 ${newId} \u6709 ${child.children.length} \u4E2A\u5B50\u4EFB\u52A1\uFF0C\u7EE7\u7EED\u9012\u5F52\u521B\u5EFA...`);
1088
+ await this.syncChildrenRecursive(
1089
+ token,
1090
+ host,
1091
+ project,
1092
+ child,
1093
+ newId,
1094
+ targetParentInfo,
1095
+ existingTaskNames,
1096
+ assignedToMail,
1097
+ dryRun,
1098
+ result
1099
+ );
1100
+ }
1101
+ } else {
1102
+ logger_default.error(`\u274C \u521B\u5EFA\u5B50\u4EFB\u52A1\u5931\u8D25: ${taskName}`, createResult.message || createResult.api_error_msg);
1103
+ result.totalFailed++;
1104
+ result.failed.push({
1105
+ sourceId,
1106
+ subject: taskName,
1107
+ error: createResult.message || createResult.api_error_msg || "\u521B\u5EFA\u5931\u8D25"
1108
+ });
1109
+ }
1110
+ } catch (error) {
1111
+ logger_default.error(`\u274C \u521B\u5EFA\u5B50\u4EFB\u52A1\u65F6\u53D1\u751F\u9519\u8BEF: ${taskName}`, error);
1112
+ result.totalFailed++;
1113
+ result.failed.push({
1114
+ sourceId,
1115
+ subject: taskName,
1116
+ error: error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"
1117
+ });
1118
+ }
1119
+ await sleep(500);
1120
+ }
1121
+ }
1122
+ }
885
1123
  };
886
1124
  var issueService = new IssueService();
887
1125
 
@@ -913,13 +1151,13 @@ function parsePmLink(url) {
913
1151
  // src/commands/issue/index.ts
914
1152
  function createIssueCommand() {
915
1153
  const issueCmd = new Command3("issue").description("\u95EE\u9898\u7BA1\u7406");
916
- issueCmd.command("get [id]").description("\u83B7\u53D6\u95EE\u9898\u8BE6\u60C5\uFF08\u9ED8\u8BA4\u9012\u5F52\u83B7\u53D6\u5B50\u5355\uFF0C\u8F93\u51FA\u5230\u6587\u4EF6\uFF09").option("--url <url>", "PM \u94FE\u63A5").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--depth <depth>", "\u9012\u5F52\u83B7\u53D6\u5B50\u5355\u7684\u6DF1\u5EA6\uFF080 \u8868\u793A\u4E0D\u83B7\u53D6\u5B50\u5355\uFF09", "10").option("-o, --output <path>", "\u8F93\u51FA JSON \u5230\u6307\u5B9A\u6587\u4EF6\uFF08\u9ED8\u8BA4\u8F93\u51FA\u5230 /tmp\uFF09").option("--stdout", "\u5F3A\u5236\u8F93\u51FA\u5230\u63A7\u5236\u53F0\u800C\u975E\u6587\u4EF6").option("--include-relations", "\u5305\u542B\u5173\u8054\u95EE\u9898").action(async (id, options) => {
1154
+ issueCmd.command("get [id]").description("\u83B7\u53D6\u95EE\u9898\u8BE6\u60C5\uFF08\u9ED8\u8BA4\u9012\u5F52\u83B7\u53D6\u5B50\u5355\uFF0C\u8F93\u51FA\u5230\u6587\u4EF6\uFF09").option("--url <url>", "PM \u94FE\u63A5").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--depth <depth>", "\u9012\u5F52\u83B7\u53D6\u5B50\u5355\u7684\u6DF1\u5EA6\uFF080 \u8868\u793A\u4E0D\u83B7\u53D6\u5B50\u5355\uFF09", "10").option("-o, --output <path>", "\u8F93\u51FA JSON \u5230\u6307\u5B9A\u6587\u4EF6\uFF08\u9ED8\u8BA4\u8F93\u51FA\u5230 /tmp\uFF09").option("--stdout", "\u5F3A\u5236\u8F93\u51FA\u5230\u63A7\u5236\u53F0\u800C\u975E\u6587\u4EF6").option("--include-relations", "\u5305\u542B\u5173\u8054\u95EE\u9898").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (id, options) => {
917
1155
  let issueId;
918
1156
  let host;
919
1157
  if (options.url) {
920
1158
  const linkInfo = parsePmLink(options.url);
921
1159
  if (!linkInfo) {
922
- outputError("\u65E0\u6548\u7684 PM \u94FE\u63A5\u683C\u5F0F");
1160
+ outputError("\u65E0\u6548\u7684 PM \u94FE\u63A5\u683C\u5F0F", options.pretty);
923
1161
  process.exit(1);
924
1162
  }
925
1163
  issueId = parseInt(linkInfo.issueId, 10);
@@ -928,11 +1166,11 @@ function createIssueCommand() {
928
1166
  const cleanId = id.replace(/^#/, "");
929
1167
  issueId = parseInt(cleanId, 10);
930
1168
  if (isNaN(issueId)) {
931
- outputError("\u65E0\u6548\u7684\u95EE\u9898 ID");
1169
+ outputError("\u65E0\u6548\u7684\u95EE\u9898 ID", options.pretty);
932
1170
  process.exit(1);
933
1171
  }
934
1172
  } else {
935
- outputError("\u8BF7\u63D0\u4F9B\u95EE\u9898 ID \u6216 --url \u53C2\u6570");
1173
+ outputError("\u8BF7\u63D0\u4F9B\u95EE\u9898 ID \u6216 --url \u53C2\u6570", options.pretty);
936
1174
  process.exit(1);
937
1175
  }
938
1176
  const creds = resolveCredentials({
@@ -941,7 +1179,7 @@ function createIssueCommand() {
941
1179
  });
942
1180
  const validation = validateCredentials(creds, ["token", "host"]);
943
1181
  if (!validation.valid) {
944
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1182
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
945
1183
  process.exit(1);
946
1184
  }
947
1185
  const depth = parseInt(options.depth, 10);
@@ -958,10 +1196,11 @@ function createIssueCommand() {
958
1196
  stdout: options.stdout,
959
1197
  output: options.output,
960
1198
  command: "issue-get",
961
- identifier: issueId.toString()
1199
+ identifier: issueId.toString(),
1200
+ pretty: options.pretty
962
1201
  });
963
1202
  } else {
964
- outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u95EE\u9898\u5931\u8D25");
1203
+ outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u95EE\u9898\u5931\u8D25", options.pretty);
965
1204
  process.exit(1);
966
1205
  }
967
1206
  } else {
@@ -978,19 +1217,20 @@ function createIssueCommand() {
978
1217
  stdout: options.stdout,
979
1218
  output: options.output,
980
1219
  command: "issue-get",
981
- identifier: issueId.toString()
1220
+ identifier: issueId.toString(),
1221
+ pretty: options.pretty
982
1222
  });
983
1223
  } else {
984
- outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u95EE\u9898\u5931\u8D25");
1224
+ outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u95EE\u9898\u5931\u8D25", options.pretty);
985
1225
  process.exit(1);
986
1226
  }
987
1227
  }
988
1228
  });
989
- issueCmd.command("create").description("\u521B\u5EFA\u95EE\u9898").requiredOption("--subject <subject>", "\u95EE\u9898\u6807\u9898").option("--description <description>", "\u95EE\u9898\u63CF\u8FF0").option("--tracker <tracker>", "\u8DDF\u8E2A\u5668\u540D\u79F0").option("--tracker-id <id>", "\u8DDF\u8E2A\u5668 ID").option("--priority-id <id>", "\u4F18\u5148\u7EA7 ID").option("--assigned-to-mail <email>", "\u6307\u6D3E\u4EBA\u90AE\u7BB1").option("--assigned-to-id <id>", "\u6307\u6D3E\u4EBA ID").option("--parent-id <id>", "\u7236\u95EE\u9898 ID\uFF08\u5B50\u5355\u4F1A\u7EE7\u627F\u7236\u5355\u7684 tracker\u3001version\u3001assigned_to \u7B49\u4FE1\u606F\uFF09").option("--version <version>", "\u76EE\u6807\u7248\u672C\u540D\u79F0").option("--start-date <date>", "\u5F00\u59CB\u65E5\u671F").option("--due-date <date>", "\u622A\u6B62\u65E5\u671F").option("--estimated-hours <hours>", "\u9884\u4F30\u5DE5\u65F6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
1229
+ issueCmd.command("create").description("\u521B\u5EFA\u95EE\u9898").requiredOption("--subject <subject>", "\u95EE\u9898\u6807\u9898").option("--description <description>", "\u95EE\u9898\u63CF\u8FF0").option("--tracker <tracker>", "\u8DDF\u8E2A\u5668\u540D\u79F0").option("--tracker-id <id>", "\u8DDF\u8E2A\u5668 ID").option("--priority-id <id>", "\u4F18\u5148\u7EA7 ID").option("--assigned-to-mail <email>", "\u6307\u6D3E\u4EBA\u90AE\u7BB1").option("--assigned-to-id <id>", "\u6307\u6D3E\u4EBA ID").option("--parent-id <id>", "\u7236\u95EE\u9898 ID\uFF08\u5B50\u5355\u4F1A\u7EE7\u627F\u7236\u5355\u7684 tracker\u3001version\u3001assigned_to \u7B49\u4FE1\u606F\uFF09").option("--version <version>", "\u76EE\u6807\u7248\u672C\u540D\u79F0").option("--start-date <date>", "\u5F00\u59CB\u65E5\u671F").option("--due-date <date>", "\u622A\u6B62\u65E5\u671F").option("--estimated-hours <hours>", "\u9884\u4F30\u5DE5\u65F6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
990
1230
  const creds = resolveCredentials(options);
991
1231
  const validation = validateCredentials(creds);
992
1232
  if (!validation.valid) {
993
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1233
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
994
1234
  process.exit(1);
995
1235
  }
996
1236
  const params = {
@@ -1052,7 +1292,7 @@ function createIssueCommand() {
1052
1292
  }
1053
1293
  }
1054
1294
  } else {
1055
- outputError(`\u65E0\u6CD5\u83B7\u53D6\u7236\u5355 #${parentId} \u7684\u4FE1\u606F: ${parentResult.message || "\u672A\u77E5\u9519\u8BEF"}`);
1295
+ outputError(`\u65E0\u6CD5\u83B7\u53D6\u7236\u5355 #${parentId} \u7684\u4FE1\u606F: ${parentResult.message || "\u672A\u77E5\u9519\u8BEF"}`, options.pretty);
1056
1296
  process.exit(1);
1057
1297
  }
1058
1298
  params.parent_issue_id = parentId;
@@ -1069,19 +1309,19 @@ function createIssueCommand() {
1069
1309
  if (options.estimatedHours) params.estimated_hours = parseFloat(options.estimatedHours);
1070
1310
  const result = await issueService.createIssue(params);
1071
1311
  if (result.success && result.data) {
1072
- outputSuccess(result.data);
1312
+ outputSuccess(result.data, options.pretty);
1073
1313
  } else {
1074
- outputError(result.message || result.msg || result.api_error_msg || "\u521B\u5EFA\u95EE\u9898\u5931\u8D25");
1314
+ outputError(result.message || result.msg || result.api_error_msg || "\u521B\u5EFA\u95EE\u9898\u5931\u8D25", options.pretty);
1075
1315
  process.exit(1);
1076
1316
  }
1077
1317
  });
1078
- issueCmd.command("update <id>").description("\u66F4\u65B0\u95EE\u9898").option("--subject <subject>", "\u95EE\u9898\u6807\u9898").option("--description <description>", "\u95EE\u9898\u63CF\u8FF0").option("--status <status>", "\u72B6\u6001\u540D\u79F0 (\u5982: \u65B0\u5EFA\u3001\u5F00\u53D1\u4E2D\u3001\u5DF2\u89E3\u51B3)").option("--tracker <tracker>", "\u8DDF\u8E2A\u6807\u7B7E\u540D\u79F0 (\u5982: BUG\u3001\u4EFB\u52A1)").option("--version <version>", "\u76EE\u6807\u7248\u672C\u540D\u79F0").option("--assigned-to-mail <email>", "\u6307\u6D3E\u4EBA\u90AE\u7BB1").option("--notes <notes>", "\u66F4\u65B0\u8BF4\u660E/\u5907\u6CE8").option("--start-date <date>", "\u5F00\u59CB\u65E5\u671F (\u683C\u5F0F: YYYY-MM-DD)").option("--due-date <date>", "\u622A\u6B62\u65E5\u671F (\u683C\u5F0F: YYYY-MM-DD)").option("--estimated-hours <hours>", "\u9884\u4F30\u5DE5\u65F6").option("--follows <email>", "\u8DDF\u8FDBQA\u90AE\u7BB1").option("--url <url>", "PM \u94FE\u63A5 (\u81EA\u52A8\u89E3\u6790 host \u548C issue_id)").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (id, options) => {
1318
+ issueCmd.command("update <id>").description("\u66F4\u65B0\u95EE\u9898").option("--subject <subject>", "\u95EE\u9898\u6807\u9898").option("--description <description>", "\u95EE\u9898\u63CF\u8FF0").option("--status <status>", "\u72B6\u6001\u540D\u79F0 (\u5982: \u65B0\u5EFA\u3001\u5F00\u53D1\u4E2D\u3001\u5DF2\u89E3\u51B3)").option("--tracker <tracker>", "\u8DDF\u8E2A\u6807\u7B7E\u540D\u79F0 (\u5982: BUG\u3001\u4EFB\u52A1)").option("--version <version>", "\u76EE\u6807\u7248\u672C\u540D\u79F0").option("--assigned-to-mail <email>", "\u6307\u6D3E\u4EBA\u90AE\u7BB1").option("--notes <notes>", "\u66F4\u65B0\u8BF4\u660E/\u5907\u6CE8").option("--start-date <date>", "\u5F00\u59CB\u65E5\u671F (\u683C\u5F0F: YYYY-MM-DD)").option("--due-date <date>", "\u622A\u6B62\u65E5\u671F (\u683C\u5F0F: YYYY-MM-DD)").option("--estimated-hours <hours>", "\u9884\u4F30\u5DE5\u65F6").option("--follows <email>", "\u8DDF\u8FDBQA\u90AE\u7BB1").option("--custom-field <json>", `\u81EA\u5B9A\u4E49\u5B57\u6BB5 (JSON\u683C\u5F0F\uFF0C\u5982: '{"123":"value"}'\uFF0C\u652F\u6301\u4F20\u5165\u5B57\u6BB5\u540D\u6216\u5B57\u6BB5ID)`).option("--url <url>", "PM \u94FE\u63A5 (\u81EA\u52A8\u89E3\u6790 host \u548C issue_id)").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (id, options) => {
1079
1319
  let issueId;
1080
1320
  let urlHost;
1081
1321
  if (options.url) {
1082
1322
  const linkInfo = parsePmLink(options.url);
1083
1323
  if (!linkInfo) {
1084
- outputError("\u65E0\u6548\u7684 PM \u94FE\u63A5\u683C\u5F0F");
1324
+ outputError("\u65E0\u6548\u7684 PM \u94FE\u63A5\u683C\u5F0F", options.pretty);
1085
1325
  process.exit(1);
1086
1326
  }
1087
1327
  issueId = parseInt(linkInfo.issueId, 10);
@@ -1089,7 +1329,7 @@ function createIssueCommand() {
1089
1329
  } else {
1090
1330
  issueId = parseInt(id.replace(/^#/, ""), 10);
1091
1331
  if (isNaN(issueId)) {
1092
- outputError("\u65E0\u6548\u7684\u95EE\u9898 ID");
1332
+ outputError("\u65E0\u6548\u7684\u95EE\u9898 ID", options.pretty);
1093
1333
  process.exit(1);
1094
1334
  }
1095
1335
  }
@@ -1099,7 +1339,7 @@ function createIssueCommand() {
1099
1339
  });
1100
1340
  const validation = validateCredentials(creds);
1101
1341
  if (!validation.valid) {
1102
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1342
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1103
1343
  process.exit(1);
1104
1344
  }
1105
1345
  const params = {
@@ -1119,19 +1359,66 @@ function createIssueCommand() {
1119
1359
  if (options.dueDate) params.due_date = options.dueDate;
1120
1360
  if (options.estimatedHours) params.estimated_hours = parseFloat(options.estimatedHours);
1121
1361
  if (options.follows) params.follows = options.follows;
1362
+ if (options.customField) {
1363
+ try {
1364
+ const customFieldData = JSON.parse(options.customField);
1365
+ const hasNonNumericKey = Object.keys(customFieldData).some((key) => isNaN(Number(key)));
1366
+ if (hasNonNumericKey) {
1367
+ const fieldOptionsResult = await issueService.getIssueFieldOptions(
1368
+ creds.token,
1369
+ creds.host,
1370
+ creds.project
1371
+ );
1372
+ if (fieldOptionsResult.success && fieldOptionsResult.data) {
1373
+ const fieldOptions = fieldOptionsResult.data;
1374
+ if (fieldOptions.data?.custom_fields) {
1375
+ const fieldMap = /* @__PURE__ */ new Map();
1376
+ for (const field of fieldOptions.data.custom_fields) {
1377
+ fieldMap.set(field.name, field.id);
1378
+ }
1379
+ const convertedData = {};
1380
+ for (const [key, value] of Object.entries(customFieldData)) {
1381
+ const fieldId = isNaN(Number(key)) ? fieldMap.get(key) : Number(key);
1382
+ if (fieldId !== void 0) {
1383
+ convertedData[fieldId] = value;
1384
+ } else {
1385
+ outputError(`\u672A\u627E\u5230\u81EA\u5B9A\u4E49\u5B57\u6BB5: ${key}`, options.pretty);
1386
+ process.exit(1);
1387
+ }
1388
+ }
1389
+ params.custom_field = JSON.stringify(convertedData);
1390
+ } else {
1391
+ outputError("\u65E0\u6CD5\u83B7\u53D6\u81EA\u5B9A\u4E49\u5B57\u6BB5\u5217\u8868", options.pretty);
1392
+ process.exit(1);
1393
+ }
1394
+ } else {
1395
+ outputError("\u83B7\u53D6\u81EA\u5B9A\u4E49\u5B57\u6BB5\u5217\u8868\u5931\u8D25", options.pretty);
1396
+ process.exit(1);
1397
+ }
1398
+ } else {
1399
+ params.custom_field = JSON.stringify(customFieldData);
1400
+ }
1401
+ } catch (error) {
1402
+ outputError(
1403
+ `\u81EA\u5B9A\u4E49\u5B57\u6BB5 JSON \u683C\u5F0F\u9519\u8BEF: ${error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"}`,
1404
+ options.pretty
1405
+ );
1406
+ process.exit(1);
1407
+ }
1408
+ }
1122
1409
  const result = await issueService.updateIssue(params);
1123
1410
  if (result.success && result.data) {
1124
- outputSuccess(result.data);
1411
+ outputSuccess(result.data, options.pretty);
1125
1412
  } else {
1126
- outputError(result.message || result.msg || result.api_error_msg || "\u66F4\u65B0\u95EE\u9898\u5931\u8D25");
1413
+ outputError(result.message || result.msg || result.api_error_msg || "\u66F4\u65B0\u95EE\u9898\u5931\u8D25", options.pretty);
1127
1414
  process.exit(1);
1128
1415
  }
1129
1416
  });
1130
- issueCmd.command("query").description("\u81EA\u5B9A\u4E49\u67E5\u8BE2").requiredOption("--query-id <id>", "\u67E5\u8BE2 ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
1417
+ issueCmd.command("query").description("\u81EA\u5B9A\u4E49\u67E5\u8BE2").requiredOption("--query-id <id>", "\u67E5\u8BE2 ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1131
1418
  const creds = resolveCredentials(options);
1132
1419
  const validation = validateCredentials(creds);
1133
1420
  if (!validation.valid) {
1134
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1421
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1135
1422
  process.exit(1);
1136
1423
  }
1137
1424
  const queryId = parseInt(options.queryId, 10);
@@ -1146,17 +1433,17 @@ function createIssueCommand() {
1146
1433
  offset
1147
1434
  );
1148
1435
  if (result.success && result.data) {
1149
- outputSuccess(result.data);
1436
+ outputSuccess(result.data, options.pretty);
1150
1437
  } else {
1151
- outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5931\u8D25");
1438
+ outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5931\u8D25", options.pretty);
1152
1439
  process.exit(1);
1153
1440
  }
1154
1441
  });
1155
- issueCmd.command("filter").description("V6 \u8FC7\u6EE4\u5668\u67E5\u8BE2").option("--mode <mode>", "\u67E5\u8BE2\u6A21\u5F0F (normal/simple/advanced)", "normal").option("--status <status>", "\u72B6\u6001\u8FC7\u6EE4").option("--tracker <tracker>", "\u8DDF\u8E2A\u5668\u8FC7\u6EE4").option("--assigned-to <user>", "\u6307\u6D3E\u4EBA\u8FC7\u6EE4").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
1442
+ issueCmd.command("filter").description("V6 \u8FC7\u6EE4\u5668\u67E5\u8BE2").option("--mode <mode>", "\u67E5\u8BE2\u6A21\u5F0F (normal/simple/advanced)", "normal").option("--status <status>", "\u72B6\u6001\u8FC7\u6EE4").option("--tracker <tracker>", "\u8DDF\u8E2A\u5668\u8FC7\u6EE4").option("--assigned-to <user>", "\u6307\u6D3E\u4EBA\u8FC7\u6EE4").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1156
1443
  const creds = resolveCredentials(options);
1157
1444
  const validation = validateCredentials(creds);
1158
1445
  if (!validation.valid) {
1159
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1446
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1160
1447
  process.exit(1);
1161
1448
  }
1162
1449
  const filterParams = {};
@@ -1173,17 +1460,17 @@ function createIssueCommand() {
1173
1460
  filterParams
1174
1461
  );
1175
1462
  if (result.success && result.data) {
1176
- outputSuccess(result.data);
1463
+ outputSuccess(result.data, options.pretty);
1177
1464
  } else {
1178
- outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5931\u8D25");
1465
+ outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5931\u8D25", options.pretty);
1179
1466
  process.exit(1);
1180
1467
  }
1181
1468
  });
1182
- issueCmd.command("field-options").description("\u83B7\u53D6\u95EE\u9898\u5B57\u6BB5\u9009\u9879").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
1469
+ issueCmd.command("field-options").description("\u83B7\u53D6\u95EE\u9898\u5B57\u6BB5\u9009\u9879").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1183
1470
  const creds = resolveCredentials(options);
1184
1471
  const validation = validateCredentials(creds);
1185
1472
  if (!validation.valid) {
1186
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1473
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1187
1474
  process.exit(1);
1188
1475
  }
1189
1476
  const result = await issueService.getIssueFieldOptions(
@@ -1192,19 +1479,19 @@ function createIssueCommand() {
1192
1479
  creds.project
1193
1480
  );
1194
1481
  if (result.success) {
1195
- outputSuccess(result.data);
1482
+ outputSuccess(result.data, options.pretty);
1196
1483
  } else {
1197
- outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u5B57\u6BB5\u9009\u9879\u5931\u8D25");
1484
+ outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u5B57\u6BB5\u9009\u9879\u5931\u8D25", options.pretty);
1198
1485
  process.exit(1);
1199
1486
  }
1200
1487
  });
1201
- issueCmd.command("children <id>").description("\u67E5\u8BE2\u5B50\u4EFB\u52A1\uFF08\u652F\u6301\u6309\u8D1F\u8D23\u4EBA\u8FC7\u6EE4\uFF09").option("--url <url>", "PM \u94FE\u63A5").option("--assigned-to <name>", "\u8D1F\u8D23\u4EBA\u59D3\u540D\uFF08\u652F\u6301\u6A21\u7CCA\u5339\u914D\uFF09").option("--assigned-to-id <id>", "\u8D1F\u8D23\u4EBA ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236", "100").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (id, options) => {
1488
+ issueCmd.command("children <id>").description("\u67E5\u8BE2\u5B50\u4EFB\u52A1\uFF08\u652F\u6301\u6309\u8D1F\u8D23\u4EBA\u8FC7\u6EE4\uFF09").option("--url <url>", "PM \u94FE\u63A5").option("--assigned-to <name>", "\u8D1F\u8D23\u4EBA\u59D3\u540D\uFF08\u652F\u6301\u6A21\u7CCA\u5339\u914D\uFF09").option("--assigned-to-id <id>", "\u8D1F\u8D23\u4EBA ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236", "100").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (id, options) => {
1202
1489
  let issueId;
1203
1490
  let host;
1204
1491
  if (options.url) {
1205
1492
  const linkInfo = parsePmLink(options.url);
1206
1493
  if (!linkInfo) {
1207
- outputError("\u65E0\u6548\u7684 PM \u94FE\u63A5\u683C\u5F0F");
1494
+ outputError("\u65E0\u6548\u7684 PM \u94FE\u63A5\u683C\u5F0F", options.pretty);
1208
1495
  process.exit(1);
1209
1496
  }
1210
1497
  issueId = parseInt(linkInfo.issueId, 10);
@@ -1213,7 +1500,7 @@ function createIssueCommand() {
1213
1500
  const cleanId = id.replace(/^#/, "");
1214
1501
  issueId = parseInt(cleanId, 10);
1215
1502
  if (isNaN(issueId)) {
1216
- outputError("\u65E0\u6548\u7684\u95EE\u9898 ID");
1503
+ outputError("\u65E0\u6548\u7684\u95EE\u9898 ID", options.pretty);
1217
1504
  process.exit(1);
1218
1505
  }
1219
1506
  }
@@ -1223,7 +1510,7 @@ function createIssueCommand() {
1223
1510
  });
1224
1511
  const validation = validateCredentials(creds);
1225
1512
  if (!validation.valid) {
1226
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1513
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1227
1514
  process.exit(1);
1228
1515
  }
1229
1516
  let assignedToId;
@@ -1242,11 +1529,11 @@ function createIssueCommand() {
1242
1529
  if (matchedUser) {
1243
1530
  assignedToId = matchedUser.id;
1244
1531
  } else {
1245
- outputError(`\u672A\u627E\u5230\u5339\u914D\u7684\u7528\u6237: ${options.assignedTo}`);
1532
+ outputError(`\u672A\u627E\u5230\u5339\u914D\u7684\u7528\u6237: ${options.assignedTo}`, options.pretty);
1246
1533
  process.exit(1);
1247
1534
  }
1248
1535
  } else {
1249
- outputError("\u83B7\u53D6\u7528\u6237\u5217\u8868\u5931\u8D25");
1536
+ outputError("\u83B7\u53D6\u7528\u6237\u5217\u8868\u5931\u8D25", options.pretty);
1250
1537
  process.exit(1);
1251
1538
  }
1252
1539
  } else if (options.assignedToId) {
@@ -1267,16 +1554,16 @@ function createIssueCommand() {
1267
1554
  outputSuccess({
1268
1555
  total: data.data.list.length,
1269
1556
  issues: data.data.list
1270
- });
1557
+ }, options.pretty);
1271
1558
  } else {
1272
- outputSuccess(result.data);
1559
+ outputSuccess(result.data, options.pretty);
1273
1560
  }
1274
1561
  } else {
1275
- outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5B50\u4EFB\u52A1\u5931\u8D25");
1562
+ outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5B50\u4EFB\u52A1\u5931\u8D25", options.pretty);
1276
1563
  process.exit(1);
1277
1564
  }
1278
1565
  });
1279
- issueCmd.command("mget [ids...]").description("\u6279\u91CF\u83B7\u53D6\u591A\u4E2A\u95EE\u9898\u8BE6\u60C5").option("--ids <ids>", "\u9017\u53F7\u5206\u9694\u7684\u95EE\u9898 ID \u5217\u8868").option("--depth <depth>", "\u9012\u5F52\u83B7\u53D6\u5B50\u5355\u7684\u6DF1\u5EA6\uFF080 \u8868\u793A\u4E0D\u83B7\u53D6\u5B50\u5355\uFF09", "0").option("--include-relations", "\u5305\u542B\u5173\u8054\u95EE\u9898").option("-o, --output <path>", "\u8F93\u51FA JSON \u5230\u6307\u5B9A\u6587\u4EF6\uFF08\u9ED8\u8BA4\u8F93\u51FA\u5230 /tmp\uFF09").option("--stdout", "\u5F3A\u5236\u8F93\u51FA\u5230\u63A7\u5236\u53F0\u800C\u975E\u6587\u4EF6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (ids, options) => {
1566
+ issueCmd.command("mget [ids...]").description("\u6279\u91CF\u83B7\u53D6\u591A\u4E2A\u95EE\u9898\u8BE6\u60C5").option("--ids <ids>", "\u9017\u53F7\u5206\u9694\u7684\u95EE\u9898 ID \u5217\u8868").option("--depth <depth>", "\u9012\u5F52\u83B7\u53D6\u5B50\u5355\u7684\u6DF1\u5EA6\uFF080 \u8868\u793A\u4E0D\u83B7\u53D6\u5B50\u5355\uFF09", "0").option("--include-relations", "\u5305\u542B\u5173\u8054\u95EE\u9898").option("-o, --output <path>", "\u8F93\u51FA JSON \u5230\u6307\u5B9A\u6587\u4EF6\uFF08\u9ED8\u8BA4\u8F93\u51FA\u5230 /tmp\uFF09").option("--stdout", "\u5F3A\u5236\u8F93\u51FA\u5230\u63A7\u5236\u53F0\u800C\u975E\u6587\u4EF6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (ids, options) => {
1280
1567
  let issueIds = [];
1281
1568
  if (ids && ids.length > 0) {
1282
1569
  const parsedIds = ids.map((id) => parseInt(id.replace(/^#/, ""), 10)).filter((id) => !isNaN(id));
@@ -1288,13 +1575,13 @@ function createIssueCommand() {
1288
1575
  }
1289
1576
  issueIds = [...new Set(issueIds)];
1290
1577
  if (issueIds.length === 0) {
1291
- outputError("\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u4E2A\u95EE\u9898 ID");
1578
+ outputError("\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u4E2A\u95EE\u9898 ID", options.pretty);
1292
1579
  process.exit(1);
1293
1580
  }
1294
1581
  const creds = resolveCredentials(options);
1295
1582
  const validation = validateCredentials(creds, ["token", "host"]);
1296
1583
  if (!validation.valid) {
1297
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1584
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1298
1585
  process.exit(1);
1299
1586
  }
1300
1587
  const depth = parseInt(options.depth, 10);
@@ -1324,10 +1611,117 @@ function createIssueCommand() {
1324
1611
  stdout: options.stdout,
1325
1612
  output: options.output,
1326
1613
  command: "issue-mget",
1327
- identifier: issueIds.join("_")
1614
+ identifier: issueIds.join("_"),
1615
+ pretty: options.pretty
1616
+ });
1617
+ } else {
1618
+ outputError(result.message || result.msg || result.api_error_msg || "\u6279\u91CF\u83B7\u53D6\u95EE\u9898\u5931\u8D25", options.pretty);
1619
+ process.exit(1);
1620
+ }
1621
+ });
1622
+ issueCmd.command("sync").description("\u540C\u6B65\u5B50\u5355\uFF1A\u4ECE\u6E90\u7236\u5355\u590D\u5236\u5B50\u5355\u5230\u76EE\u6807\u7236\u5355").option("--from <id>", "\u6E90\u7236\u5355 ID").option("--to <id>", "\u76EE\u6807\u7236\u5355 ID").option("--from-url <url>", "\u6E90\u7236\u5355 PM \u94FE\u63A5").option("--to-url <url>", "\u76EE\u6807\u7236\u5355 PM \u94FE\u63A5").option("--assigned-to-mail <email>", "\u6307\u6D3E\u4EBA\u90AE\u7BB1\uFF08\u9ED8\u8BA4\u4F7F\u7528\u914D\u7F6E\u7684 userMail\uFF09").option("--depth <depth>", "\u9012\u5F52\u6DF1\u5EA6", "10").option("--dry-run", "\u6A21\u62DF\u8FD0\u884C\uFF0C\u4E0D\u5B9E\u9645\u521B\u5EFA").option("--no-skip-existing", "\u4E0D\u8DF3\u8FC7\u540C\u540D\u4EFB\u52A1").option("-o, --output <path>", "\u8F93\u51FA JSON \u5230\u6307\u5B9A\u6587\u4EF6").option("--stdout", "\u5F3A\u5236\u8F93\u51FA\u5230\u63A7\u5236\u53F0\u800C\u975E\u6587\u4EF6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1623
+ let sourceId;
1624
+ let targetId;
1625
+ let sourceHost;
1626
+ let targetHost;
1627
+ if (options.fromUrl) {
1628
+ const linkInfo = parsePmLink(options.fromUrl);
1629
+ if (!linkInfo) {
1630
+ outputError("\u65E0\u6548\u7684\u6E90\u7236\u5355 PM \u94FE\u63A5\u683C\u5F0F", options.pretty);
1631
+ process.exit(1);
1632
+ }
1633
+ sourceId = parseInt(linkInfo.issueId, 10);
1634
+ sourceHost = linkInfo.host;
1635
+ } else if (options.from) {
1636
+ const cleanId = options.from.replace(/^#/, "");
1637
+ sourceId = parseInt(cleanId, 10);
1638
+ if (isNaN(sourceId)) {
1639
+ outputError("\u65E0\u6548\u7684\u6E90\u7236\u5355 ID", options.pretty);
1640
+ process.exit(1);
1641
+ }
1642
+ }
1643
+ if (options.toUrl) {
1644
+ const linkInfo = parsePmLink(options.toUrl);
1645
+ if (!linkInfo) {
1646
+ outputError("\u65E0\u6548\u7684\u76EE\u6807\u7236\u5355 PM \u94FE\u63A5\u683C\u5F0F", options.pretty);
1647
+ process.exit(1);
1648
+ }
1649
+ targetId = parseInt(linkInfo.issueId, 10);
1650
+ targetHost = linkInfo.host;
1651
+ } else if (options.to) {
1652
+ const cleanId = options.to.replace(/^#/, "");
1653
+ targetId = parseInt(cleanId, 10);
1654
+ if (isNaN(targetId)) {
1655
+ outputError("\u65E0\u6548\u7684\u76EE\u6807\u7236\u5355 ID", options.pretty);
1656
+ process.exit(1);
1657
+ }
1658
+ }
1659
+ if (!sourceId) {
1660
+ outputError("\u8BF7\u63D0\u4F9B\u6E90\u7236\u5355 ID\uFF08--from\uFF09\u6216 PM \u94FE\u63A5\uFF08--from-url\uFF09", options.pretty);
1661
+ process.exit(1);
1662
+ }
1663
+ if (!targetId) {
1664
+ outputError("\u8BF7\u63D0\u4F9B\u76EE\u6807\u7236\u5355 ID\uFF08--to\uFF09\u6216 PM \u94FE\u63A5\uFF08--to-url\uFF09", options.pretty);
1665
+ process.exit(1);
1666
+ }
1667
+ const creds = resolveCredentials({
1668
+ ...options,
1669
+ host: sourceHost || targetHost || options.host
1670
+ });
1671
+ const validation = validateCredentials(creds, ["token", "host"]);
1672
+ if (!validation.valid) {
1673
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1674
+ process.exit(1);
1675
+ }
1676
+ let assignedToMail = options.assignedToMail;
1677
+ if (!assignedToMail) {
1678
+ const config = readConfig(options.config);
1679
+ assignedToMail = config.default?.userMail;
1680
+ if (options.profile && config.profiles[options.profile]?.userMail) {
1681
+ assignedToMail = config.profiles[options.profile].userMail;
1682
+ }
1683
+ }
1684
+ if (!assignedToMail) {
1685
+ outputError("\u8BF7\u63D0\u4F9B\u6307\u6D3E\u4EBA\u90AE\u7BB1\uFF08--assigned-to-mail\uFF09\u6216\u914D\u7F6E userMail\uFF08pm-cli config set user-mail xxx\uFF09", options.pretty);
1686
+ process.exit(1);
1687
+ }
1688
+ const depth = parseInt(options.depth, 10);
1689
+ const dryRun = options.dryRun || false;
1690
+ const skipExisting = options.skipExisting !== false;
1691
+ const result = await issueService.syncChildIssues(
1692
+ creds.token,
1693
+ creds.host,
1694
+ creds.project || "",
1695
+ sourceId,
1696
+ targetId,
1697
+ assignedToMail,
1698
+ { dryRun, depth, skipExisting }
1699
+ );
1700
+ if (result.success && result.data) {
1701
+ const output = {
1702
+ success: true,
1703
+ dryRun,
1704
+ sourceParentId: sourceId,
1705
+ targetParentId: targetId,
1706
+ assignedToMail,
1707
+ summary: {
1708
+ totalCreated: result.data.totalCreated,
1709
+ totalSkipped: result.data.totalSkipped,
1710
+ totalFailed: result.data.totalFailed
1711
+ },
1712
+ created: result.data.created,
1713
+ skipped: result.data.skipped.length > 0 ? result.data.skipped : void 0,
1714
+ failed: result.data.failed.length > 0 ? result.data.failed : void 0
1715
+ };
1716
+ smartOutput(output, {
1717
+ stdout: options.stdout,
1718
+ output: options.output,
1719
+ command: "issue-sync",
1720
+ identifier: `${sourceId}_to_${targetId}`,
1721
+ pretty: options.pretty
1328
1722
  });
1329
1723
  } else {
1330
- outputError(result.message || result.msg || result.api_error_msg || "\u6279\u91CF\u83B7\u53D6\u95EE\u9898\u5931\u8D25");
1724
+ outputError(result.message || result.msg || result.api_error_msg || "\u540C\u6B65\u5B50\u5355\u5931\u8D25", options.pretty);
1331
1725
  process.exit(1);
1332
1726
  }
1333
1727
  });
@@ -1433,19 +1827,19 @@ function getWeekDateRange(week) {
1433
1827
  }
1434
1828
  function createTimeCommand() {
1435
1829
  const timeCmd = new Command4("time").description("\u5DE5\u65F6\u7BA1\u7406");
1436
- timeCmd.command("list").description("\u67E5\u8BE2\u5DE5\u65F6\u6761\u76EE").option("--from <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)").option("--to <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)").option("--user-id <id>", "\u7528\u6237 ID").option("--activity-id <id>", "\u6D3B\u52A8\u7C7B\u578B ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--all-projects", "\u67E5\u8BE2\u6240\u6709\u9879\u76EE\u7684\u5DE5\u65F6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
1830
+ timeCmd.command("list").description("\u67E5\u8BE2\u5DE5\u65F6\u6761\u76EE").option("--from <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)").option("--to <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)").option("--user-id <id>", "\u7528\u6237 ID").option("--activity-id <id>", "\u6D3B\u52A8\u7C7B\u578B ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--all-projects", "\u67E5\u8BE2\u6240\u6709\u9879\u76EE\u7684\u5DE5\u65F6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1437
1831
  const creds = resolveCredentials(options);
1438
1832
  const requiredFields = options.allProjects ? ["token", "host"] : ["token", "host", "project"];
1439
1833
  const validation = validateCredentials(creds, requiredFields);
1440
1834
  if (!validation.valid) {
1441
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1835
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1442
1836
  process.exit(1);
1443
1837
  }
1444
1838
  if (options.allProjects) {
1445
1839
  logger_default.info("\u67E5\u8BE2\u6240\u6709\u9879\u76EE\u7684\u5DE5\u65F6...");
1446
1840
  const projectsResult = await userService.getProjects(creds.token, creds.host);
1447
1841
  if (!projectsResult.success || !projectsResult.data) {
1448
- outputError(projectsResult.message || projectsResult.msg || projectsResult.api_error_msg || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25");
1842
+ outputError(projectsResult.message || projectsResult.msg || projectsResult.api_error_msg || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25", options.pretty);
1449
1843
  process.exit(1);
1450
1844
  }
1451
1845
  const projects = projectsResult.data;
@@ -1501,18 +1895,18 @@ function createTimeCommand() {
1501
1895
  offset: options.offset ? parseInt(options.offset, 10) : void 0
1502
1896
  });
1503
1897
  if (result.success && result.data) {
1504
- outputSuccess(result.data);
1898
+ outputSuccess(result.data, options.pretty);
1505
1899
  } else {
1506
- outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5DE5\u65F6\u5931\u8D25");
1900
+ outputError(result.message || result.msg || result.api_error_msg || "\u67E5\u8BE2\u5DE5\u65F6\u5931\u8D25", options.pretty);
1507
1901
  process.exit(1);
1508
1902
  }
1509
1903
  }
1510
1904
  });
1511
- timeCmd.command("create").description("\u521B\u5EFA\u5DE5\u65F6\u6761\u76EE").requiredOption("--issue <id>", "\u95EE\u9898 ID").requiredOption("--days <days>", "\u5DE5\u65F6\uFF08\u5929\uFF09").requiredOption("--activity <id>", "\u6D3B\u52A8\u7C7B\u578B ID\uFF08\u4F7F\u7528 pm-cli time options \u83B7\u53D6\u53EF\u7528\u503C\uFF09").option("--date <date>", "\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u4ECA\u5929").option("--comments <comments>", "\u5907\u6CE8").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
1905
+ timeCmd.command("create").description("\u521B\u5EFA\u5DE5\u65F6\u6761\u76EE").requiredOption("--issue <id>", "\u95EE\u9898 ID").requiredOption("--days <days>", "\u5DE5\u65F6\uFF08\u5929\uFF09").requiredOption("--activity <id>", "\u6D3B\u52A8\u7C7B\u578B ID\uFF08\u4F7F\u7528 pm-cli time options \u83B7\u53D6\u53EF\u7528\u503C\uFF09").option("--date <date>", "\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u4ECA\u5929").option("--comments <comments>", "\u5907\u6CE8").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1512
1906
  const creds = resolveCredentials(options);
1513
1907
  const validation = validateCredentials(creds);
1514
1908
  if (!validation.valid) {
1515
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1909
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1516
1910
  process.exit(1);
1517
1911
  }
1518
1912
  let userId;
@@ -1521,22 +1915,22 @@ function createTimeCommand() {
1521
1915
  userId = parseInt(configUserId, 10);
1522
1916
  }
1523
1917
  if (!userId) {
1524
- outputError("\u7F3A\u5C11\u7528\u6237 ID\uFF0C\u8BF7\u5148\u8BBE\u7F6E: pm-cli config set user-id <\u60A8\u7684\u7528\u6237ID>");
1918
+ outputError("\u7F3A\u5C11\u7528\u6237 ID\uFF0C\u8BF7\u5148\u8BBE\u7F6E: pm-cli config set user-id <\u60A8\u7684\u7528\u6237ID>", options.pretty);
1525
1919
  process.exit(1);
1526
1920
  }
1527
1921
  const issueId = parseInt(options.issue.replace(/^#/, ""), 10);
1528
1922
  if (isNaN(issueId)) {
1529
- outputError("\u65E0\u6548\u7684\u95EE\u9898 ID");
1923
+ outputError("\u65E0\u6548\u7684\u95EE\u9898 ID", options.pretty);
1530
1924
  process.exit(1);
1531
1925
  }
1532
1926
  const days = parseFloat(options.days);
1533
1927
  if (isNaN(days) || days <= 0) {
1534
- outputError("\u65E0\u6548\u7684\u5DE5\u65F6\u6570");
1928
+ outputError("\u65E0\u6548\u7684\u5DE5\u65F6\u6570", options.pretty);
1535
1929
  process.exit(1);
1536
1930
  }
1537
1931
  const activityId = parseInt(options.activity, 10);
1538
1932
  if (isNaN(activityId)) {
1539
- outputError("\u65E0\u6548\u7684\u6D3B\u52A8\u7C7B\u578B ID\uFF0C\u4F7F\u7528 pm-cli time options \u83B7\u53D6\u53EF\u7528\u503C");
1933
+ outputError("\u65E0\u6548\u7684\u6D3B\u52A8\u7C7B\u578B ID\uFF0C\u4F7F\u7528 pm-cli time options \u83B7\u53D6\u53EF\u7528\u503C", options.pretty);
1540
1934
  process.exit(1);
1541
1935
  }
1542
1936
  const params = {
@@ -1549,23 +1943,25 @@ function createTimeCommand() {
1549
1943
  spent_on: options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
1550
1944
  user_id: userId,
1551
1945
  // 用户 ID(必填)
1552
- activity_id: activityId
1946
+ activity_id: activityId,
1553
1947
  // 活动类型 ID(必填)
1948
+ bulk_create: "true"
1949
+ // 固定为 true
1554
1950
  };
1555
1951
  if (options.comments) params.comments = options.comments;
1556
1952
  const result = await timeEntryService.createTimeEntry(params);
1557
1953
  if (result.success && result.data) {
1558
- outputSuccess(result.data);
1954
+ outputSuccess(result.data, options.pretty);
1559
1955
  } else {
1560
- outputError(result.message || result.msg || result.api_error_msg || "\u521B\u5EFA\u5DE5\u65F6\u5931\u8D25");
1956
+ outputError(result.message || result.msg || result.api_error_msg || "\u521B\u5EFA\u5DE5\u65F6\u5931\u8D25", options.pretty);
1561
1957
  process.exit(1);
1562
1958
  }
1563
1959
  });
1564
- timeCmd.command("update <id>").description("\u66F4\u65B0\u5DE5\u65F6\u6761\u76EE").requiredOption("--issue <id>", "\u95EE\u9898 ID\uFF08\u5FC5\u586B\uFF09").requiredOption("--days <days>", "\u5DE5\u65F6\uFF08\u5929\uFF09\uFF08\u5FC5\u586B\uFF09").requiredOption("--activity <id>", "\u6D3B\u52A8\u7C7B\u578B ID\uFF08\u5FC5\u586B\uFF09").requiredOption("--date <date>", "\u65E5\u671F (YYYY-MM-DD)\uFF08\u5FC5\u586B\uFF09").option("--comments <comments>", "\u5907\u6CE8").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (id, options) => {
1960
+ timeCmd.command("update <id>").description("\u66F4\u65B0\u5DE5\u65F6\u6761\u76EE").requiredOption("--issue <id>", "\u95EE\u9898 ID\uFF08\u5FC5\u586B\uFF09").requiredOption("--days <days>", "\u5DE5\u65F6\uFF08\u5929\uFF09\uFF08\u5FC5\u586B\uFF09").requiredOption("--activity <id>", "\u6D3B\u52A8\u7C7B\u578B ID\uFF08\u5FC5\u586B\uFF09").requiredOption("--date <date>", "\u65E5\u671F (YYYY-MM-DD)\uFF08\u5FC5\u586B\uFF09").option("--comments <comments>", "\u5907\u6CE8").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (id, options) => {
1565
1961
  const creds = resolveCredentials(options);
1566
1962
  const validation = validateCredentials(creds);
1567
1963
  if (!validation.valid) {
1568
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
1964
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1569
1965
  process.exit(1);
1570
1966
  }
1571
1967
  let userId;
@@ -1574,17 +1970,17 @@ function createTimeCommand() {
1574
1970
  userId = parseInt(configUserId, 10);
1575
1971
  }
1576
1972
  if (!userId) {
1577
- outputError("\u7F3A\u5C11\u7528\u6237 ID\uFF0C\u8BF7\u5148\u8BBE\u7F6E: pm-cli config set user-id <\u60A8\u7684\u7528\u6237ID>");
1973
+ outputError("\u7F3A\u5C11\u7528\u6237 ID\uFF0C\u8BF7\u5148\u8BBE\u7F6E: pm-cli config set user-id <\u60A8\u7684\u7528\u6237ID>", options.pretty);
1578
1974
  process.exit(1);
1579
1975
  }
1580
1976
  const timeEntryId = parseInt(id, 10);
1581
1977
  if (isNaN(timeEntryId)) {
1582
- outputError("\u65E0\u6548\u7684\u5DE5\u65F6\u6761\u76EE ID");
1978
+ outputError("\u65E0\u6548\u7684\u5DE5\u65F6\u6761\u76EE ID", options.pretty);
1583
1979
  process.exit(1);
1584
1980
  }
1585
1981
  const issueId = parseInt(options.issue.replace(/^#/, ""), 10);
1586
1982
  if (isNaN(issueId)) {
1587
- outputError("\u65E0\u6548\u7684\u95EE\u9898 ID");
1983
+ outputError("\u65E0\u6548\u7684\u95EE\u9898 ID", options.pretty);
1588
1984
  process.exit(1);
1589
1985
  }
1590
1986
  const params = {
@@ -1609,22 +2005,22 @@ function createTimeCommand() {
1609
2005
  if (options.comments) params.comments = options.comments;
1610
2006
  const result = await timeEntryService.updateTimeEntry(params);
1611
2007
  if (result.success && result.data) {
1612
- outputSuccess(result.data);
2008
+ outputSuccess(result.data, options.pretty);
1613
2009
  } else {
1614
- outputError(result.message || result.msg || result.api_error_msg || "\u66F4\u65B0\u5DE5\u65F6\u5931\u8D25");
2010
+ outputError(result.message || result.msg || result.api_error_msg || "\u66F4\u65B0\u5DE5\u65F6\u5931\u8D25", options.pretty);
1615
2011
  process.exit(1);
1616
2012
  }
1617
2013
  });
1618
- timeCmd.command("delete <id>").description("\u5220\u9664\u5DE5\u65F6\u6761\u76EE").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (id, options) => {
2014
+ timeCmd.command("delete <id>").description("\u5220\u9664\u5DE5\u65F6\u6761\u76EE").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (id, options) => {
1619
2015
  const creds = resolveCredentials(options);
1620
2016
  const validation = validateCredentials(creds, ["token", "host"]);
1621
2017
  if (!validation.valid) {
1622
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
2018
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1623
2019
  process.exit(1);
1624
2020
  }
1625
2021
  const timeEntryId = parseInt(id, 10);
1626
2022
  if (isNaN(timeEntryId)) {
1627
- outputError("\u65E0\u6548\u7684\u5DE5\u65F6\u6761\u76EE ID");
2023
+ outputError("\u65E0\u6548\u7684\u5DE5\u65F6\u6761\u76EE ID", options.pretty);
1628
2024
  process.exit(1);
1629
2025
  }
1630
2026
  const result = await timeEntryService.deleteTimeEntry(
@@ -1633,17 +2029,17 @@ function createTimeCommand() {
1633
2029
  timeEntryId
1634
2030
  );
1635
2031
  if (result.success) {
1636
- outputSuccess({ message: "\u5DE5\u65F6\u6761\u76EE\u5DF2\u5220\u9664", id: timeEntryId });
2032
+ outputSuccess({ message: "\u5DE5\u65F6\u6761\u76EE\u5DF2\u5220\u9664", id: timeEntryId }, options.pretty);
1637
2033
  } else {
1638
- outputError(result.message || result.msg || result.api_error_msg || "\u5220\u9664\u5DE5\u65F6\u5931\u8D25");
2034
+ outputError(result.message || result.msg || result.api_error_msg || "\u5220\u9664\u5DE5\u65F6\u5931\u8D25", options.pretty);
1639
2035
  process.exit(1);
1640
2036
  }
1641
2037
  });
1642
- timeCmd.command("options").description("\u83B7\u53D6\u5DE5\u65F6\u6761\u76EE\u9009\u9879\uFF08\u6D3B\u52A8\u7C7B\u578B\u5217\u8868\u7B49\uFF09").option("--issue <id>", "\u95EE\u9898 ID\uFF08\u53EF\u9009\uFF0C\u7528\u4E8E\u83B7\u53D6\u7279\u5B9A\u95EE\u9898\u7684\u5DE5\u65F6\u9009\u9879\uFF09").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
2038
+ timeCmd.command("options").description("\u83B7\u53D6\u5DE5\u65F6\u6761\u76EE\u9009\u9879\uFF08\u6D3B\u52A8\u7C7B\u578B\u5217\u8868\u7B49\uFF09").option("--issue <id>", "\u95EE\u9898 ID\uFF08\u53EF\u9009\uFF0C\u7528\u4E8E\u83B7\u53D6\u7279\u5B9A\u95EE\u9898\u7684\u5DE5\u65F6\u9009\u9879\uFF09").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1643
2039
  const creds = resolveCredentials(options);
1644
2040
  const validation = validateCredentials(creds);
1645
2041
  if (!validation.valid) {
1646
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
2042
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1647
2043
  process.exit(1);
1648
2044
  }
1649
2045
  const issueId = options.issue ? parseInt(options.issue.replace(/^#/, ""), 10) : void 0;
@@ -1657,20 +2053,20 @@ function createTimeCommand() {
1657
2053
  const data = result.data;
1658
2054
  if (data.options?.activities) {
1659
2055
  const activities = data.options.activities.map(([name, id]) => ({ id, name }));
1660
- outputSuccess({ activities });
2056
+ outputSuccess({ activities }, options.pretty);
1661
2057
  } else {
1662
- outputSuccess(result.data);
2058
+ outputSuccess(result.data, options.pretty);
1663
2059
  }
1664
2060
  } else {
1665
- outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u9009\u9879\u5931\u8D25");
2061
+ outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u9009\u9879\u5931\u8D25", options.pretty);
1666
2062
  process.exit(1);
1667
2063
  }
1668
2064
  });
1669
- timeCmd.command("summary").description("\u5DE5\u65F6\u7EDF\u8BA1\u6C47\u603B\uFF08\u67E5\u8BE2\u6307\u5B9A\u65F6\u95F4\u6BB5\u7684\u5DE5\u65F6\u5E76\u8BA1\u7B97\u7F3A\u53E3\uFF09").option("--week <week>", "\u5468\u9009\u62E9: current (\u672C\u5468), last (\u4E0A\u5468), \u6216\u6570\u5B57\u504F\u79FB", "current").option("--from <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u4E0E --week \u4E92\u65A5").option("--to <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u4E0E --week \u4E92\u65A5").option("--target <days>", "\u76EE\u6807\u5DE5\u65F6\uFF08\u5929\uFF09\uFF0C\u9ED8\u8BA4 5", "5").option("--detail", "\u663E\u793A\u5B8C\u6574\u5DE5\u65F6\u6761\u76EE\u8BE6\u60C5").option("--user-id <id>", "\u7528\u6237 ID\uFF08\u9ED8\u8BA4\u4F7F\u7528\u914D\u7F6E\u4E2D\u7684 user-id\uFF09").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
2065
+ timeCmd.command("summary").description("\u5DE5\u65F6\u7EDF\u8BA1\u6C47\u603B\uFF08\u67E5\u8BE2\u6307\u5B9A\u65F6\u95F4\u6BB5\u7684\u5DE5\u65F6\u5E76\u8BA1\u7B97\u7F3A\u53E3\uFF09").option("--week <week>", "\u5468\u9009\u62E9: current (\u672C\u5468), last (\u4E0A\u5468), \u6216\u6570\u5B57\u504F\u79FB", "current").option("--from <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u4E0E --week \u4E92\u65A5").option("--to <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u4E0E --week \u4E92\u65A5").option("--target <days>", "\u76EE\u6807\u5DE5\u65F6\uFF08\u5929\uFF09\uFF0C\u9ED8\u8BA4 5", "5").option("--detail", "\u663E\u793A\u5B8C\u6574\u5DE5\u65F6\u6761\u76EE\u8BE6\u60C5").option("--user-id <id>", "\u7528\u6237 ID\uFF08\u9ED8\u8BA4\u4F7F\u7528\u914D\u7F6E\u4E2D\u7684 user-id\uFF09").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1670
2066
  const creds = resolveCredentials(options);
1671
2067
  const validation = validateCredentials(creds, ["token", "host"]);
1672
2068
  if (!validation.valid) {
1673
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
2069
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1674
2070
  process.exit(1);
1675
2071
  }
1676
2072
  let fromDate;
@@ -1701,7 +2097,7 @@ function createTimeCommand() {
1701
2097
  }
1702
2098
  const projectsResult = await userService.getProjects(creds.token, creds.host);
1703
2099
  if (!projectsResult.success || !projectsResult.data) {
1704
- outputError(projectsResult.message || projectsResult.msg || projectsResult.api_error_msg || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25");
2100
+ outputError(projectsResult.message || projectsResult.msg || projectsResult.api_error_msg || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25", options.pretty);
1705
2101
  process.exit(1);
1706
2102
  }
1707
2103
  const projects = projectsResult.data;
@@ -1754,7 +2150,7 @@ function createTimeCommand() {
1754
2150
  return dateA.localeCompare(dateB);
1755
2151
  });
1756
2152
  }
1757
- outputSuccess(output);
2153
+ outputSuccess(output, options.pretty);
1758
2154
  });
1759
2155
  return timeCmd;
1760
2156
  }
@@ -1763,26 +2159,26 @@ function createTimeCommand() {
1763
2159
  import { Command as Command5 } from "commander";
1764
2160
  function createProjectCommand() {
1765
2161
  const projectCmd = new Command5("project").description("\u9879\u76EE\u7BA1\u7406");
1766
- projectCmd.command("list").description("\u83B7\u53D6\u9879\u76EE\u5217\u8868").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
2162
+ projectCmd.command("list").description("\u83B7\u53D6\u9879\u76EE\u5217\u8868").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1767
2163
  const creds = resolveCredentials(options);
1768
2164
  const validation = validateCredentials(creds, ["token", "host"]);
1769
2165
  if (!validation.valid) {
1770
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
2166
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1771
2167
  process.exit(1);
1772
2168
  }
1773
2169
  const result = await userService.getProjects(creds.token, creds.host);
1774
2170
  if (result.success && result.data) {
1775
- outputSuccess(result.data);
2171
+ outputSuccess(result.data, options.pretty);
1776
2172
  } else {
1777
- outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25");
2173
+ outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25", options.pretty);
1778
2174
  process.exit(1);
1779
2175
  }
1780
2176
  });
1781
- projectCmd.command("users").description("\u83B7\u53D6\u9879\u76EE\u7528\u6237\u5217\u8868").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
2177
+ projectCmd.command("users").description("\u83B7\u53D6\u9879\u76EE\u7528\u6237\u5217\u8868").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1782
2178
  const creds = resolveCredentials(options);
1783
2179
  const validation = validateCredentials(creds);
1784
2180
  if (!validation.valid) {
1785
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
2181
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1786
2182
  process.exit(1);
1787
2183
  }
1788
2184
  const result = await userService.getProjectUsers(
@@ -1791,24 +2187,24 @@ function createProjectCommand() {
1791
2187
  creds.project
1792
2188
  );
1793
2189
  if (result.success && result.data) {
1794
- outputSuccess(result.data);
2190
+ outputSuccess(result.data, options.pretty);
1795
2191
  } else {
1796
- outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u7528\u6237\u5217\u8868\u5931\u8D25");
2192
+ outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u7528\u6237\u5217\u8868\u5931\u8D25", options.pretty);
1797
2193
  process.exit(1);
1798
2194
  }
1799
2195
  });
1800
- projectCmd.command("info").description("\u83B7\u53D6\u4E3B\u673A\u4FE1\u606F").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
2196
+ projectCmd.command("info").description("\u83B7\u53D6\u4E3B\u673A\u4FE1\u606F").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
1801
2197
  const creds = resolveCredentials(options);
1802
2198
  const validation = validateCredentials(creds, ["token", "host"]);
1803
2199
  if (!validation.valid) {
1804
- outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`);
2200
+ outputError(`\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${validation.missing.join(", ")}`, options.pretty);
1805
2201
  process.exit(1);
1806
2202
  }
1807
2203
  const result = await userService.getHostInfo(creds.token, creds.host);
1808
2204
  if (result.success) {
1809
- outputSuccess(result.data);
2205
+ outputSuccess(result.data, options.pretty);
1810
2206
  } else {
1811
- outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u4E3B\u673A\u4FE1\u606F\u5931\u8D25");
2207
+ outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u4E3B\u673A\u4FE1\u606F\u5931\u8D25", options.pretty);
1812
2208
  process.exit(1);
1813
2209
  }
1814
2210
  });
@@ -1816,8 +2212,15 @@ function createProjectCommand() {
1816
2212
  }
1817
2213
 
1818
2214
  // src/index.ts
2215
+ import { readFileSync as readFileSync2 } from "fs";
2216
+ import { dirname as dirname2, join as join2 } from "path";
2217
+ import { fileURLToPath } from "url";
2218
+ var __filename = fileURLToPath(import.meta.url);
2219
+ var __dirname = dirname2(__filename);
2220
+ var packageJson = JSON.parse(readFileSync2(join2(__dirname, "../package.json"), "utf-8"));
2221
+ var version = packageJson.version;
1819
2222
  var program = new Command6();
1820
- program.name("pm-cli").description("\u7F51\u6613\u6613\u534F\u4F5C (PM NetEase) \u547D\u4EE4\u884C\u5DE5\u5177").version("0.1.0").option("--verbose", "\u8BE6\u7EC6\u8F93\u51FA").option("--debug", "\u8C03\u8BD5\u6A21\u5F0F").option("--no-mapping", "\u4E0D\u8F93\u51FA key \u6620\u5C04\u8868\uFF08\u9ED8\u8BA4\u8F93\u51FA\uFF09").hook("preAction", (thisCommand) => {
2223
+ program.name("pm-cli").description("\u7F51\u6613\u6613\u534F\u4F5C (PM NetEase) \u547D\u4EE4\u884C\u5DE5\u5177").version(version).option("--verbose", "\u8BE6\u7EC6\u8F93\u51FA").option("--debug", "\u8C03\u8BD5\u6A21\u5F0F").option("--no-mapping", "\u4E0D\u8F93\u51FA key \u6620\u5C04\u8868\uFF08\u9ED8\u8BA4\u8F93\u51FA\uFF09").hook("preAction", (thisCommand) => {
1821
2224
  const opts = thisCommand.opts();
1822
2225
  if (opts.debug) {
1823
2226
  logger_default.setLevel("debug");