workplace-pua-cli 0.4.1 → 0.7.1
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/LICENSE +21 -0
- package/README.md +512 -243
- package/dist/commands/chat-new-imports.js +2 -0
- package/dist/commands/config.js +14 -6
- package/dist/commands/email.js +301 -0
- package/dist/commands/interview.js +660 -0
- package/dist/commands/jargon.js +153 -0
- package/dist/commands/meeting-room.js +384 -0
- package/dist/commands/meeting.js +323 -0
- package/dist/commands/weekly.js +302 -0
- package/dist/index.js +29 -7
- package/dist/prompts/hr.js +126 -0
- package/dist/prompts/index.js +82 -1
- package/dist/prompts/intern.js +126 -0
- package/dist/prompts/interview-prompts.js +286 -0
- package/dist/prompts/meeting-prompts.js +229 -0
- package/dist/prompts/pm.js +123 -0
- package/dist/prompts/techlead.js +126 -0
- package/dist/utils/box.js +141 -0
- package/dist/utils/meeting-utils.js +194 -0
- package/dist/utils/resume-parser.js +122 -0
- package/dist/utils/stream.js +97 -13
- package/dist/utils/theme.js +177 -0
- package/package.json +73 -52
- package/.env.example +0 -4
- package/.eslintrc.json +0 -21
- package/.prettierrc.json +0 -9
- package/CHANGELOG.md +0 -113
- package/docs/OPTIMIZATION.md +0 -772
- package/docs/TECHNICAL_PRINCIPLES.md +0 -663
- package/sample/1.png +0 -0
- package/sample/2.png +0 -0
- package/screenshots/chat-dialogue.png +0 -0
- package/screenshots/chat-mode.png +0 -0
- package/src/__tests__/config/settings.test.ts +0 -48
- package/src/__tests__/prompts/boss.test.ts +0 -35
- package/src/commands/chat.ts +0 -328
- package/src/commands/config.ts +0 -283
- package/src/commands/prompt.ts +0 -154
- package/src/config/providers.ts +0 -109
- package/src/config/session-storage.ts +0 -94
- package/src/config/settings.ts +0 -194
- package/src/config/storage.ts +0 -150
- package/src/history/session.ts +0 -141
- package/src/index.ts +0 -164
- package/src/llm/base.ts +0 -55
- package/src/llm/factory.ts +0 -24
- package/src/llm/openai.ts +0 -113
- package/src/llm/zhipu.ts +0 -101
- package/src/prompts/boss.ts +0 -43
- package/src/prompts/employee.ts +0 -43
- package/src/prompts/index.ts +0 -3
- package/src/utils/formatter.ts +0 -104
- package/src/utils/logger.ts +0 -31
- package/src/utils/stream.ts +0 -76
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -18
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 会议发言建议生成器
|
|
4
|
+
* 功能:根据不同会议场景和角色生成会议发言
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.generateMeetingSuggestion = generateMeetingSuggestion;
|
|
11
|
+
exports.createMeetingCommand = createMeetingCommand;
|
|
12
|
+
const commander_1 = require("commander");
|
|
13
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
14
|
+
/**
|
|
15
|
+
* 会议场景配置
|
|
16
|
+
*/
|
|
17
|
+
const MEETING_SCENARIOS = {
|
|
18
|
+
standup: {
|
|
19
|
+
name: '每日站会',
|
|
20
|
+
description: '快速同步工作进展和计划',
|
|
21
|
+
duration: '15分钟'
|
|
22
|
+
},
|
|
23
|
+
review: {
|
|
24
|
+
name: '评审会议',
|
|
25
|
+
description: '方案评审/代码评审/产品评审',
|
|
26
|
+
duration: '30-60分钟'
|
|
27
|
+
},
|
|
28
|
+
brainstorm: {
|
|
29
|
+
name: '头脑风暴',
|
|
30
|
+
description: '创意发散和方案讨论',
|
|
31
|
+
duration: '30-90分钟'
|
|
32
|
+
},
|
|
33
|
+
retro: {
|
|
34
|
+
name: '回顾会议',
|
|
35
|
+
description: '总结经验教训和改进点',
|
|
36
|
+
duration: '60分钟'
|
|
37
|
+
},
|
|
38
|
+
planning: {
|
|
39
|
+
name: '规划会议',
|
|
40
|
+
description: '迭代规划和任务分配',
|
|
41
|
+
duration: '60分钟'
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 角色会议发言模板
|
|
46
|
+
*/
|
|
47
|
+
const ROLE_MEETING_TEMPLATES = {
|
|
48
|
+
boss: {
|
|
49
|
+
standup: [
|
|
50
|
+
'大家抓紧时间,我简单说几点',
|
|
51
|
+
'{X},你的进度怎么样?要抓紧啊',
|
|
52
|
+
'这个项目时间很紧,大家要有紧迫感',
|
|
53
|
+
'辛苦辛苦,但结果才是最重要的'
|
|
54
|
+
],
|
|
55
|
+
review: [
|
|
56
|
+
'这个方案我看了,还需要再完善',
|
|
57
|
+
'我认为可以从以下角度优化',
|
|
58
|
+
'我的建议是{X},大家参考',
|
|
59
|
+
'这个方向是对的,但执行要到位'
|
|
60
|
+
],
|
|
61
|
+
brainstorm: [
|
|
62
|
+
'我想听一下大家的想法,不要怕说错',
|
|
63
|
+
'我们要开放心态,多提意见',
|
|
64
|
+
'这个想法不错,可以深入一下',
|
|
65
|
+
'我补充一点'
|
|
66
|
+
],
|
|
67
|
+
retro: [
|
|
68
|
+
'这个迭代整体还行,但还有改进空间',
|
|
69
|
+
'我觉得{X}做得不错,{Y}需要加强',
|
|
70
|
+
'下次我们要注意{X}',
|
|
71
|
+
'大家可以畅所欲言,不要有顾虑'
|
|
72
|
+
],
|
|
73
|
+
planning: [
|
|
74
|
+
'这个迭代我们要确保{X}目标的达成',
|
|
75
|
+
'大家要对自己的任务负责',
|
|
76
|
+
'时间节点不能拖延',
|
|
77
|
+
'有问题及时沟通,不要等最后才说'
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
employee: {
|
|
81
|
+
standup: [
|
|
82
|
+
'昨天我完成了{X}',
|
|
83
|
+
'今天计划{X}',
|
|
84
|
+
'目前遇到{X}问题,正在排查',
|
|
85
|
+
'可能需要{support}支持一下'
|
|
86
|
+
],
|
|
87
|
+
review: [
|
|
88
|
+
'我觉得这个方案可行',
|
|
89
|
+
'技术上应该可以实现',
|
|
90
|
+
'我可能需要{X}天时间',
|
|
91
|
+
'可以参考{X}方案'
|
|
92
|
+
],
|
|
93
|
+
brainstorm: [
|
|
94
|
+
'我觉得可以从{X}角度考虑',
|
|
95
|
+
'我的想法是{X}',
|
|
96
|
+
'可以尝试{X}方案',
|
|
97
|
+
'我补充一点'
|
|
98
|
+
],
|
|
99
|
+
retro: [
|
|
100
|
+
'我觉得这次{X}做得不错',
|
|
101
|
+
'{Y}方面可能需要改进',
|
|
102
|
+
'下次可以{X}',
|
|
103
|
+
'我也分享一下我的感受'
|
|
104
|
+
],
|
|
105
|
+
planning: [
|
|
106
|
+
'我可以负责{X}任务',
|
|
107
|
+
'预计需要{X}天完成',
|
|
108
|
+
'可能需要{support}支持',
|
|
109
|
+
'我会尽力按时完成'
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
pm: {
|
|
113
|
+
standup: [
|
|
114
|
+
'今天对齐{X}个事项',
|
|
115
|
+
'{X}个项目需要{action}',
|
|
116
|
+
'用户反馈需要{review}',
|
|
117
|
+
'下周要上线{X}个功能'
|
|
118
|
+
],
|
|
119
|
+
review: [
|
|
120
|
+
'从产品角度看{X}',
|
|
121
|
+
'用户价值{X}',
|
|
122
|
+
'建议{action}后再确认',
|
|
123
|
+
'这个方案对齐用户需求了吗'
|
|
124
|
+
],
|
|
125
|
+
brainstorm: [
|
|
126
|
+
'我们可以从用户场景考虑',
|
|
127
|
+
'核心诉求是{X}',
|
|
128
|
+
'我的想法是{X}',
|
|
129
|
+
'这个思路有创新性'
|
|
130
|
+
],
|
|
131
|
+
retro: [
|
|
132
|
+
'这次迭代{X}方面做得不错',
|
|
133
|
+
'{Y}需要继续优化',
|
|
134
|
+
'用户反馈{X}',
|
|
135
|
+
'下次可以{X}'
|
|
136
|
+
],
|
|
137
|
+
planning: [
|
|
138
|
+
'这次迭代聚焦{X}功能',
|
|
139
|
+
'时间节点{X}',
|
|
140
|
+
'资源分配{X}',
|
|
141
|
+
'上线目标{X}'
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
hr: {
|
|
145
|
+
standup: [
|
|
146
|
+
'大家今天状态怎么样',
|
|
147
|
+
'有什么需要支持的',
|
|
148
|
+
'团队氛围{X}',
|
|
149
|
+
'要注意劳逸结合'
|
|
150
|
+
],
|
|
151
|
+
review: [
|
|
152
|
+
'从团队角度{X}',
|
|
153
|
+
'资源配置{X}',
|
|
154
|
+
'大家觉得呢',
|
|
155
|
+
'有什么困难可以提出来'
|
|
156
|
+
],
|
|
157
|
+
brainstorm: [
|
|
158
|
+
'我们可以多角度思考',
|
|
159
|
+
'大家畅所欲言',
|
|
160
|
+
'团队的意见很重要',
|
|
161
|
+
'我补充一点企业文化相关'
|
|
162
|
+
],
|
|
163
|
+
retro: [
|
|
164
|
+
'团队协作{X}',
|
|
165
|
+
'{Y}有待提升',
|
|
166
|
+
'文化建设{X}',
|
|
167
|
+
'下次活动{X}'
|
|
168
|
+
],
|
|
169
|
+
planning: [
|
|
170
|
+
'团建计划{X}',
|
|
171
|
+
'培训安排{X}',
|
|
172
|
+
'文化建设{X}',
|
|
173
|
+
'团队发展{X}'
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
techlead: {
|
|
177
|
+
standup: [
|
|
178
|
+
'{X},你的代码需要review',
|
|
179
|
+
'这个模块性能有问题',
|
|
180
|
+
'架构需要优化',
|
|
181
|
+
'技术债务要处理'
|
|
182
|
+
],
|
|
183
|
+
review: [
|
|
184
|
+
'这个方案{X}有问题',
|
|
185
|
+
'架构上不够清晰',
|
|
186
|
+
'性能考虑不足',
|
|
187
|
+
'需要重构'
|
|
188
|
+
],
|
|
189
|
+
brainstorm: [
|
|
190
|
+
'从技术角度看{X}',
|
|
191
|
+
'可以用{X}方案',
|
|
192
|
+
'架构层面{X}',
|
|
193
|
+
'技术选型{X}'
|
|
194
|
+
],
|
|
195
|
+
retro: [
|
|
196
|
+
'代码质量{X}',
|
|
197
|
+
'{Y}需要改进',
|
|
198
|
+
'技术分享{X}',
|
|
199
|
+
'下次重构{X}'
|
|
200
|
+
],
|
|
201
|
+
planning: [
|
|
202
|
+
'技术预研{X}',
|
|
203
|
+
'重构计划{X}',
|
|
204
|
+
'性能优化{X}',
|
|
205
|
+
'代码审查{X}'
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
intern: {
|
|
209
|
+
standup: [
|
|
210
|
+
'昨天我学习了{X}',
|
|
211
|
+
'今天计划{X}',
|
|
212
|
+
'遇到{X}问题,请教了一下',
|
|
213
|
+
'正在学习中'
|
|
214
|
+
],
|
|
215
|
+
review: [
|
|
216
|
+
'我学到了{X}',
|
|
217
|
+
'这个方案好像可行',
|
|
218
|
+
'我可能需要指导',
|
|
219
|
+
'可以尝试实现'
|
|
220
|
+
],
|
|
221
|
+
brainstorm: [
|
|
222
|
+
'我想到了一个想法',
|
|
223
|
+
'可以从{X}角度考虑',
|
|
224
|
+
'请问{X}这样行吗',
|
|
225
|
+
'我补充一下'
|
|
226
|
+
],
|
|
227
|
+
retro: [
|
|
228
|
+
'我学到了很多',
|
|
229
|
+
'{X}做得很好',
|
|
230
|
+
'{Y}对我来说有点难',
|
|
231
|
+
'下次希望能多学学'
|
|
232
|
+
],
|
|
233
|
+
planning: [
|
|
234
|
+
'我想参与{X}任务',
|
|
235
|
+
'可能需要指导',
|
|
236
|
+
'我会努力学习',
|
|
237
|
+
'有不懂的及时请教'
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* 获取随机占位符值
|
|
243
|
+
*/
|
|
244
|
+
function getRandomPlaceholder() {
|
|
245
|
+
const placeholders = ['相关需求', '核心功能', '业务问题', '技术方案', '项目进展', '团队协作', '用户体验', '性能优化'];
|
|
246
|
+
return placeholders[Math.floor(Math.random() * placeholders.length)];
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* 填充模板
|
|
250
|
+
*/
|
|
251
|
+
function fillTemplate(template) {
|
|
252
|
+
const actions = ['处理', '跟进', '完善', 'review', '实现', '优化'];
|
|
253
|
+
const supports = ['协助', '指导', '帮助', '支持'];
|
|
254
|
+
return template.replace(/{X}/g, getRandomPlaceholder())
|
|
255
|
+
.replace(/{Y}/g, getRandomPlaceholder())
|
|
256
|
+
.replace(/{review}/g, 'review')
|
|
257
|
+
.replace(/{action}/g, () => actions[Math.floor(Math.random() * actions.length)])
|
|
258
|
+
.replace(/{support}/g, () => supports[Math.floor(Math.random() * supports.length)]);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* 生成会议发言
|
|
262
|
+
*/
|
|
263
|
+
function generateMeetingSuggestion(options) {
|
|
264
|
+
const role = options.role || 'boss';
|
|
265
|
+
const scenario = options.scenario || 'standup';
|
|
266
|
+
const roleTemplates = ROLE_MEETING_TEMPLATES[role] || ROLE_MEETING_TEMPLATES.boss;
|
|
267
|
+
const scenarioTemplates = roleTemplates[scenario] || roleTemplates.standup;
|
|
268
|
+
// 随机选择 1-3 个发言
|
|
269
|
+
const count = Math.floor(Math.random() * 3) + 1;
|
|
270
|
+
const suggestions = [];
|
|
271
|
+
for (let i = 0; i < count; i++) {
|
|
272
|
+
const template = scenarioTemplates[Math.floor(Math.random() * scenarioTemplates.length)];
|
|
273
|
+
suggestions.push(fillTemplate(template));
|
|
274
|
+
}
|
|
275
|
+
// 生成角色和场景名称
|
|
276
|
+
const roleNames = {
|
|
277
|
+
boss: '老板',
|
|
278
|
+
employee: '员工',
|
|
279
|
+
pm: '产品经理',
|
|
280
|
+
hr: 'HR',
|
|
281
|
+
techlead: '技术主管',
|
|
282
|
+
intern: '实习生'
|
|
283
|
+
};
|
|
284
|
+
const scenarioInfo = MEETING_SCENARIOS[scenario] || MEETING_SCENARIOS.standup;
|
|
285
|
+
// 生成输出
|
|
286
|
+
const output = [];
|
|
287
|
+
output.push(chalk_1.default.cyan('╔════════════════════════════════════════════════════════╗'));
|
|
288
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.white('会议发言建议生成器') + ' ' + chalk_1.default.cyan('║'));
|
|
289
|
+
output.push(chalk_1.default.cyan('╠════════════════════════════════════════════════════╣'));
|
|
290
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.yellow('角色: ') + roleNames[role] + ' ' + chalk_1.default.cyan('║'));
|
|
291
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.yellow('场景: ') + scenarioInfo.name + ' (' + scenarioInfo.description + ') ' + chalk_1.default.cyan('║'));
|
|
292
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.yellow('时长: ') + scenarioInfo.duration + ' ' + chalk_1.default.cyan('║'));
|
|
293
|
+
output.push(chalk_1.default.cyan('╠══════════════════════════════════════════════════════╣'));
|
|
294
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.cyan('║'));
|
|
295
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.green('💡 发言建议:') + ' ' + chalk_1.default.cyan('║'));
|
|
296
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.cyan('║'));
|
|
297
|
+
suggestions.forEach((suggestion, index) => {
|
|
298
|
+
output.push(chalk_1.default.cyan('║') + ` ${index + 1}. ${suggestion.padEnd(60)} ` + chalk_1.default.cyan('║'));
|
|
299
|
+
});
|
|
300
|
+
output.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.cyan('║'));
|
|
301
|
+
output.push(chalk_1.default.cyan('╚═══════════════════════════════════════════════════════════╝'));
|
|
302
|
+
return output.join('\n');
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* 会议发言建议命令
|
|
306
|
+
*/
|
|
307
|
+
function createMeetingCommand() {
|
|
308
|
+
const command = new commander_1.Command('meeting')
|
|
309
|
+
.description('会议发言建议 - 根据角色和场景生成会议发言建议')
|
|
310
|
+
.option('-r, --role <role>', '角色: boss, employee, pm, hr, techlead, intern', 'boss')
|
|
311
|
+
.option('-s, --scenario <type>', '场景: standup(站会), review(评审), brainstorm(头脑风暴), retro(回顾), planning(规划)', 'standup')
|
|
312
|
+
.option('-n, --number <count>', '建议数量(1-3,默认随机)');
|
|
313
|
+
command.action(async (options) => {
|
|
314
|
+
const role = options.role || 'boss';
|
|
315
|
+
const scenario = options.scenario || 'standup';
|
|
316
|
+
const suggestion = generateMeetingSuggestion({ role, scenario });
|
|
317
|
+
console.log();
|
|
318
|
+
console.log(suggestion);
|
|
319
|
+
console.log();
|
|
320
|
+
console.log(chalk_1.default.gray('💡 提示: 在实际会议中,根据情况灵活调整发言内容和时机'));
|
|
321
|
+
});
|
|
322
|
+
return command;
|
|
323
|
+
}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 周报生成器
|
|
4
|
+
* 功能:根据不同角色自动生成职场周报
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.generateWeeklyReport = generateWeeklyReport;
|
|
11
|
+
exports.createWeeklyCommand = createWeeklyCommand;
|
|
12
|
+
const commander_1 = require("commander");
|
|
13
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
14
|
+
/**
|
|
15
|
+
* 获取当前周数
|
|
16
|
+
*/
|
|
17
|
+
function getWeekNumber(date) {
|
|
18
|
+
const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
|
|
19
|
+
const pastDaysOfYear = (date.getTime() - firstDayOfYear.getTime()) / 86400000;
|
|
20
|
+
return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 周报模板配置
|
|
24
|
+
*/
|
|
25
|
+
const WEEKLY_TEMPLATES = {
|
|
26
|
+
boss: {
|
|
27
|
+
highlights: [
|
|
28
|
+
'本周{X}个下属的工作进行了指导和监督',
|
|
29
|
+
'与{X}位员工进行了1对1沟通',
|
|
30
|
+
'参加了{X}场管理层会议',
|
|
31
|
+
'对团队工作状态进行了{X}次检查'
|
|
32
|
+
],
|
|
33
|
+
plans: [
|
|
34
|
+
'下周计划重点关注{X}个项目的推进',
|
|
35
|
+
'计划进行{X}次团队培训',
|
|
36
|
+
'准备与{X}位核心员工进行深入沟通',
|
|
37
|
+
'计划召开{X}场部门协调会'
|
|
38
|
+
],
|
|
39
|
+
risks: [
|
|
40
|
+
'可能存在{X}个项目进度风险',
|
|
41
|
+
'需要注意{X}位员工的绩效问题',
|
|
42
|
+
'资源可能存在{X}%的缺口',
|
|
43
|
+
'可能面临{X}个外部挑战'
|
|
44
|
+
],
|
|
45
|
+
data: [
|
|
46
|
+
'本周团队产出提升{X}%',
|
|
47
|
+
'完成{X}个关键里程碑',
|
|
48
|
+
'团队加班时长{X}小时',
|
|
49
|
+
'客户满意度{X}%'
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
employee: {
|
|
53
|
+
highlights: [
|
|
54
|
+
'完成了{X}个分配任务',
|
|
55
|
+
'参与了{X}个项目会议',
|
|
56
|
+
'处理了{X}个工单/问题',
|
|
57
|
+
'学习了{X}项新技术/业务知识'
|
|
58
|
+
],
|
|
59
|
+
plans: [
|
|
60
|
+
'下周计划完成{X}个待办任务',
|
|
61
|
+
'准备{X}个文档/报告',
|
|
62
|
+
'计划学习{X}项新技能',
|
|
63
|
+
'跟进{X}个问题处理进度'
|
|
64
|
+
],
|
|
65
|
+
risks: [
|
|
66
|
+
'可能存在{X}个技术难点',
|
|
67
|
+
'{X}个任务可能时间紧张',
|
|
68
|
+
'需要等待{X}个依赖/支持',
|
|
69
|
+
'个人技能可能存在{X}个不足'
|
|
70
|
+
],
|
|
71
|
+
data: [
|
|
72
|
+
'完成任务{X}个',
|
|
73
|
+
'代码提交{X}次',
|
|
74
|
+
'修复Bug{X}个',
|
|
75
|
+
'参加培训{X}小时'
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
pm: {
|
|
79
|
+
highlights: [
|
|
80
|
+
'完成了{X}个需求的评审和确认',
|
|
81
|
+
'与{X}个干系人对齐了产品方向',
|
|
82
|
+
'进行了{X}场用户调研/数据分析',
|
|
83
|
+
'输出了{X}份产品文档/原型'
|
|
84
|
+
],
|
|
85
|
+
plans: [
|
|
86
|
+
'下周计划上线{X}个新功能',
|
|
87
|
+
'准备进行{X}场产品宣讲',
|
|
88
|
+
'计划优化{X}个核心流程',
|
|
89
|
+
'准备{X}个版本的迭代规划'
|
|
90
|
+
],
|
|
91
|
+
risks: [
|
|
92
|
+
'{X}个需求可能存在变更风险',
|
|
93
|
+
'开发资源可能存在{X}%的缺口',
|
|
94
|
+
'{X}个功能可能延期上线',
|
|
95
|
+
'用户反馈可能存在{X}个不确定性'
|
|
96
|
+
],
|
|
97
|
+
data: [
|
|
98
|
+
'需求完成率{X}%',
|
|
99
|
+
'需求评审{X}场',
|
|
100
|
+
'文档输出{X}份',
|
|
101
|
+
'干系人对齐{X}次'
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
hr: {
|
|
105
|
+
highlights: [
|
|
106
|
+
'组织了{X}场团队建设活动',
|
|
107
|
+
'完成了{X}位员工的入职/离职手续',
|
|
108
|
+
'处理了{X}个员工关系/问题',
|
|
109
|
+
'推进了{X}项企业文化建设工作'
|
|
110
|
+
],
|
|
111
|
+
plans: [
|
|
112
|
+
'下周计划组织{X}场培训活动',
|
|
113
|
+
'准备进行{X}次员工访谈',
|
|
114
|
+
'计划优化{X}项HR流程制度',
|
|
115
|
+
'准备{X}场团建/文化活动'
|
|
116
|
+
],
|
|
117
|
+
risks: [
|
|
118
|
+
'员工满意度可能存在{X}%的波动',
|
|
119
|
+
'{X}位核心员工可能存在离职风险',
|
|
120
|
+
'招聘计划可能存在{X}%的缺口',
|
|
121
|
+
'文化建设可能存在{X}个阻力'
|
|
122
|
+
],
|
|
123
|
+
data: [
|
|
124
|
+
'新入职员工{X}人',
|
|
125
|
+
'离职员工{X}人',
|
|
126
|
+
'培训覆盖率{X}%',
|
|
127
|
+
'员工满意度{X}%'
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
techlead: {
|
|
131
|
+
highlights: [
|
|
132
|
+
'完成了{X}次代码审查',
|
|
133
|
+
'处理了{X}个技术债务',
|
|
134
|
+
'进行了{X}场技术分享会',
|
|
135
|
+
'重构了{X}个核心模块'
|
|
136
|
+
],
|
|
137
|
+
plans: [
|
|
138
|
+
'下周计划优化{X}个性能瓶颈',
|
|
139
|
+
'准备进行{X}项技术调研',
|
|
140
|
+
'计划重构{X}个遗留模块',
|
|
141
|
+
'准备输出{X}份技术文档'
|
|
142
|
+
],
|
|
143
|
+
risks: [
|
|
144
|
+
'{X}个系统可能存在稳定性风险',
|
|
145
|
+
'{X}个技术债务可能影响交付',
|
|
146
|
+
'团队技能可能存在{X}个短板',
|
|
147
|
+
'{X}个依赖项可能存在兼容性问题'
|
|
148
|
+
],
|
|
149
|
+
data: [
|
|
150
|
+
'代码审查{X}次',
|
|
151
|
+
'Bug修复{X}个',
|
|
152
|
+
'性能优化{X}项',
|
|
153
|
+
'技术分享{X}场'
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
intern: {
|
|
157
|
+
highlights: [
|
|
158
|
+
'完成了{X}个分配的学习任务',
|
|
159
|
+
'参与了{X}个项目会议',
|
|
160
|
+
'向{X}位同事请教了问题',
|
|
161
|
+
'学习了{X}项新技能'
|
|
162
|
+
],
|
|
163
|
+
plans: [
|
|
164
|
+
'下周计划学习{X}项新内容',
|
|
165
|
+
'准备参与{X}个项目',
|
|
166
|
+
'计划请教{X}位资深同事',
|
|
167
|
+
'计划阅读{X}篇技术文档'
|
|
168
|
+
],
|
|
169
|
+
risks: [
|
|
170
|
+
'可能存在{X}个知识盲区',
|
|
171
|
+
'{X}个任务可能超出能力范围',
|
|
172
|
+
'需要依赖{X}位同事的指导',
|
|
173
|
+
'学习曲线可能存在{X}个挑战'
|
|
174
|
+
],
|
|
175
|
+
data: [
|
|
176
|
+
'学习时长{X}小时',
|
|
177
|
+
'完成任务{X}个',
|
|
178
|
+
'提问{X}次',
|
|
179
|
+
'文档阅读{X}篇'
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* 生成随机数
|
|
185
|
+
*/
|
|
186
|
+
function randomCount(min = 1, max = 5) {
|
|
187
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 填充模板中的占位符
|
|
191
|
+
*/
|
|
192
|
+
function fillTemplate(template, role) {
|
|
193
|
+
const roleTemplate = WEEKLY_TEMPLATES[role] || WEEKLY_TEMPLATES.boss;
|
|
194
|
+
return template.replace(/{X}/g, () => randomCount().toString());
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 生成完整周报
|
|
198
|
+
*/
|
|
199
|
+
function generateWeeklyReport(options) {
|
|
200
|
+
const role = options.role || 'boss';
|
|
201
|
+
const week = options.week || getWeekNumber(new Date());
|
|
202
|
+
const roleTemplate = WEEKLY_TEMPLATES[role];
|
|
203
|
+
// 生成内容
|
|
204
|
+
const highlightsCount = randomCount(3, 5);
|
|
205
|
+
const plansCount = randomCount(2, 4);
|
|
206
|
+
const risksCount = randomCount(1, 2);
|
|
207
|
+
const highlights = [];
|
|
208
|
+
const plans = [];
|
|
209
|
+
const risks = [];
|
|
210
|
+
const data = [];
|
|
211
|
+
for (let i = 0; i < highlightsCount; i++) {
|
|
212
|
+
const template = roleTemplate.highlights[i % roleTemplate.highlights.length];
|
|
213
|
+
highlights.push(` ${['一', '二', '三', '四', '五'][i]}、${fillTemplate(template, role)}`);
|
|
214
|
+
}
|
|
215
|
+
for (let i = 0; i < plansCount; i++) {
|
|
216
|
+
const template = roleTemplate.plans[i % roleTemplate.plans.length];
|
|
217
|
+
plans.push(` ${['一', '二', '三', '四'][i]}、${fillTemplate(template, role)}`);
|
|
218
|
+
}
|
|
219
|
+
for (let i = 0; i < risksCount; i++) {
|
|
220
|
+
const template = roleTemplate.risks[i % roleTemplate.risks.length];
|
|
221
|
+
risks.push(` ${['一', '二'][i]}、${fillTemplate(template, role)}`);
|
|
222
|
+
}
|
|
223
|
+
// 生成数据部分(如果模板有)
|
|
224
|
+
if (roleTemplate.data) {
|
|
225
|
+
for (let i = 0; i < roleTemplate.data.length; i++) {
|
|
226
|
+
const template = roleTemplate.data[i];
|
|
227
|
+
data.push(` • ${fillTemplate(template, role)}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// 组装报告
|
|
231
|
+
const roleNames = {
|
|
232
|
+
boss: '老板',
|
|
233
|
+
employee: '员工',
|
|
234
|
+
pm: '产品经理',
|
|
235
|
+
hr: 'HR',
|
|
236
|
+
techlead: '技术主管',
|
|
237
|
+
intern: '实习生'
|
|
238
|
+
};
|
|
239
|
+
const report = [];
|
|
240
|
+
report.push(chalk_1.default.cyan('╔══════════════════════════════════════════════════════════════╗'));
|
|
241
|
+
report.push(chalk_1.default.cyan('║') + chalk_1.default.bold.white(` 周报生成器 - ${roleNames[role]} `) + chalk_1.default.cyan('║'));
|
|
242
|
+
report.push(chalk_1.default.cyan('╠══════════════════════════════════════════════════════════════╣'));
|
|
243
|
+
report.push(chalk_1.default.cyan('║') + ` 第 ${week} 周 ` + chalk_1.default.cyan('║'));
|
|
244
|
+
report.push(chalk_1.default.cyan('╠══════════════════════════════════════════════════════════════╣'));
|
|
245
|
+
// 本周工作
|
|
246
|
+
report.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.green('本周工作:') + ' '.padEnd(38) + chalk_1.default.cyan('║'));
|
|
247
|
+
report.push(chalk_1.default.cyan('║'));
|
|
248
|
+
highlights.forEach(h => report.push(chalk_1.default.cyan('║') + h.padEnd(68) + chalk_1.default.cyan('║')));
|
|
249
|
+
report.push(chalk_1.default.cyan('║'));
|
|
250
|
+
// 下周计划
|
|
251
|
+
report.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.yellow('下周计划:') + ' '.padEnd(38) + chalk_1.default.cyan('║'));
|
|
252
|
+
report.push(chalk_1.default.cyan('║'));
|
|
253
|
+
plans.forEach(p => report.push(chalk_1.default.cyan('║') + p.padEnd(68) + chalk_1.default.cyan('║')));
|
|
254
|
+
report.push(chalk_1.default.cyan('║'));
|
|
255
|
+
// 风险与问题
|
|
256
|
+
if (risks.length > 0) {
|
|
257
|
+
report.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.red('风险与问题:') + ' '.padEnd(38) + chalk_1.default.cyan('║'));
|
|
258
|
+
report.push(chalk_1.default.cyan('║'));
|
|
259
|
+
risks.forEach(r => report.push(chalk_1.default.cyan('║') + r.padEnd(68) + chalk_1.default.cyan('║')));
|
|
260
|
+
report.push(chalk_1.default.cyan('║'));
|
|
261
|
+
}
|
|
262
|
+
// 数据统计(如果有)
|
|
263
|
+
if (data.length > 0) {
|
|
264
|
+
report.push(chalk_1.default.cyan('║') + ' ' + chalk_1.default.bold.blue('数据统计:') + ' '.padEnd(38) + chalk_1.default.cyan('║'));
|
|
265
|
+
report.push(chalk_1.default.cyan('║'));
|
|
266
|
+
data.forEach(d => report.push(chalk_1.default.cyan('║') + d.padEnd(68) + chalk_1.default.cyan('║')));
|
|
267
|
+
report.push(chalk_1.default.cyan('║'));
|
|
268
|
+
}
|
|
269
|
+
report.push(chalk_1.default.cyan('╚══════════════════════════════════════════════════════════════════╝'));
|
|
270
|
+
return report.join('\n');
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* 周报生成器命令
|
|
274
|
+
*/
|
|
275
|
+
function createWeeklyCommand() {
|
|
276
|
+
const command = new commander_1.Command('weekly')
|
|
277
|
+
.description('周报生成器 - 根据角色自动生成职场周报')
|
|
278
|
+
.option('-r, --role <role>', '角色: boss, employee, pm, hr, techlead, intern', 'boss')
|
|
279
|
+
.option('-w, --week <number>', '周数(默认当前周)')
|
|
280
|
+
.option('-H, --highlights <number>', '亮点数量(默认随机3-5个)')
|
|
281
|
+
.option('-o, --output <file>', '输出到文件(可选)');
|
|
282
|
+
command.action(async (options) => {
|
|
283
|
+
const role = options.role || 'boss';
|
|
284
|
+
const week = options.week ? parseInt(options.week) : getWeekNumber(new Date());
|
|
285
|
+
const report = generateWeeklyReport({
|
|
286
|
+
role,
|
|
287
|
+
week,
|
|
288
|
+
highlights: options.highlights
|
|
289
|
+
});
|
|
290
|
+
console.log();
|
|
291
|
+
console.log(report);
|
|
292
|
+
console.log();
|
|
293
|
+
if (options.output) {
|
|
294
|
+
const { writeFile } = require('fs').promises;
|
|
295
|
+
const { join } = require('path');
|
|
296
|
+
const outputPath = join(process.cwd(), options.output);
|
|
297
|
+
await writeFile(outputPath, report.replace(/[\u001b-\u001b-\u001c-\u001d-\u001e-\u001f]/g, ''), 'utf-8');
|
|
298
|
+
console.log(chalk_1.default.green('✓') + ' 周报已保存到: ' + outputPath);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
return command;
|
|
302
|
+
}
|