i18-fe-automator-beta 2.1.5 → 2.1.6
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/commonjs/index.js +37 -14
- package/dist/esm/index.mjs +37 -14
- package/package.json +1 -1
package/dist/commonjs/index.js
CHANGED
|
@@ -2215,7 +2215,7 @@ async function selectProduct(zentaosid, cliOpts) {
|
|
|
2215
2215
|
name: `#${p.id} ${p.name}`,
|
|
2216
2216
|
value: p.id,
|
|
2217
2217
|
})),
|
|
2218
|
-
{ name: "
|
|
2218
|
+
{ name: "输入其他产品-计划ID(如: https://zentao.hongxinshop.com/zentao/productplan-browse-29.html 中的29)", value: "__INPUT__" },
|
|
2219
2219
|
],
|
|
2220
2220
|
},
|
|
2221
2221
|
]);
|
|
@@ -2226,11 +2226,11 @@ async function selectProduct(zentaosid, cliOpts) {
|
|
|
2226
2226
|
}
|
|
2227
2227
|
const { id } = await inquirer.prompt([
|
|
2228
2228
|
{
|
|
2229
|
-
message: "
|
|
2229
|
+
message: "请输入产品计划ID(如: https://zentao.hongxinshop.com/zentao/productplan-browse-29.html 中的29)",
|
|
2230
2230
|
name: "id",
|
|
2231
2231
|
type: "input",
|
|
2232
2232
|
validate: (val) =>
|
|
2233
|
-
/^\d+$/.test(String(val).trim()) || "
|
|
2233
|
+
/^\d+$/.test(String(val).trim()) || "请输入数字产品计划ID",
|
|
2234
2234
|
},
|
|
2235
2235
|
]);
|
|
2236
2236
|
return resolveProduct(zentaosid, id);
|
|
@@ -2854,7 +2854,7 @@ function writeZentaoTasks({ plan, scope, stories, storyDetails, products, failed
|
|
|
2854
2854
|
}
|
|
2855
2855
|
}
|
|
2856
2856
|
|
|
2857
|
-
// 计划选取交互: 关键词过滤 > 命中1条自动选中 > rawlist选取
|
|
2857
|
+
// 计划选取交互: 关键词过滤(标题) > 命中1条自动选中 > rawlist选取
|
|
2858
2858
|
async function selectPlan(plans, keyword) {
|
|
2859
2859
|
if (keyword && String(keyword).trim()) {
|
|
2860
2860
|
const kw = String(keyword).trim().toLowerCase();
|
|
@@ -2899,10 +2899,15 @@ async function loadPlanList(zentaosid, productID) {
|
|
|
2899
2899
|
return plans;
|
|
2900
2900
|
}
|
|
2901
2901
|
|
|
2902
|
-
// plan动作: 选中计划后展示计划信息 + 关联需求列表(ID供detail用)
|
|
2902
|
+
// plan动作: 选中计划后展示计划信息 + 关联需求列表(ID供detail用); 返回关联需求(供调用方判断空计划)
|
|
2903
2903
|
async function showPlanDetail(zentaosid, selected) {
|
|
2904
2904
|
Loading$1.start("拉取计划详情中...");
|
|
2905
2905
|
const { plan, stories } = await fetchPlanDetail(zentaosid, selected.id);
|
|
2906
|
+
// 0条需求时详情/工时统计均无意义, 一句话结束
|
|
2907
|
+
if (!stories.length) {
|
|
2908
|
+
Loading$1.succeed(`计划 #${plan.id} ${plan.title} 无关联需求`);
|
|
2909
|
+
return stories;
|
|
2910
|
+
}
|
|
2906
2911
|
Loading$1.succeed("拉取计划详情成功");
|
|
2907
2912
|
console.log(chalk.bold("\n计划信息"));
|
|
2908
2913
|
console.table([
|
|
@@ -2957,6 +2962,7 @@ async function showPlanDetail(zentaosid, selected) {
|
|
|
2957
2962
|
console.log(
|
|
2958
2963
|
chalk.blue("提示: ID 供 fe-it-beta story detail <需求ID> 使用(也可传需求url)")
|
|
2959
2964
|
);
|
|
2965
|
+
return stories;
|
|
2960
2966
|
}
|
|
2961
2967
|
|
|
2962
2968
|
// 导出动作(plan收尾交互使用): 按范围过滤需求, 拉详情并产出 .zentao-<计划名>/ + 工作区
|
|
@@ -3125,7 +3131,7 @@ async function storyMain(action, cliOpts) {
|
|
|
3125
3131
|
if (!match) {
|
|
3126
3132
|
console.log(
|
|
3127
3133
|
chalk.red(
|
|
3128
|
-
"
|
|
3134
|
+
"请传入项目-需求url的ID, 如: fe-it-beta story task 2915 或 fe-it-beta story task https://zentao.hongxinshop.com/zentao/project-story-2915.html"
|
|
3129
3135
|
)
|
|
3130
3136
|
);
|
|
3131
3137
|
process.exit(1);
|
|
@@ -3725,7 +3731,7 @@ async function storyMain(action, cliOpts) {
|
|
|
3725
3731
|
if (!match) {
|
|
3726
3732
|
console.log(
|
|
3727
3733
|
chalk.red(
|
|
3728
|
-
"
|
|
3734
|
+
"请传入项目-任务-由我参与url的ID, 如: fe-it-beta story close 2915 或 fe-it-beta story close https://zentao.hongxinshop.com/zentao/project-task-2915-myinvolved.html"
|
|
3729
3735
|
)
|
|
3730
3736
|
);
|
|
3731
3737
|
process.exit(1);
|
|
@@ -3997,10 +4003,26 @@ async function storyMain(action, cliOpts) {
|
|
|
3997
4003
|
// plan: 产品选择 -> 计划选取 -> 展示 -> 导出(--export直通一键场景, 不传则收尾交互)
|
|
3998
4004
|
const session = await ensureZentaoSession(cliOpts);
|
|
3999
4005
|
await session.request(async (zentaosid) => {
|
|
4000
|
-
|
|
4006
|
+
// 位置参数纯数字 = 产品计划ID(productplan-browse-<ID>.html 中的ID), 等同 --product 直通
|
|
4007
|
+
const nameArg = String(cliOpts.name || "").trim();
|
|
4008
|
+
const productIdArg = /^\d+$/.test(nameArg) ? nameArg : "";
|
|
4009
|
+
const product = await selectProduct(zentaosid, {
|
|
4010
|
+
...cliOpts,
|
|
4011
|
+
product: cliOpts.product || productIdArg,
|
|
4012
|
+
});
|
|
4001
4013
|
const plans = await loadPlanList(zentaosid, product.id);
|
|
4002
|
-
|
|
4003
|
-
|
|
4014
|
+
// 该产品无计划时后续选取/详情/导出均无意义, 提前结束
|
|
4015
|
+
if (!plans.length) {
|
|
4016
|
+
console.log(chalk.yellow(`产品 #${product.id} ${product.name} 下无计划, 结束`));
|
|
4017
|
+
return;
|
|
4018
|
+
}
|
|
4019
|
+
// 纯数字已用作产品ID, 非数字关键词仍按计划标题过滤
|
|
4020
|
+
const selected = await selectPlan(plans, productIdArg ? "" : cliOpts.name);
|
|
4021
|
+
const stories = await showPlanDetail(zentaosid, selected);
|
|
4022
|
+
// 空计划提示已在showPlanDetail输出, 直接结束不进导出询问
|
|
4023
|
+
if (!stories.length) {
|
|
4024
|
+
return;
|
|
4025
|
+
}
|
|
4004
4026
|
// 导出范围: --export参数直通(一键场景) > 收尾交互(默认前端)
|
|
4005
4027
|
let exportChoice;
|
|
4006
4028
|
if (cliOpts.export !== undefined) {
|
|
@@ -4009,14 +4031,14 @@ async function storyMain(action, cliOpts) {
|
|
|
4009
4031
|
} else {
|
|
4010
4032
|
({ exportChoice } = await inquirer.prompt([
|
|
4011
4033
|
{
|
|
4012
|
-
message:
|
|
4034
|
+
message: `是否导出需求文件(按计划生成 .zentao-<计划名>目录, ${chalk.red("目前导出功能只适用于claude code批量建任务")})?`,
|
|
4013
4035
|
name: "exportChoice",
|
|
4014
4036
|
type: "list",
|
|
4015
4037
|
choices: [
|
|
4016
|
-
{ name: "
|
|
4038
|
+
{ name: "否", value: "none" }, // 默认第一项
|
|
4039
|
+
{ name: "导出: 前端需求", value: "front" },
|
|
4017
4040
|
{ name: "导出: 后端需求", value: "back" },
|
|
4018
4041
|
{ name: "导出: 全部需求", value: "all" },
|
|
4019
|
-
{ name: "否", value: "none" },
|
|
4020
4042
|
],
|
|
4021
4043
|
},
|
|
4022
4044
|
]));
|
|
@@ -4042,7 +4064,7 @@ function registerStoryCommand(program, { markHandled, addHelpExample }) {
|
|
|
4042
4064
|
.option("--username <name>", "禅道账号(story命令用)")
|
|
4043
4065
|
.option("--password <pwd>", "禅道密码(story命令用, 日常建议用--cache)")
|
|
4044
4066
|
.option("--cache", "凭据静默走缓存")
|
|
4045
|
-
.option("--product <id>", "
|
|
4067
|
+
.option("--product <id>", "禅道产品计划ID(plan用, 即productplan-browse-<ID>.html中的ID, 不传则交互选择)")
|
|
4046
4068
|
.option("--export <scope>", "plan导出范围: front|back|all(传了跳过收尾询问直接导出)")
|
|
4047
4069
|
.option("--type <t>", "task任务类型: front|back(传了跳过类型询问与确认, 一键创建)")
|
|
4048
4070
|
.option("--split", "task时创建父任务并自动拆分子任务(>8h, 每个8h末个补余); subtask时跳过确认直接拆")
|
|
@@ -4061,6 +4083,7 @@ function registerStoryCommand(program, { markHandled, addHelpExample }) {
|
|
|
4061
4083
|
// help示例经 helpers 注入 index.js 的 helpExamples, 自动参与列对齐
|
|
4062
4084
|
addHelpExample("fe-it-beta story login", "禅道登录, 缓存zentaosid");
|
|
4063
4085
|
addHelpExample("fe-it-beta story plan --product 87", "选计划看列表, 交互选导出");
|
|
4086
|
+
addHelpExample("fe-it-beta story plan 29", "29=产品计划ID(productplan-browse-29.html), 拉计划列表再选取");
|
|
4064
4087
|
addHelpExample("fe-it-beta story detail 需求ID", "按需求ID查看详情");
|
|
4065
4088
|
addHelpExample("fe-it-beta story task 项目ID", "选项目勾选需求, 交互建禅道任务");
|
|
4066
4089
|
addHelpExample(
|
package/dist/esm/index.mjs
CHANGED
|
@@ -2193,7 +2193,7 @@ async function selectProduct(zentaosid, cliOpts) {
|
|
|
2193
2193
|
name: `#${p.id} ${p.name}`,
|
|
2194
2194
|
value: p.id,
|
|
2195
2195
|
})),
|
|
2196
|
-
{ name: "
|
|
2196
|
+
{ name: "输入其他产品-计划ID(如: https://zentao.hongxinshop.com/zentao/productplan-browse-29.html 中的29)", value: "__INPUT__" },
|
|
2197
2197
|
],
|
|
2198
2198
|
},
|
|
2199
2199
|
]);
|
|
@@ -2204,11 +2204,11 @@ async function selectProduct(zentaosid, cliOpts) {
|
|
|
2204
2204
|
}
|
|
2205
2205
|
const { id } = await inquirer.prompt([
|
|
2206
2206
|
{
|
|
2207
|
-
message: "
|
|
2207
|
+
message: "请输入产品计划ID(如: https://zentao.hongxinshop.com/zentao/productplan-browse-29.html 中的29)",
|
|
2208
2208
|
name: "id",
|
|
2209
2209
|
type: "input",
|
|
2210
2210
|
validate: (val) =>
|
|
2211
|
-
/^\d+$/.test(String(val).trim()) || "
|
|
2211
|
+
/^\d+$/.test(String(val).trim()) || "请输入数字产品计划ID",
|
|
2212
2212
|
},
|
|
2213
2213
|
]);
|
|
2214
2214
|
return resolveProduct(zentaosid, id);
|
|
@@ -2832,7 +2832,7 @@ function writeZentaoTasks({ plan, scope, stories, storyDetails, products, failed
|
|
|
2832
2832
|
}
|
|
2833
2833
|
}
|
|
2834
2834
|
|
|
2835
|
-
// 计划选取交互: 关键词过滤 > 命中1条自动选中 > rawlist选取
|
|
2835
|
+
// 计划选取交互: 关键词过滤(标题) > 命中1条自动选中 > rawlist选取
|
|
2836
2836
|
async function selectPlan(plans, keyword) {
|
|
2837
2837
|
if (keyword && String(keyword).trim()) {
|
|
2838
2838
|
const kw = String(keyword).trim().toLowerCase();
|
|
@@ -2877,10 +2877,15 @@ async function loadPlanList(zentaosid, productID) {
|
|
|
2877
2877
|
return plans;
|
|
2878
2878
|
}
|
|
2879
2879
|
|
|
2880
|
-
// plan动作: 选中计划后展示计划信息 + 关联需求列表(ID供detail用)
|
|
2880
|
+
// plan动作: 选中计划后展示计划信息 + 关联需求列表(ID供detail用); 返回关联需求(供调用方判断空计划)
|
|
2881
2881
|
async function showPlanDetail(zentaosid, selected) {
|
|
2882
2882
|
Loading.start("拉取计划详情中...");
|
|
2883
2883
|
const { plan, stories } = await fetchPlanDetail(zentaosid, selected.id);
|
|
2884
|
+
// 0条需求时详情/工时统计均无意义, 一句话结束
|
|
2885
|
+
if (!stories.length) {
|
|
2886
|
+
Loading.succeed(`计划 #${plan.id} ${plan.title} 无关联需求`);
|
|
2887
|
+
return stories;
|
|
2888
|
+
}
|
|
2884
2889
|
Loading.succeed("拉取计划详情成功");
|
|
2885
2890
|
console.log(chalk.bold("\n计划信息"));
|
|
2886
2891
|
console.table([
|
|
@@ -2935,6 +2940,7 @@ async function showPlanDetail(zentaosid, selected) {
|
|
|
2935
2940
|
console.log(
|
|
2936
2941
|
chalk.blue("提示: ID 供 fe-it-beta story detail <需求ID> 使用(也可传需求url)")
|
|
2937
2942
|
);
|
|
2943
|
+
return stories;
|
|
2938
2944
|
}
|
|
2939
2945
|
|
|
2940
2946
|
// 导出动作(plan收尾交互使用): 按范围过滤需求, 拉详情并产出 .zentao-<计划名>/ + 工作区
|
|
@@ -3103,7 +3109,7 @@ async function storyMain(action, cliOpts) {
|
|
|
3103
3109
|
if (!match) {
|
|
3104
3110
|
console.log(
|
|
3105
3111
|
chalk.red(
|
|
3106
|
-
"
|
|
3112
|
+
"请传入项目-需求url的ID, 如: fe-it-beta story task 2915 或 fe-it-beta story task https://zentao.hongxinshop.com/zentao/project-story-2915.html"
|
|
3107
3113
|
)
|
|
3108
3114
|
);
|
|
3109
3115
|
process.exit(1);
|
|
@@ -3703,7 +3709,7 @@ async function storyMain(action, cliOpts) {
|
|
|
3703
3709
|
if (!match) {
|
|
3704
3710
|
console.log(
|
|
3705
3711
|
chalk.red(
|
|
3706
|
-
"
|
|
3712
|
+
"请传入项目-任务-由我参与url的ID, 如: fe-it-beta story close 2915 或 fe-it-beta story close https://zentao.hongxinshop.com/zentao/project-task-2915-myinvolved.html"
|
|
3707
3713
|
)
|
|
3708
3714
|
);
|
|
3709
3715
|
process.exit(1);
|
|
@@ -3975,10 +3981,26 @@ async function storyMain(action, cliOpts) {
|
|
|
3975
3981
|
// plan: 产品选择 -> 计划选取 -> 展示 -> 导出(--export直通一键场景, 不传则收尾交互)
|
|
3976
3982
|
const session = await ensureZentaoSession(cliOpts);
|
|
3977
3983
|
await session.request(async (zentaosid) => {
|
|
3978
|
-
|
|
3984
|
+
// 位置参数纯数字 = 产品计划ID(productplan-browse-<ID>.html 中的ID), 等同 --product 直通
|
|
3985
|
+
const nameArg = String(cliOpts.name || "").trim();
|
|
3986
|
+
const productIdArg = /^\d+$/.test(nameArg) ? nameArg : "";
|
|
3987
|
+
const product = await selectProduct(zentaosid, {
|
|
3988
|
+
...cliOpts,
|
|
3989
|
+
product: cliOpts.product || productIdArg,
|
|
3990
|
+
});
|
|
3979
3991
|
const plans = await loadPlanList(zentaosid, product.id);
|
|
3980
|
-
|
|
3981
|
-
|
|
3992
|
+
// 该产品无计划时后续选取/详情/导出均无意义, 提前结束
|
|
3993
|
+
if (!plans.length) {
|
|
3994
|
+
console.log(chalk.yellow(`产品 #${product.id} ${product.name} 下无计划, 结束`));
|
|
3995
|
+
return;
|
|
3996
|
+
}
|
|
3997
|
+
// 纯数字已用作产品ID, 非数字关键词仍按计划标题过滤
|
|
3998
|
+
const selected = await selectPlan(plans, productIdArg ? "" : cliOpts.name);
|
|
3999
|
+
const stories = await showPlanDetail(zentaosid, selected);
|
|
4000
|
+
// 空计划提示已在showPlanDetail输出, 直接结束不进导出询问
|
|
4001
|
+
if (!stories.length) {
|
|
4002
|
+
return;
|
|
4003
|
+
}
|
|
3982
4004
|
// 导出范围: --export参数直通(一键场景) > 收尾交互(默认前端)
|
|
3983
4005
|
let exportChoice;
|
|
3984
4006
|
if (cliOpts.export !== undefined) {
|
|
@@ -3987,14 +4009,14 @@ async function storyMain(action, cliOpts) {
|
|
|
3987
4009
|
} else {
|
|
3988
4010
|
({ exportChoice } = await inquirer.prompt([
|
|
3989
4011
|
{
|
|
3990
|
-
message:
|
|
4012
|
+
message: `是否导出需求文件(按计划生成 .zentao-<计划名>目录, ${chalk.red("目前导出功能只适用于claude code批量建任务")})?`,
|
|
3991
4013
|
name: "exportChoice",
|
|
3992
4014
|
type: "list",
|
|
3993
4015
|
choices: [
|
|
3994
|
-
{ name: "
|
|
4016
|
+
{ name: "否", value: "none" }, // 默认第一项
|
|
4017
|
+
{ name: "导出: 前端需求", value: "front" },
|
|
3995
4018
|
{ name: "导出: 后端需求", value: "back" },
|
|
3996
4019
|
{ name: "导出: 全部需求", value: "all" },
|
|
3997
|
-
{ name: "否", value: "none" },
|
|
3998
4020
|
],
|
|
3999
4021
|
},
|
|
4000
4022
|
]));
|
|
@@ -4020,7 +4042,7 @@ function registerStoryCommand(program, { markHandled, addHelpExample }) {
|
|
|
4020
4042
|
.option("--username <name>", "禅道账号(story命令用)")
|
|
4021
4043
|
.option("--password <pwd>", "禅道密码(story命令用, 日常建议用--cache)")
|
|
4022
4044
|
.option("--cache", "凭据静默走缓存")
|
|
4023
|
-
.option("--product <id>", "
|
|
4045
|
+
.option("--product <id>", "禅道产品计划ID(plan用, 即productplan-browse-<ID>.html中的ID, 不传则交互选择)")
|
|
4024
4046
|
.option("--export <scope>", "plan导出范围: front|back|all(传了跳过收尾询问直接导出)")
|
|
4025
4047
|
.option("--type <t>", "task任务类型: front|back(传了跳过类型询问与确认, 一键创建)")
|
|
4026
4048
|
.option("--split", "task时创建父任务并自动拆分子任务(>8h, 每个8h末个补余); subtask时跳过确认直接拆")
|
|
@@ -4039,6 +4061,7 @@ function registerStoryCommand(program, { markHandled, addHelpExample }) {
|
|
|
4039
4061
|
// help示例经 helpers 注入 index.js 的 helpExamples, 自动参与列对齐
|
|
4040
4062
|
addHelpExample("fe-it-beta story login", "禅道登录, 缓存zentaosid");
|
|
4041
4063
|
addHelpExample("fe-it-beta story plan --product 87", "选计划看列表, 交互选导出");
|
|
4064
|
+
addHelpExample("fe-it-beta story plan 29", "29=产品计划ID(productplan-browse-29.html), 拉计划列表再选取");
|
|
4042
4065
|
addHelpExample("fe-it-beta story detail 需求ID", "按需求ID查看详情");
|
|
4043
4066
|
addHelpExample("fe-it-beta story task 项目ID", "选项目勾选需求, 交互建禅道任务");
|
|
4044
4067
|
addHelpExample(
|