工作计划管理skills

This commit is contained in:
黎润豪 2026-04-13 17:36:44 +08:00
parent f237feb79e
commit dbced98449
5 changed files with 981 additions and 0 deletions

View File

@ -38,6 +38,14 @@
"skills": [
"./load-codestyle"
]
},
{
"name": "work-weekly-report",
"source": "./skills",
"strict": false,
"skills": [
"./work-weekly-report"
]
}
]
}

View File

@ -0,0 +1,75 @@
# work-weekly-report
工作计划管理工具。用于管理个人工作周报,包括制定本周工作计划、记录日常工作、更新工作进度、查询历史周报等。
## 目录结构
```
work-weekly-report/
├── SKILL.md # Skill 定义文件
├── README.md # 本文件
├── scripts/ # 脚本目录
│ └── work-weekly-report.js
└── data/ # 数据存储目录
└── weekly-reports.json
```
## 功能概述
- **制定本周工作计划**: 为当前工作周制定或更新工作计划
- **更新工作记录**: 记录指定日期的实际工作情况
- **输出本周未完成工作**: 汇总当前工作周中未完成的任务
- **查询指定周周报**: 查看指定工作周的工作计划与实际记录
- **更新计划项状态**: 将某个计划项标记为完成或其他状态
- **设置周报总结**: 为某周添加总结文字
## 工作周定义
- **工作周**: 周一至周五(法定工作日)
- **周编号**: ISO 8601 标准,格式 `YYYY-Www`(如 `2026-W15` 表示 2026 年第 15 周)
- **周起始**: 周一为该周的第一天,周五为最后一天
## 使用方式
### 触发命令
- `/work-weekly-report`
- "制定本周工作计划"
- "更新今天的工作记录"
- "查看本周未完成的工作"
- "查询 2026-W15 的周报"
### CLI 命令
```bash
# 制定本周计划
node scripts/work-weekly-report.js plan --tasks "任务1" "任务2"
# 更新今天的工作记录
node scripts/work-weekly-report.js record --content "完成了XX任务" --status completed
# 查看本周未完成
node scripts/work-weekly-report.js pending
# 查询指定周
node scripts/work-weekly-report.js query --week "2026-W15"
# 设置周报总结
node scripts/work-weekly-report.js summary --week "2026-W15" --content "本周主要完成了..."
```
## 数据存储
数据存储在 `data/weekly-reports.json` 文件中,采用 JSON 格式,包含以下结构:
- `meta`: 版本信息
- `weeklyReports`: 按周编号索引的工作周报数据
- `plan`: 计划任务列表
- `records`: 每日工作记录
- `summary`: 周报总结
## 注意事项
1. 数据文件会自动创建,首次使用时会初始化
2. 所有日期需为有效的法定工作日(周一至周五)
3. 建议每次完成工作后及时记录,便于周末生成周报

View File

