i18-fe-automator-beta 2.1.7 → 2.1.8
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 +75 -10
- package/dist/esm/index.mjs +75 -10
- package/package.json +1 -1
package/dist/commonjs/index.js
CHANGED
|
@@ -2877,6 +2877,8 @@ async function selectPlan(plans, keyword) {
|
|
|
2877
2877
|
message: "请选择计划",
|
|
2878
2878
|
name: "plan",
|
|
2879
2879
|
type: "rawlist",
|
|
2880
|
+
// 到列表边界停止, 不循环回第一条
|
|
2881
|
+
loop: false,
|
|
2880
2882
|
choices: plans.map((p) => ({
|
|
2881
2883
|
name: `#${p.id} ${p.title} [${p.begin} ~ ${p.end}] (${
|
|
2882
2884
|
p.stories ?? 0
|
|
@@ -2971,9 +2973,64 @@ async function showPlanDetail(zentaosid, selected) {
|
|
|
2971
2973
|
return stories;
|
|
2972
2974
|
}
|
|
2973
2975
|
|
|
2974
|
-
//
|
|
2976
|
+
// 按导出范围过滤需求: front=有前端工时 | back=有后端工时 | all=全部
|
|
2977
|
+
function filterStoriesByScope(stories, scope) {
|
|
2978
|
+
return stories.filter((s) => {
|
|
2979
|
+
if (scope === "front") return Number(s.webestimate) > 0;
|
|
2980
|
+
if (scope === "back") return Number(s.estimate) > 0;
|
|
2981
|
+
return true;
|
|
2982
|
+
});
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
// 导出前下一步: 列出范围内需求供勾选(「全选」与子项父子联动, 复用 CheckboxAllPrompt)
|
|
2986
|
+
// 返回勾选的需求数组; 未勾选任何项返回[](调用方据此跳过导出)
|
|
2987
|
+
async function selectExportStories(stories, scope) {
|
|
2988
|
+
const scoped = filterStoriesByScope(stories, scope);
|
|
2989
|
+
// 工时展示跟随导出范围: front只展示前端工时 / back只展示后端工时 / all全展示
|
|
2990
|
+
const hoursOf = (s) => {
|
|
2991
|
+
const w = Number(s.webestimate) > 0 ? `${s.webestimate}h` : "-";
|
|
2992
|
+
const e = Number(s.estimate) > 0 ? `${s.estimate}h` : "-";
|
|
2993
|
+
if (scope === "front") return `(前端${w})`;
|
|
2994
|
+
if (scope === "back") return `(后端${e})`;
|
|
2995
|
+
return `(前端${w}/后端${e})`;
|
|
2996
|
+
};
|
|
2997
|
+
// prompt 注册幂等, 与 upload.js 各自使用前注册
|
|
2998
|
+
inquirer.registerPrompt("checkbox-all", CheckboxAllPrompt);
|
|
2999
|
+
// 需求选项拼接序号, 与数字键选择对应(按2选第一个需求...); 「全选」不占序号, 固定首项无前缀
|
|
3000
|
+
const choices = [
|
|
3001
|
+
{
|
|
3002
|
+
name: `全选(共${scoped.length}条)`,
|
|
3003
|
+
value: SELECT_ALL,
|
|
3004
|
+
short: "全选",
|
|
3005
|
+
// 默认全选(与全部子项联动一致)
|
|
3006
|
+
checked: true,
|
|
3007
|
+
},
|
|
3008
|
+
...scoped.map((s, index) => ({
|
|
3009
|
+
name: `${index + 1}. #${s.id} ${s.title} ${hoursOf(s)}`,
|
|
3010
|
+
value: String(s.id),
|
|
3011
|
+
short: `#${s.id}`,
|
|
3012
|
+
checked: true,
|
|
3013
|
+
})),
|
|
3014
|
+
];
|
|
3015
|
+
const { picked } = await inquirer.prompt([
|
|
3016
|
+
{
|
|
3017
|
+
message: `请勾选要导出的需求(空格选择, 回车确认; 「全选」与单个需求联动)`,
|
|
3018
|
+
name: "picked",
|
|
3019
|
+
type: "checkbox-all",
|
|
3020
|
+
// 到列表边界停止, 不循环回第一条
|
|
3021
|
+
loop: false,
|
|
3022
|
+
choices,
|
|
3023
|
+
},
|
|
3024
|
+
]);
|
|
3025
|
+
// 全选勾上时返回值含哨兵值, 一并忽略后按ID过滤
|
|
3026
|
+
const ids = new Set(picked.filter((v) => v !== SELECT_ALL));
|
|
3027
|
+
return scoped.filter((s) => ids.has(String(s.id)));
|
|
3028
|
+
}
|
|
3029
|
+
|
|
3030
|
+
// 导出动作(plan收尾交互使用): 按范围过滤需求(交互勾选时再按pickedIds收窄), 拉详情并产出 .zentao-<计划名>/ + 工作区
|
|
2975
3031
|
// scope: front=有前端工时的需求 | back=有后端工时的需求 | all=全部
|
|
2976
|
-
|
|
3032
|
+
// pickedIds: 交互勾选的需求ID集合(Set); 未传(--export直通一键场景)为范围内全量
|
|
3033
|
+
async function exportPlanStories(zentaosid, selected, scope, pickedIds) {
|
|
2977
3034
|
const scopeLabel =
|
|
2978
3035
|
scope === "front" ? "前端" : scope === "back" ? "后端" : "全部";
|
|
2979
3036
|
Loading$1.start("拉取计划详情中...");
|
|
@@ -2981,12 +3038,10 @@ async function exportPlanStories(zentaosid, selected, scope) {
|
|
|
2981
3038
|
zentaosid,
|
|
2982
3039
|
selected.id
|
|
2983
3040
|
);
|
|
2984
|
-
//
|
|
2985
|
-
const stories = allStories.filter(
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
return true;
|
|
2989
|
-
});
|
|
3041
|
+
// 按导出范围过滤需求, 再按勾选ID收窄(pickedIds未传=范围内全量)
|
|
3042
|
+
const stories = filterStoriesByScope(allStories, scope).filter(
|
|
3043
|
+
(s) => !pickedIds || pickedIds.has(String(s.id))
|
|
3044
|
+
);
|
|
2990
3045
|
Loading$1.succeed(
|
|
2991
3046
|
`拉取计划详情成功(${scopeLabel}${stories.length}/${allStories.length}条)`
|
|
2992
3047
|
);
|
|
@@ -4015,7 +4070,7 @@ async function storyMain(action, cliOpts) {
|
|
|
4015
4070
|
});
|
|
4016
4071
|
return;
|
|
4017
4072
|
}
|
|
4018
|
-
// plan: 产品选择 -> 计划选取 -> 展示 ->
|
|
4073
|
+
// plan: 产品选择 -> 计划选取 -> 展示 -> 导出询问(交互场景勾选需求, --export直通一键场景)
|
|
4019
4074
|
const session = await ensureZentaoSession(cliOpts);
|
|
4020
4075
|
await session.request(async (zentaosid) => {
|
|
4021
4076
|
// 位置参数纯数字 = 产品计划ID(productplan-browse-<ID>.html 中的ID), 等同 --product 直通
|
|
@@ -4059,7 +4114,17 @@ async function storyMain(action, cliOpts) {
|
|
|
4059
4114
|
]));
|
|
4060
4115
|
}
|
|
4061
4116
|
if (exportChoice !== "none") {
|
|
4062
|
-
|
|
4117
|
+
// 下一步(仅交互场景): 列出范围内需求勾选要导出的(「全选」与单个需求互斥); --export直通为范围内全量
|
|
4118
|
+
let pickedIds = null;
|
|
4119
|
+
if (cliOpts.export === undefined) {
|
|
4120
|
+
const pickedStories = await selectExportStories(stories, exportChoice);
|
|
4121
|
+
if (!pickedStories.length) {
|
|
4122
|
+
console.log(chalk.yellow("未勾选需求, 跳过导出"));
|
|
4123
|
+
return;
|
|
4124
|
+
}
|
|
4125
|
+
pickedIds = new Set(pickedStories.map((s) => String(s.id)));
|
|
4126
|
+
}
|
|
4127
|
+
await exportPlanStories(zentaosid, selected, exportChoice, pickedIds);
|
|
4063
4128
|
}
|
|
4064
4129
|
});
|
|
4065
4130
|
}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -2855,6 +2855,8 @@ async function selectPlan(plans, keyword) {
|
|
|
2855
2855
|
message: "请选择计划",
|
|
2856
2856
|
name: "plan",
|
|
2857
2857
|
type: "rawlist",
|
|
2858
|
+
// 到列表边界停止, 不循环回第一条
|
|
2859
|
+
loop: false,
|
|
2858
2860
|
choices: plans.map((p) => ({
|
|
2859
2861
|
name: `#${p.id} ${p.title} [${p.begin} ~ ${p.end}] (${
|
|
2860
2862
|
p.stories ?? 0
|
|
@@ -2949,9 +2951,64 @@ async function showPlanDetail(zentaosid, selected) {
|
|
|
2949
2951
|
return stories;
|
|
2950
2952
|
}
|
|
2951
2953
|
|
|
2952
|
-
//
|
|
2954
|
+
// 按导出范围过滤需求: front=有前端工时 | back=有后端工时 | all=全部
|
|
2955
|
+
function filterStoriesByScope(stories, scope) {
|
|
2956
|
+
return stories.filter((s) => {
|
|
2957
|
+
if (scope === "front") return Number(s.webestimate) > 0;
|
|
2958
|
+
if (scope === "back") return Number(s.estimate) > 0;
|
|
2959
|
+
return true;
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
// 导出前下一步: 列出范围内需求供勾选(「全选」与子项父子联动, 复用 CheckboxAllPrompt)
|
|
2964
|
+
// 返回勾选的需求数组; 未勾选任何项返回[](调用方据此跳过导出)
|
|
2965
|
+
async function selectExportStories(stories, scope) {
|
|
2966
|
+
const scoped = filterStoriesByScope(stories, scope);
|
|
2967
|
+
// 工时展示跟随导出范围: front只展示前端工时 / back只展示后端工时 / all全展示
|
|
2968
|
+
const hoursOf = (s) => {
|
|
2969
|
+
const w = Number(s.webestimate) > 0 ? `${s.webestimate}h` : "-";
|
|
2970
|
+
const e = Number(s.estimate) > 0 ? `${s.estimate}h` : "-";
|
|
2971
|
+
if (scope === "front") return `(前端${w})`;
|
|
2972
|
+
if (scope === "back") return `(后端${e})`;
|
|
2973
|
+
return `(前端${w}/后端${e})`;
|
|
2974
|
+
};
|
|
2975
|
+
// prompt 注册幂等, 与 upload.js 各自使用前注册
|
|
2976
|
+
inquirer.registerPrompt("checkbox-all", CheckboxAllPrompt);
|
|
2977
|
+
// 需求选项拼接序号, 与数字键选择对应(按2选第一个需求...); 「全选」不占序号, 固定首项无前缀
|
|
2978
|
+
const choices = [
|
|
2979
|
+
{
|
|
2980
|
+
name: `全选(共${scoped.length}条)`,
|
|
2981
|
+
value: SELECT_ALL,
|
|
2982
|
+
short: "全选",
|
|
2983
|
+
// 默认全选(与全部子项联动一致)
|
|
2984
|
+
checked: true,
|
|
2985
|
+
},
|
|
2986
|
+
...scoped.map((s, index) => ({
|
|
2987
|
+
name: `${index + 1}. #${s.id} ${s.title} ${hoursOf(s)}`,
|
|
2988
|
+
value: String(s.id),
|
|
2989
|
+
short: `#${s.id}`,
|
|
2990
|
+
checked: true,
|
|
2991
|
+
})),
|
|
2992
|
+
];
|
|
2993
|
+
const { picked } = await inquirer.prompt([
|
|
2994
|
+
{
|
|
2995
|
+
message: `请勾选要导出的需求(空格选择, 回车确认; 「全选」与单个需求联动)`,
|
|
2996
|
+
name: "picked",
|
|
2997
|
+
type: "checkbox-all",
|
|
2998
|
+
// 到列表边界停止, 不循环回第一条
|
|
2999
|
+
loop: false,
|
|
3000
|
+
choices,
|
|
3001
|
+
},
|
|
3002
|
+
]);
|
|
3003
|
+
// 全选勾上时返回值含哨兵值, 一并忽略后按ID过滤
|
|
3004
|
+
const ids = new Set(picked.filter((v) => v !== SELECT_ALL));
|
|
3005
|
+
return scoped.filter((s) => ids.has(String(s.id)));
|
|
3006
|
+
}
|
|
3007
|
+
|
|
3008
|
+
// 导出动作(plan收尾交互使用): 按范围过滤需求(交互勾选时再按pickedIds收窄), 拉详情并产出 .zentao-<计划名>/ + 工作区
|
|
2953
3009
|
// scope: front=有前端工时的需求 | back=有后端工时的需求 | all=全部
|
|
2954
|
-
|
|
3010
|
+
// pickedIds: 交互勾选的需求ID集合(Set); 未传(--export直通一键场景)为范围内全量
|
|
3011
|
+
async function exportPlanStories(zentaosid, selected, scope, pickedIds) {
|
|
2955
3012
|
const scopeLabel =
|
|
2956
3013
|
scope === "front" ? "前端" : scope === "back" ? "后端" : "全部";
|
|
2957
3014
|
Loading.start("拉取计划详情中...");
|
|
@@ -2959,12 +3016,10 @@ async function exportPlanStories(zentaosid, selected, scope) {
|
|
|
2959
3016
|
zentaosid,
|
|
2960
3017
|
selected.id
|
|
2961
3018
|
);
|
|
2962
|
-
//
|
|
2963
|
-
const stories = allStories.filter(
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
return true;
|
|
2967
|
-
});
|
|
3019
|
+
// 按导出范围过滤需求, 再按勾选ID收窄(pickedIds未传=范围内全量)
|
|
3020
|
+
const stories = filterStoriesByScope(allStories, scope).filter(
|
|
3021
|
+
(s) => !pickedIds || pickedIds.has(String(s.id))
|
|
3022
|
+
);
|
|
2968
3023
|
Loading.succeed(
|
|
2969
3024
|
`拉取计划详情成功(${scopeLabel}${stories.length}/${allStories.length}条)`
|
|
2970
3025
|
);
|
|
@@ -3993,7 +4048,7 @@ async function storyMain(action, cliOpts) {
|
|
|
3993
4048
|
});
|
|
3994
4049
|
return;
|
|
3995
4050
|
}
|
|
3996
|
-
// plan: 产品选择 -> 计划选取 -> 展示 ->
|
|
4051
|
+
// plan: 产品选择 -> 计划选取 -> 展示 -> 导出询问(交互场景勾选需求, --export直通一键场景)
|
|
3997
4052
|
const session = await ensureZentaoSession(cliOpts);
|
|
3998
4053
|
await session.request(async (zentaosid) => {
|
|
3999
4054
|
// 位置参数纯数字 = 产品计划ID(productplan-browse-<ID>.html 中的ID), 等同 --product 直通
|
|
@@ -4037,7 +4092,17 @@ async function storyMain(action, cliOpts) {
|
|
|
4037
4092
|
]));
|
|
4038
4093
|
}
|
|
4039
4094
|
if (exportChoice !== "none") {
|
|
4040
|
-
|
|
4095
|
+
// 下一步(仅交互场景): 列出范围内需求勾选要导出的(「全选」与单个需求互斥); --export直通为范围内全量
|
|
4096
|
+
let pickedIds = null;
|
|
4097
|
+
if (cliOpts.export === undefined) {
|
|
4098
|
+
const pickedStories = await selectExportStories(stories, exportChoice);
|
|
4099
|
+
if (!pickedStories.length) {
|
|
4100
|
+
console.log(chalk.yellow("未勾选需求, 跳过导出"));
|
|
4101
|
+
return;
|
|
4102
|
+
}
|
|
4103
|
+
pickedIds = new Set(pickedStories.map((s) => String(s.id)));
|
|
4104
|
+
}
|
|
4105
|
+
await exportPlanStories(zentaosid, selected, exportChoice, pickedIds);
|
|
4041
4106
|
}
|
|
4042
4107
|
});
|
|
4043
4108
|
}
|