@ -0,0 +1,210 @@
---
name: work-weekly-report
description: |
工作周报管理工具。用于管理个人工作周报,包括制定本周工作计划、记录日常工作、更新工作进度、查询历史周报等。
当用户提到以下场景时使用此 Skill
(1) 制定本周工作计划、安排工作
(2) 更新今天或指定日期的工作记录
(3) 查看本周未完成的工作
(4) 查询指定工作周的周报
(5) 用户提到 "周报"、"工作计划"、"工作记录"、"工作周"
argument-hint: "[操作] [参数]"
allowed-tools: Read, Bash, Glob, Grep
---
# 工作周报管理 Skill
## 概述
此 Skill 用于管理个人工作周报,支持工作计划制定、日常工作记录、未完成工作统计和历史周报查询。
## 工作周定义
- **工作周**: 周一至周五(法定工作日)
- **周编号**: ISO 8601 标准,格式 `YYYY-Www`(如 `2026-W15` 表示 2026 年第 15 周)
- **周起始**: 周一为该周的第一天,周五为最后一天
## 数据存储
数据存储在 `data/weekly-reports.json` 文件中,采用 JSON 格式。
## 功能清单
### 功能1: 制定本周工作计划
为当前工作周制定或更新工作计划。
**使用示例**:
```
制定本周工作计划
安排本周工作
本周计划完成 A、B、C 任务
```
**CLI 命令**:
```bash
# 制定本周计划
node scripts/work-weekly-report.js plan --tasks "任务1" "任务2" "任务3"
# 制定指定周计划(带优先级)
node scripts/work-weekly-report.js plan --week "2026-W15" --tasks "任务1" "任务2" --priority high
```
---
### 功能2: 更新工作记录
记录指定日期的实际工作情况。
**使用示例**:
```
更新今天的工作记录
记录今天完成的工作
更新 2026-04-10 的工作
```
**CLI 命令**:
```bash
# 更新今天的工作记录
node scripts/work-weekly-report.js record --content "完成了XX任务" --status completed
# 更新指定日期的工作记录
node scripts/work-weekly-report.js record --date "2026-04-09" --content "继续开发XX功能" --status in-progress
# 带工时记录
node scripts/work-weekly-report.js record --date "2026-04-10" --content "完成代码审查" --status completed --hours 2
```
---
### 功能3: 输出本周未完成的工作
汇总当前工作周中未完成的任务。
**使用示例**:
```
本周有哪些未完成的工作
查看未完成任务
本周还有什么没做完的
```
**CLI 命令**:
```bash
node scripts/work-weekly-report.js pending
node scripts/work-weekly-report.js pending --week "2026-W15"
```
---
### 功能4: 查询指定工作周的周报
查看指定工作周的工作计划与实际记录。
**使用示例**:
```
查询 2026-W15 的周报
查看第 15 周的工作情况
查看上周的周报
本周工作总结
```
**CLI 命令**:
```bash
# 查询本周
node scripts/work-weekly-report.js query
# 查询指定周
node scripts/work-weekly-report.js query --week "2026-W15"
# 简洁摘要格式
node scripts/work-weekly-report.js query --week "2026-W15" --format summary
```
---
### 功能5: 更新计划项状态
将某个计划项标记为完成或其他状态。
**使用示例**:
```
把任务A标记为完成
更新计划项状态
```
**CLI 命令**:
```bash
node scripts/work-weekly-report.js update-status --week "2026-W15" --plan-item "uuid" --status completed
```
---
### 功能6: 设置周报总结
为某周添加总结文字。
**CLI 命令**:
```bash
node scripts/work-weekly-report.js summary --week "2026-W15" --content "本周主要完成了..."
```
---
## 周标识支持
查询和操作支持多种周标识格式:
- `YYYY-Www` - ISO 格式(如 `2026-W15`
- `本周`、`当前周` - 当前工作周
- `上周`、`上上周` - 相对上周
- `下周` - 相对下周
## 数据文件结构
```json
{
"meta": {
"version": "1.0.0",
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-04-13T09:30:00.000Z"
},
"weeklyReports": {
"2026-W15": {
"weekNumber": "2026-W15",
"weekStartDate": "2026-04-07",
"weekEndDate": "2026-04-11",
"plan": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"description": "完成项目 A 的开发工作",
"expectedDate": "2026-04-10",
"priority": "high",
"status": "completed",
"createdAt": "2026-04-07T09:00:00.000Z",
"updatedAt": "2026-04-10T18:00:00.000Z"
}
],
"records": {
"2026-04-07": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"content": "开始项目 A 的架构设计",
"date": "2026-04-07",
"status": "completed",
"hours": 6,
"planItemId": "550e8400-e29b-41d4-a716-446655440001"
}
]
},
"summary": "本周主要完成了项目 A 的开发工作..."
}
}
}
```
## 注意事项
1. 数据文件会自动创建,首次使用时会初始化
2. 所有日期需为有效的法定工作日(周一至周五)
3. 建议每次完成工作后及时记录,便于周末生成周报

View File

@ -0,0 +1,8 @@
{
"meta": {
"version": "1.0.0",
"createdAt": "2026-04-13T00:00:00.000Z",
"updatedAt": "2026-04-13T00:00:00.000Z"
},
"weeklyReports": {}
}

View File

@ -0,0 +1,680 @@
#!/usr/bin/env node
/**
* 工作周报管理工具
* 用于管理个人工作周报包括制定计划记录工作查询周报等
*/
const fs = require('fs');
const path = require('path');
// 数据文件路径
const DATA_DIR = path.join(__dirname, '..', 'data');
const DATA_FILE = path.join(DATA_DIR, 'weekly-reports.json');
// 确保数据目录存在
if (!fs.existsSync(DATA_DIR)) {
fs.mkdirSync(DATA_DIR, { recursive: true });
}
/**
* 生成 UUID
*/
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/**
* 获取本地日期字符串 YYYY-MM-DD
*/
function toLocalDateString(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
/**
* 获取当前日期字符串
*/
function getCurrentDateStr() {
const now = new Date();
return now.toISOString().split('T')[0];
}
/**
* 获取当前时间 ISO 字符串
*/
function getCurrentISO() {
return new Date().toISOString();
}
/**
* 判断是否为法定工作日周一至周五
*/
function isWorkday(dateStr) {
const date = new Date(dateStr);
const day = date.getDay();
return day >= 1 && day <= 5;
}
/**
* 获取日期所在周的第一天周一
*/
function getWeekStartDate(dateStr) {
const date = new Date(dateStr);
const day = date.getDay();
// 计算到周一的天数
const diff = day === 0 ? -6 : 1 - day;
const monday = new Date(date);
monday.setDate(date.getDate() + diff);
return toLocalDateString(monday);
}
/**
* 获取日期所在周的周五
*/
function getWeekEndDate(weekStartDate) {
const monday = new Date(weekStartDate);
const friday = new Date(monday);
friday.setDate(monday.getDate() + 4);
return toLocalDateString(friday);
}
/**
* 获取 ISO 周编号 (YYYY-Www)
*/
function getWeekNumber(dateStr) {
const date = new Date(dateStr);
// ISO 周码每年的第一个周四所在的周为第1周
const thursday = new Date(date);
thursday.setDate(date.getDate() + (4 - (date.getDay() === 0 ? 7 : date.getDay())));
const yearStart = new Date(thursday.getFullYear(), 0, 1);
const weekNum = Math.ceil(((thursday - yearStart) / 86400000 + 1) / 7);
return `${thursday.getFullYear()}-W${String(weekNum).padStart(2, '0')}`;
}
/**
* 获取当前工作周信息
*/
function getCurrentWeek() {
const today = getCurrentDateStr();
return getWeekInfo(today);
}
/**
* 获取指定日期所在的工作周信息
*/
function getWeekInfo(dateStr) {
const weekStart = getWeekStartDate(dateStr);
const weekEnd = getWeekEndDate(weekStart);
const weekNumber = getWeekNumber(dateStr);
return {
weekNumber,
startDate: weekStart,
endDate: weekEnd
};
}
/**
* 解析周标识为周编号
*/
function parseWeekIdentifier(identifier) {
if (!identifier || identifier === '本周' || identifier === '当前周') {
return getCurrentWeek().weekNumber;
}
if (identifier === '上周') {
const today = new Date();
today.setDate(today.getDate() - 7);
return getWeekNumber(today.toISOString().split('T')[0]);
}
if (identifier === '上上周') {
const today = new Date();
today.setDate(today.getDate() - 14);
return getWeekNumber(today.toISOString().split('T')[0]);
}
if (identifier === '下周') {
const today = new Date();
today.setDate(today.getDate() + 7);
return getWeekNumber(today.toISOString().split('T')[0]);
}
// 假设是 YYYY-Www 格式
if (/^\d{4}-W\d{2}$/.test(identifier)) {
return identifier;
}
throw new Error(`无法解析周标识: ${identifier}`);
}
/**
* 加载数据文件
*/
function loadData() {
if (!fs.existsSync(DATA_FILE)) {
const initial = {
meta: {
version: '1.0.0',
createdAt: getCurrentISO(),
updatedAt: getCurrentISO()
},
weeklyReports: {}
};
fs.writeFileSync(DATA_FILE, JSON.stringify(initial, null, 2), 'utf8');
return initial;
}
const content = fs.readFileSync(DATA_FILE, 'utf8');
return JSON.parse(content);
}
/**
* 保存数据文件
*/
function saveData(data) {
data.meta.updatedAt = getCurrentISO();
fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2), 'utf8');
}
/**
* 从周编号反推该周的周一日期
* 使用 ISO 8601 标准每年第一个周四所在的周为第1周W1从该周的周一开始
*/
function getWeekStartFromWeekNumber(year, weekNum) {
const MS_PER_DAY = 24 * 60 * 60 * 1000;
// 找到该年1月4日ISO 8601 定义包含该年第一个周四的那一周是W1
const jan4 = new Date(year, 0, 4);
const jan4Day = jan4.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat
// 找到W1的周一
let firstMonday;
if (jan4Day === 1) {
// 1月4日是周一 -> W1周一是1月4日
firstMonday = jan4;
} else if (jan4Day === 0) {
// 1月4日是周日 -> W1周一是上周一12月X日
// 1月4日 - 7天 = 12月28日上上个周一再 -1天 = 12月29日上周一
firstMonday = new Date(jan4.getTime() - 7 * MS_PER_DAY);
// 但这已经是12月28了而1月4日是周日那上周一是12月29日
// 所以实际上 1月4日 - 8天 = 12月27... 这不对
// 让我重新想:
// 如果1月4日是周日那这一周是 Dec 28 - Jan 3 (W1 ends Jan 3)
// 所以W1的周一是 Dec 28
// 那么 Dec 28 + 7 = Jan 4W2从 Jan 5开始
// 所以 W1 of 2026 = Dec 28 - Jan 3
// W1 starts on Monday Dec 28
// Let me recalculate: Jan 4 - 6 = Dec 29 (that's Monday if Jan 4 is Sunday)
// Wait, if Jan 4 is Sunday, then Jan 4 - 1 = Jan 3 (Saturday)
// Jan 4 - 2 = Jan 2, ..., Jan 4 - 7 = Dec 28
// But that's 7 days back, not 6. And Dec 28 is Monday?
// Let me just use getTime()
const daysToSubtract = jan4Day === 0 ? 6 : jan4Day - 1;
firstMonday = new Date(jan4.getTime() - daysToSubtract * MS_PER_DAY);
} else {
// 1月4日是 Tue(2), Wed(3), Thu(4), Fri(5), Sat(6) -> 找到上溯到周一
// 如果1月4日是周三那周一就是1月4日 - 2天
// daysToSubtract = 4 - 1 = 3, 1月4日 - 3天 = 1月1日 = 周一 ✓
const daysToSubtract = jan4Day - 1;
firstMonday = new Date(jan4.getTime() - daysToSubtract * MS_PER_DAY);
}
// 计算目标周的周一
const targetMonday = new Date(firstMonday.getTime() + (weekNum - 1) * 7 * MS_PER_DAY);
return targetMonday;
}
/**
* 获取或创建指定周的周报对象
*/
function getOrCreateWeeklyReport(weekNumber) {
const data = loadData();
if (!data.weeklyReports[weekNumber]) {
const [yearStr, weekPart] = weekNumber.split('-W');
const year = parseInt(yearStr, 10);
const weekNum = parseInt(weekPart, 10);
const targetMonday = getWeekStartFromWeekNumber(year, weekNum);
const targetFriday = new Date(targetMonday);
targetFriday.setDate(targetMonday.getDate() + 4);
data.weeklyReports[weekNumber] = {
weekNumber,
weekStartDate: toLocalDateString(targetMonday),
weekEndDate: toLocalDateString(targetFriday),
plan: [],
records: {},
summary: ''
};
}
return { data, report: data.weeklyReports[weekNumber] };
}
/**
* 制定/更新周计划
*/
function planWeek(weekNumber, tasks, priority = 'medium') {
const { data, report } = getOrCreateWeeklyReport(weekNumber);
const now = getCurrentISO();
for (const taskDesc of tasks) {
const planItem = {
id: generateUUID(),
description: taskDesc,
expectedDate: null,
priority: priority,
status: 'pending',
createdAt: now,
updatedAt: now
};
report.plan.push(planItem);
}
saveData(data);
return report;
}
/**
* 添加工作记录
*/
function addRecord(date, content, status, options = {}) {
const { hours, planItemId } = options;
if (!isWorkday(date)) {
throw new Error(`${date} 不是法定工作日(周一至周五)`);
}
const weekInfo = getWeekInfo(date);
const { data, report } = getOrCreateWeeklyReport(weekInfo.weekNumber);
if (!report.records[date]) {
report.records[date] = [];
}
const record = {
id: generateUUID(),
content,
date,
status,
hours: hours || null,
planItemId: planItemId || null,
createdAt: getCurrentISO(),
updatedAt: getCurrentISO()
};
report.records[date].push(record);
// 如果有关联的计划项,自动更新其状态
if (planItemId) {
const planItem = report.plan.find(p => p.id === planItemId);
if (planItem) {
planItem.status = status === 'completed' ? 'completed' :
status === 'in-progress' ? 'in-progress' : planItem.status;
planItem.updatedAt = getCurrentISO();
}
}
saveData(data);
return report;
}
/**
* 获取未完成的工作项
*/
function getPendingItems(weekIdentifier) {
const weekNumber = parseWeekIdentifier(weekIdentifier);
const { data, report } = getOrCreateWeeklyReport(weekNumber);
const pending = report.plan.filter(p => p.status === 'pending' || p.status === 'in-progress');
// 按优先级排序
const priorityOrder = { high: 0, medium: 1, low: 2 };
pending.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
return pending;
}
/**
* 查询周报
*/
function queryWeek(weekIdentifier, format = 'detail') {
const weekNumber = parseWeekIdentifier(weekIdentifier);
const { report } = getOrCreateWeeklyReport(weekNumber);
if (format === 'summary') {
return formatWeekSummary(report);
}
return report;
}
/**
* 格式化周报摘要
*/
function formatWeekSummary(report) {
const total = report.plan.length;
const completed = report.plan.filter(p => p.status === 'completed').length;
const pending = report.plan.filter(p => p.status === 'pending' || p.status === 'in-progress');
let output = `周报摘要: ${report.weekNumber} (${report.weekStartDate}${report.weekEndDate})\n`;
output += '================================================================\n\n';
output += `计划完成率: ${completed}/${total}`;
if (total > 0) {
output += ` (${Math.round(completed / total * 100)}%)`;
}
output += '\n\n';
if (report.plan.length > 0) {
output += '计划项:\n';
for (const item of report.plan) {
const statusIcon = item.status === 'completed' ? '[√]' : '[ ]';
const priorityTag = item.priority === 'high' ? '[高]' : item.priority === 'low' ? '[低]' : '[中]';
output += ` ${statusIcon} ${priorityTag} ${item.description}`;
if (item.expectedDate) {
output += ` (预计: ${item.expectedDate})`;
}
output += '\n';
}
output += '\n';
}
if (Object.keys(report.records).length > 0) {
output += '每日记录:\n';
const sortedDates = Object.keys(report.records).sort();
for (const date of sortedDates) {
const records = report.records[date];
const hours = records.reduce((sum, r) => sum + (r.hours || 0), 0);
const content = records.map(r => r.content).join('; ');
output += ` - ${date}: ${content}`;
if (hours > 0) {
output += ` (${hours}h)`;
}
output += '\n';
}
output += '\n';
}
if (pending.length > 0) {
output += '未完成工作:\n';
for (const item of pending) {
output += ` - ${item.description}\n`;
}
output += '\n';
}
if (report.summary) {
output += `总结: ${report.summary}\n`;
}
return output;
}
/**
* 更新计划项状态
*/
function updatePlanItemStatus(weekNumber, planItemId, status) {
const { data, report } = getOrCreateWeeklyReport(weekNumber);
const planItem = report.plan.find(p => p.id === planItemId);
if (!planItem) {
throw new Error(`未找到计划项: ${planItemId}`);
}
planItem.status = status;
planItem.updatedAt = getCurrentISO();
saveData(data);
return report;
}
/**
* 设置周报总结
*/
function setSummary(weekNumber, summary) {
const { data, report } = getOrCreateWeeklyReport(weekNumber);
report.summary = summary;
saveData(data);
return report;
}
/**
* 删除计划项
*/
function removePlanItem(weekNumber, planItemId) {
const { data, report } = getOrCreateWeeklyReport(weekNumber);
const index = report.plan.findIndex(p => p.id === planItemId);
if (index === -1) {
throw new Error(`未找到计划项: ${planItemId}`);
}
report.plan.splice(index, 1);
saveData(data);
return report;
}
/**
* 获取工作周的所有工作日
*/
function getWorkdays(weekNumber) {
const { report } = getOrCreateWeeklyReport(weekNumber);
const workdays = [];
const current = new Date(report.weekStartDate);
const end = new Date(report.weekEndDate);
while (current <= end) {
workdays.push(current.toISOString().split('T')[0]);
current.setDate(current.getDate() + 1);
}
return workdays;
}
// === CLI 模式 ===
if (require.main === module) {
const args = process.argv.slice(2);
const command = args[0];
// 已知的标志列表
const FLAGS = ['--week', '--tasks', '--priority', '--date', '--content', '--status', '--hours', '--plan-item', '--format'];
function getArgValue(flag) {
const index = args.indexOf(flag);
if (index !== -1 && index + 1 < args.length) {
const nextArg = args[index + 1];
// 如果下一个参数也是标志返回null
if (FLAGS.includes(nextArg)) {
return null;
}
return nextArg;
}
// 支持 --flag=value 格式
const combined = args.find(arg => arg.startsWith(`${flag}=`));
if (combined) {
return combined.split('=')[1];
}
return null;
}
function getRemainingArgs(flag) {
const index = args.indexOf(flag);
if (index === -1) return [];
const result = [];
let i = index + 1;
while (i < args.length) {
const arg = args[i];
// 如果遇到另一个标志,停止
if (FLAGS.includes(arg)) {
break;
}
result.push(arg);
i++;
}
return result;
}
try {
switch (command) {
case 'plan': {
const week = getArgValue('--week') || getCurrentWeek().weekNumber;
const tasks = getRemainingArgs('--tasks');
if (tasks.length === 0) {
console.error('错误: 请提供任务列表 (--tasks "任务1" "任务2" ...)');
process.exit(1);
}
const priority = getArgValue('--priority') || 'medium';
const report = planWeek(week, tasks, priority);
console.log(`已在 ${report.weekNumber} 创建 ${tasks.length} 个计划项`);
console.log('\n计划项:');
report.plan.slice(-tasks.length).forEach((item, i) => {
console.log(` ${i + 1}. [${item.priority}] ${item.description} (${item.id})`);
});
break;
}
case 'record': {
const date = getArgValue('--date') || getCurrentDateStr();
const content = getArgValue('--content');
if (!content) {
console.error('错误: 请提供工作内容 (--content "内容")');
process.exit(1);
}
const status = getArgValue('--status') || 'in-progress';
const hours = getArgValue('--hours') ? parseFloat(getArgValue('--hours')) : null;
const planItemId = getArgValue('--plan-item');
const report = addRecord(date, content, status, { hours, planItemId });
console.log(`已在 ${date} 添加工作记录`);
console.log(`${report.weekNumber} 当前共有 ${report.plan.length} 个计划项`);
break;
}
case 'pending': {
const week = getArgValue('--week') || getCurrentWeek().weekNumber;
const pending = getPendingItems(week);
const currentWeek = getCurrentWeek();
console.log(`本周未完成的工作 (${week})\n`);
console.log('========================================\n');
if (pending.length === 0) {
console.log('所有任务已完成!');
} else {
const high = pending.filter(p => p.priority === 'high');
const medium = pending.filter(p => p.priority === 'medium');
const low = pending.filter(p => p.priority === 'low');
if (high.length > 0) {
console.log('[高优先级]');
high.forEach(p => console.log(` - ${p.description}`));
console.log();
}
if (medium.length > 0) {
console.log('[中优先级]');
medium.forEach(p => console.log(` - ${p.description}`));
console.log();
}
if (low.length > 0) {
console.log('[低优先级]');
low.forEach(p => console.log(` - ${p.description}`));
console.log();
}
}
console.log(`${pending.length} 项未完成任务`);
break;
}
case 'query': {
const week = getArgValue('--week') || '本周';
const format = getArgValue('--format') || 'detail';
const weekNumber = parseWeekIdentifier(week);
const result = queryWeek(weekNumber, format);
console.log(typeof result === 'string' ? result : JSON.stringify(result, null, 2));
break;
}
case 'update-status': {
const weekIdentifier = getArgValue('--week') || '本周';
const planItemId = getArgValue('--plan-item');
const status = getArgValue('--status');
if (!planItemId || !status) {
console.error('错误: 请提供计划项ID (--plan-item) 和状态 (--status)');
process.exit(1);
}
const weekNumber = parseWeekIdentifier(weekIdentifier);
const report = updatePlanItemStatus(weekNumber, planItemId, status);
console.log(`已更新计划项 ${planItemId} 状态为 ${status}`);
console.log(`${report.weekNumber} 计划完成率: ${report.plan.filter(p => p.status === 'completed').length}/${report.plan.length}`);
break;
}
case 'summary': {
const weekIdentifier = getArgValue('--week') || '本周';
const content = getArgValue('--content');
if (!content) {
console.error('错误: 请提供总结内容 (--content "内容")');
process.exit(1);
}
const weekNumber = parseWeekIdentifier(weekIdentifier);
const report = setSummary(weekNumber, content);
console.log(`已在 ${weekNumber} 设置周报总结`);
break;
}
case 'remove-plan': {
const weekIdentifier = getArgValue('--week') || '本周';
const planItemId = getArgValue('--plan-item');
if (!planItemId) {
console.error('错误: 请提供计划项ID (--plan-item)');
process.exit(1);
}
const weekNumber = parseWeekIdentifier(weekIdentifier);
const report = removePlanItem(weekNumber, planItemId);
console.log(`已删除计划项 ${planItemId}`);
console.log(`${report.weekNumber} 剩余 ${report.plan.length} 个计划项`);
break;
}
case 'week-info': {
const date = getArgValue('--date') || getCurrentDateStr();
const info = getWeekInfo(date);
console.log(`日期 ${date} 所在工作周:`);
console.log(` 周编号: ${info.weekNumber}`);
console.log(` 周一: ${info.startDate}`);
console.log(` 周五: ${info.endDate}`);
break;
}
default:
console.log('用法:');
console.log(' node work-weekly-report.js plan --tasks "任务1" "任务2" [--week YYYY-Www] [--priority high|medium|low]');
console.log(' node work-weekly-report.js record --content "内容" [--date YYYY-MM-DD] [--status completed|in-progress|blocked] [--hours N] [--plan-item UUID]');
console.log(' node work-weekly-report.js pending [--week YYYY-Www]');
console.log(' node work-weekly-report.js query [--week YYYY-Www] [--format detail|summary]');
console.log(' node work-weekly-report.js update-status --plan-item UUID --status STATUS [--week YYYY-Www]');
console.log(' node work-weekly-report.js summary --content "总结" [--week YYYY-Www]');
console.log(' node work-weekly-report.js remove-plan --plan-item UUID [--week YYYY-Www]');
console.log(' node work-weekly-report.js week-info [--date YYYY-MM-DD]');
console.log('\n周标识: YYYY-Www, 本周, 上周, 上上周, 下周');
}
} catch (error) {
console.error('错误:', error.message);
process.exit(1);
}
}
// 导出模块
module.exports = {
getCurrentWeek,
getWeekInfo,
planWeek,
addRecord,
getPendingItems,
queryWeek,
updatePlanItemStatus,
setSummary,
removePlanItem,
getWorkdays,
parseWeekIdentifier,
isWorkday
};