@wangjs-jacky/ticktick-cli 0.1.0 → 0.1.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/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/commands/task.ts +6 -0
- package/src/utils/format.ts +13 -5
package/dist/index.js
CHANGED
|
@@ -496,6 +496,10 @@ import pc2 from "picocolors";
|
|
|
496
496
|
// src/utils/format.ts
|
|
497
497
|
function normalizeTickTickDate(dateStr) {
|
|
498
498
|
let result = dateStr;
|
|
499
|
+
result = result.replace(/(T\d{2}:\d{2})(?![.:]|\d)/, "$1:00");
|
|
500
|
+
if (!/[Zz]$|[+\-]\d{2}:?\d{2}$/.test(result)) {
|
|
501
|
+
result += "+0800";
|
|
502
|
+
}
|
|
499
503
|
if (!/T\d{2}:\d{2}:\d{2}\.\d{3}/.test(result)) {
|
|
500
504
|
result = result.replace(/(T\d{2}:\d{2}:\d{2})([+\-Z])/, "$1.000$2");
|
|
501
505
|
}
|
|
@@ -1291,6 +1295,10 @@ async function taskBatchUpdateCommand(jsonFile, options) {
|
|
|
1291
1295
|
p3.outro(pc3.red("JSON \u89E3\u6790\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u683C\u5F0F"));
|
|
1292
1296
|
return;
|
|
1293
1297
|
}
|
|
1298
|
+
for (const task of tasks) {
|
|
1299
|
+
if (task.startDate) task.startDate = normalizeTickTickDate(task.startDate);
|
|
1300
|
+
if (task.dueDate) task.dueDate = normalizeTickTickDate(task.dueDate);
|
|
1301
|
+
}
|
|
1294
1302
|
const s2 = p3.spinner();
|
|
1295
1303
|
s2.start(`\u6B63\u5728\u6279\u91CF\u66F4\u65B0 ${tasks.length} \u4E2A\u4EFB\u52A1...`);
|
|
1296
1304
|
try {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/auth.ts","../src/utils/config.ts","../src/utils/endpoints.ts","../src/api/oauth.ts","../src/utils/server.ts","../src/api/client.ts","../src/commands/project.ts","../src/utils/format.ts","../src/api/resources.ts","../src/commands/task.ts","../src/commands/user.ts"],"sourcesContent":["import { cac } from 'cac';\nimport type { Region } from './types.js';\nimport { loginCommand, logoutCommand, whoamiCommand, configCommand } from './commands/auth.js';\nimport { registerProjectCommands } from './commands/project.js';\nimport { registerTaskCommands } from './commands/task.js';\nimport { registerUserCommands } from './commands/user.js';\n\n// cac v7 不支持空格子命令(如 'task list'),需要将 argv 预处理为连字符格式\nconst SUBCOMMAND_GROUPS = ['task', 'project', 'user'];\nconst argv = process.argv.slice(2);\nif (\n argv.length >= 2 &&\n SUBCOMMAND_GROUPS.includes(argv[0]) &&\n !argv[1].startsWith('-')\n) {\n argv.splice(0, 2, `${argv[0]}-${argv[1]}`);\n}\n\nconst cli = cac('tt');\n\n// 认证命令\ncli.command('login', '登录滴答清单').action(loginCommand);\ncli.command('logout', '登出').action(logoutCommand);\ncli.command('whoami', '查看登录状态').action(whoamiCommand);\ncli\n .command('config', '查看/设置配置')\n .option('--region <region>', '切换区域: cn (国内版) / global (国际版)')\n .action(async (options: { region?: string }) => {\n if (options.region && options.region !== 'cn' && options.region !== 'global') {\n console.error(`无效的区域: ${options.region},请使用 cn 或 global`);\n process.exit(1);\n }\n await configCommand({ region: options.region as Region | undefined });\n });\n\n// 项目命令\nregisterProjectCommands(cli);\n\n// 任务命令\nregisterTaskCommands(cli);\n\n// 用户命令\nregisterUserCommands(cli);\n\ncli.help();\ncli.parse(['', '', ...argv]);\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { Region, OAuthConfig } from '../types.js';\nimport { getOAuth, setOAuth, getToken, clearToken, isTokenValid, getRegion, setRegion } from '../utils/config.js';\nimport { getEndpoints } from '../utils/endpoints.js';\nimport { loginWithBrowser } from '../api/oauth.js';\nimport { apiRequest } from '../api/client.js';\n\nconst REGION_LABELS: Record<Region, string> = {\n cn: '国内版(滴答清单)',\n global: '国际版(TickTick)',\n};\n\n/** 引导用户输入 OAuth 凭证 */\nasync function promptOAuthCredentials(developerUrl: string): Promise<OAuthConfig | undefined> {\n p.log.info(`请访问 ${developerUrl} 获取凭证`);\n p.log.info('Redirect URI 设置为: http://localhost:3000/callback\\n');\n\n const clientId = await p.text({\n message: '请输入 Client ID',\n validate: (v) => (!v ? 'Client ID 不能为空' : undefined),\n });\n if (p.isCancel(clientId)) return undefined;\n\n const clientSecret = await p.text({\n message: '请输入 Client Secret',\n validate: (v) => (!v ? 'Client Secret 不能为空' : undefined),\n });\n if (p.isCancel(clientSecret)) return undefined;\n\n const oauth: OAuthConfig = { clientId, clientSecret };\n setOAuth(oauth);\n p.log.success('凭证已保存');\n return oauth;\n}\n\n/** tt login */\nexport async function loginCommand(): Promise<void> {\n const region = getRegion();\n const endpoints = getEndpoints(region);\n\n p.intro(pc.bgCyan(pc.black(` 滴答清单 CLI 登录 [${REGION_LABELS[region]}] `)));\n\n const token = getToken();\n if (token && isTokenValid()) {\n p.outro(pc.green('已登录,无需重复登录。使用 tt logout 先登出。'));\n return;\n }\n\n let oauth = getOAuth();\n\n // 检测凭证区域不匹配\n if (oauth?.region && oauth.region !== region) {\n p.log.warn(`当前区域为 ${REGION_LABELS[region]},但保存的凭证属于 ${REGION_LABELS[oauth.region]}`);\n p.log.warn('凭证与区域不匹配会导致登录失败\\n');\n const reconfigure = await p.confirm({\n message: `是否为 ${REGION_LABELS[region]} 重新配置凭证?`,\n });\n if (p.isCancel(reconfigure) || !reconfigure) {\n p.outro('已取消');\n return;\n }\n oauth = undefined;\n }\n\n // 旧凭证无区域标记,提示确认后再补充\n if (oauth && !oauth.region) {\n p.log.warn('保存的凭证未标记区域,可能与当前区域不匹配');\n const confirmRegion = await p.confirm({\n message: `这些凭证是否用于 ${REGION_LABELS[region]}?`,\n });\n if (p.isCancel(confirmRegion)) {\n p.outro('已取消');\n return;\n }\n if (confirmRegion) {\n setOAuth(oauth);\n p.log.success(`已将凭证标记为 ${REGION_LABELS[region]}`);\n } else {\n oauth = undefined;\n }\n }\n\n if (!oauth) {\n oauth = await promptOAuthCredentials(endpoints.developerUrl);\n if (!oauth) { p.outro('已取消'); return; }\n }\n\n const s = p.spinner();\n s.start('正在打开浏览器进行授权...');\n\n try {\n await loginWithBrowser(oauth);\n s.stop('授权完成');\n p.outro(pc.green('✔ 登录成功!'));\n } catch (err) {\n s.stop('登录失败');\n const msg = (err as Error).message;\n\n if (msg.includes('invalid_client') || msg.includes('TIMEOUT')) {\n p.log.error(pc.red('登录失败:凭证无效或与区域不匹配'));\n p.log.info(`当前区域:${REGION_LABELS[region]}`);\n p.log.info(`凭证来源:${oauth.region ? REGION_LABELS[oauth.region] : '未知'}\\n`);\n\n const action = await p.select({\n message: '请选择下一步操作',\n options: [\n { value: 'switch', label: `切换到${region === 'cn' ? '国际版' : '国内版'}` },\n { value: 'reconfig', label: '重新输入当前区域的凭证' },\n { value: 'exit', label: '退出' },\n ],\n });\n\n if (p.isCancel(action) || action === 'exit') {\n p.outro('已退出');\n return;\n }\n\n if (action === 'switch') {\n const newRegion: Region = region === 'cn' ? 'global' : 'cn';\n setRegion(newRegion);\n p.log.success(`已切换到 ${REGION_LABELS[newRegion]},请重新运行 tt login`);\n p.outro('区域已切换');\n return;\n }\n\n if (action === 'reconfig') {\n await promptOAuthCredentials(endpoints.developerUrl);\n p.outro('凭证已更新,请重新运行 tt login');\n return;\n }\n }\n\n p.outro(pc.red(`✖ ${msg}`));\n process.exit(1);\n }\n}\n\n/** tt logout */\nexport async function logoutCommand(): Promise<void> {\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 登出 ')));\n clearToken();\n p.outro(pc.green('✔ 已登出'));\n}\n\n/** tt whoami */\nexport async function whoamiCommand(): Promise<void> {\n const region = getRegion();\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 状态 ')));\n\n const token = getToken();\n if (!token) {\n p.outro(pc.yellow('未登录,请先运行 tt login'));\n return;\n }\n\n const s = p.spinner();\n s.start('正在验证登录状态...');\n\n try {\n await apiRequest<unknown[]>('project');\n s.stop('验证完成');\n\n const expiresIn = token.expiresAt - Date.now();\n if (expiresIn <= 0) {\n p.outro(pc.yellow('Token 已失效,请运行 tt login 重新登录'));\n return;\n }\n\n const hours = Math.floor(expiresIn / 3600000);\n const minutes = Math.floor((expiresIn % 3600000) / 60000);\n p.log.success(pc.green(`已登录 [${REGION_LABELS[region]}]`));\n p.log.info(`Token 有效期: 剩余 ${hours} 小时 ${minutes} 分钟`);\n p.outro('一切正常');\n } catch {\n s.stop('验证失败');\n p.outro(pc.red('Token 已失效,请运行 tt login 重新登录'));\n }\n}\n\n/** tt config [--region cn|global] */\nexport async function configCommand(args?: { region?: Region }): Promise<void> {\n if (args?.region) {\n const oldRegion = getRegion();\n setRegion(args.region);\n clearToken();\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 配置 ')));\n p.log.success(`已切换到 ${REGION_LABELS[args.region]}`);\n if (oldRegion !== args.region) {\n p.log.warn('区域已变更,请重新运行 tt login');\n }\n p.outro('配置已更新');\n return;\n }\n\n const region = getRegion();\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 配置 ')));\n p.log.info(`区域: ${REGION_LABELS[region]}`);\n\n const oauth = getOAuth();\n if (oauth) {\n p.log.info(`Client ID: ${oauth.clientId}`);\n p.log.info(`Client Secret: ${oauth.clientSecret.substring(0, 8)}${'*'.repeat(Math.max(0, oauth.clientSecret.length - 8))}`);\n } else {\n p.log.warn('尚未配置 OAuth 凭证');\n }\n\n const token = getToken();\n if (token) {\n p.log.info(`Token: ${token.accessToken.substring(0, 8)}...`);\n p.log.info(`过期时间: ${new Date(token.expiresAt).toLocaleString('zh-CN')}`);\n } else {\n p.log.info('Token: 未登录');\n }\n\n p.log.info('\\n使用 tt config --region cn/global 切换区域');\n p.outro('配置信息如上');\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport type { AppConfig, OAuthConfig, Region, TokenData } from '../types.js';\n\n/** 配置目录,可通过环境变量覆盖(测试用) */\nfunction getConfigDir(): string {\n return process.env.TT_CLI_CONFIG_DIR ?? path.join(os.homedir(), '.tt-cli');\n}\n\nconst CONFIG_FILE = 'config.json';\n\nfunction getConfigPath(): string {\n return path.join(getConfigDir(), CONFIG_FILE);\n}\n\nfunction ensureConfigDir(): void {\n const dir = getConfigDir();\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n}\n\nfunction readConfig(): AppConfig {\n const configPath = getConfigPath();\n if (!fs.existsSync(configPath)) return {};\n return JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n}\n\nfunction writeConfig(config: AppConfig): void {\n ensureConfigDir();\n fs.writeFileSync(getConfigPath(), JSON.stringify(config, null, 2));\n}\n\n/** 读取区域设置,默认国内版 */\nexport function getRegion(): Region {\n return readConfig().region ?? 'cn';\n}\n\n/** 保存区域设置 */\nexport function setRegion(region: Region): void {\n const config = readConfig();\n config.region = region;\n writeConfig(config);\n}\n\n/** 读取 OAuth 凭证 */\nexport function getOAuth(): OAuthConfig | undefined {\n return readConfig().oauth;\n}\n\n/** 保存 OAuth 凭证(同时记录当前区域) */\nexport function setOAuth(oauth: OAuthConfig): void {\n const config = readConfig();\n config.oauth = { ...oauth, region: getRegion() };\n writeConfig(config);\n}\n\n/** 获取凭证所属区域 */\nexport function getOAuthRegion(): Region | undefined {\n return readConfig().oauth?.region;\n}\n\n/** 读取 Token */\nexport function getToken(): TokenData | undefined {\n return readConfig().token;\n}\n\n/** 保存 Token */\nexport function setToken(token: TokenData): void {\n const config = readConfig();\n config.token = token;\n writeConfig(config);\n}\n\n/** 清除 Token(保留 OAuth 凭证) */\nexport function clearToken(): void {\n const config = readConfig();\n delete config.token;\n writeConfig(config);\n}\n\n/** Token 是否有效(未过期且剩余 > 5 分钟) */\nexport function isTokenValid(): boolean {\n const token = getToken();\n if (!token) return false;\n return Date.now() < token.expiresAt - 5 * 60 * 1000;\n}\n","import type { Region, RegionEndpoints } from '../types.js';\n\n/** 区域接口地址映射 */\nconst ENDPOINTS: Record<Region, RegionEndpoints> = {\n cn: {\n authUrl: 'https://dida365.com/oauth/authorize',\n tokenUrl: 'https://dida365.com/oauth/token',\n apiBase: 'https://api.dida365.com/open/v1/',\n developerUrl: 'https://developer.dida365.com/app',\n },\n global: {\n authUrl: 'https://ticktick.com/oauth/authorize',\n tokenUrl: 'https://ticktick.com/oauth/token',\n apiBase: 'https://api.ticktick.com/open/v1/',\n developerUrl: 'https://developer.ticktick.com/app',\n },\n};\n\n/** 获取指定区域的接口地址 */\nexport function getEndpoints(region: Region): RegionEndpoints {\n return ENDPOINTS[region];\n}\n","import crypto from 'crypto';\nimport open from 'open';\nimport type { OAuthConfig, TokenData, TokenResponse } from '../types.js';\nimport { getOAuth, getToken, setToken, getRegion } from '../utils/config.js';\nimport { getEndpoints } from '../utils/endpoints.js';\nimport { createCallbackServer } from '../utils/server.js';\n\nconst SCOPES = 'tasks:read tasks:write';\nconst DEFAULT_PORT = 3000;\n\n/** 生成随机 state(防 CSRF) */\nexport function generateState(): string {\n return crypto.randomBytes(16).toString('hex');\n}\n\n/** 构建授权 URL */\nexport function buildAuthUrl(config: OAuthConfig, state: string, port: number, region: 'cn' | 'global' = 'cn'): string {\n const endpoints = getEndpoints(region);\n const redirectUri = `http://localhost:${port}/callback`;\n const params = new URLSearchParams({\n client_id: config.clientId,\n response_type: 'code',\n redirect_uri: redirectUri,\n scope: SCOPES,\n state,\n });\n return `${endpoints.authUrl}?${params.toString()}`;\n}\n\n/** 用授权码换取 Token */\nexport async function exchangeCode(\n config: OAuthConfig,\n code: string,\n port: number\n): Promise<TokenData> {\n const region = getRegion();\n const endpoints = getEndpoints(region);\n const redirectUri = `http://localhost:${port}/callback`;\n const credentials = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64');\n\n const response = await fetch(endpoints.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Authorization': `Basic ${credentials}`,\n },\n body: new URLSearchParams({\n code,\n grant_type: 'authorization_code',\n redirect_uri: redirectUri,\n scope: SCOPES,\n }).toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Token 交换失败: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n return {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\n/** 刷新 Token */\nexport async function refreshAccessToken(): Promise<TokenData> {\n const oauth = getOAuth();\n const token = getToken();\n const region = getRegion();\n const endpoints = getEndpoints(region);\n\n if (!oauth || !token) {\n throw new Error('未登录,请先运行 tt login');\n }\n\n const credentials = Buffer.from(`${oauth.clientId}:${oauth.clientSecret}`).toString('base64');\n\n const response = await fetch(endpoints.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Authorization': `Basic ${credentials}`,\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: token.refreshToken,\n }).toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Token 刷新失败: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n const newToken: TokenData = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n setToken(newToken);\n return newToken;\n}\n\n/** 完整登录流程 */\nexport async function loginWithBrowser(config: OAuthConfig, port = DEFAULT_PORT): Promise<TokenData> {\n const region = getRegion();\n const state = generateState();\n const authUrl = buildAuthUrl(config, state, port, region);\n\n // 先启动服务器\n const codePromise = createCallbackServer(state, port);\n\n // 再打开浏览器\n await open(authUrl);\n\n // 等待回调(含超时处理)\n let callbackResult: { code: string; close: () => void };\n try {\n callbackResult = await codePromise;\n } catch (err) {\n if ((err as Error).message === 'TIMEOUT') {\n throw new Error(\n '登录超时(2 分钟未收到授权回调)。\\n' +\n '可能原因:\\n' +\n ' 1. 浏览器授权页面显示了错误(如 invalid_client)\\n' +\n ' 2. 凭证与当前区域不匹配\\n' +\n ` 当前区域:${region === 'cn' ? '国内版(dida365.com)' : '国际版(ticktick.com)'}\\n` +\n '建议:检查浏览器页面错误,或尝试切换区域/重新配置凭证'\n );\n }\n throw err;\n }\n\n // 交换 token\n const token = await exchangeCode(config, callbackResult.code, port);\n setToken(token);\n\n // 关闭服务器\n callbackResult.close();\n\n return token;\n}\n","import http from 'http';\n\ninterface CallbackResult {\n code: string;\n close: () => void;\n}\n\n/**\n * 创建临时本地 HTTP 服务器,等待 OAuth2 回调\n * 返回 Promise,在收到合法回调时 resolve,超时 2 分钟后 reject\n */\nexport function createCallbackServer(\n expectedState: string,\n port: number\n): Promise<CallbackResult> {\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url!, `http://localhost:${port}`);\n\n if (url.pathname !== '/callback') {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n const code = url.searchParams.get('code');\n const state = url.searchParams.get('state');\n\n if (state !== expectedState) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end('<h1>授权失败:state 不匹配</h1>');\n if (!settled) { settled = true; reject(new Error('CSRF state 不匹配')); }\n server.close();\n return;\n }\n\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end('<h1>授权失败:缺少 code 参数</h1>');\n if (!settled) { settled = true; reject(new Error('缺少授权码')); }\n server.close();\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end('<html><body style=\"display:flex;justify-content:center;align-items:center;height:100vh;font-family:sans-serif\"><h1>✅ 授权成功!请返回终端。</h1></body></html>');\n\n if (!settled) {\n settled = true;\n resolve({\n code,\n close: () => server.close(),\n });\n }\n });\n\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (!settled) {\n settled = true;\n if (err.code === 'EADDRINUSE') {\n reject(new Error(`端口 ${port} 已被占用,请关闭占用该端口的程序或等待重试`));\n } else {\n reject(err);\n }\n }\n });\n\n server.listen(port);\n\n // 2 分钟超时\n setTimeout(() => {\n if (!settled) {\n settled = true;\n server.close();\n reject(new Error('TIMEOUT'));\n }\n }, 120_000);\n });\n}\n","import { getOAuth, getToken, isTokenValid, getRegion } from '../utils/config.js';\nimport { getEndpoints } from '../utils/endpoints.js';\nimport { refreshAccessToken } from './oauth.js';\n\n/** 获取有效的 access token(自动刷新) */\nasync function getValidToken(): Promise<string> {\n const oauth = getOAuth();\n const token = getToken();\n\n if (!oauth || !token) {\n throw new Error('未登录,请先运行 tt login');\n }\n\n if (isTokenValid()) {\n return token.accessToken;\n }\n\n const newToken = await refreshAccessToken();\n return newToken.accessToken;\n}\n\n/** 发送 API 请求 */\nexport async function apiRequest<T>(path: string, options?: RequestInit): Promise<T> {\n const token = await getValidToken();\n const endpoints = getEndpoints(getRegion());\n\n const response = await fetch(`${endpoints.apiBase}${path}`, {\n ...options,\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`API 请求失败: ${response.status} ${text}`);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n // 读取响应文本,处理空 body(TickTick 部分 API 返回 200 + 空 body)\n const text = await response.text();\n if (!text || text.trim() === '') {\n return undefined as T;\n }\n\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new Error(\n `API 响应 JSON 解析失败 (HTTP ${response.status})\\n` +\n `路径: ${path}\\n` +\n `原始响应: ${text.substring(0, 500)}\\n` +\n `建议: 请检查 API 端点是否正确,或尝试 tt task-search 验证数据`\n );\n }\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { Task, CreateProjectParams, UpdateProjectParams } from '../types.js';\nimport { formatTaskTime } from '../utils/format.js';\nimport {\n getProjects,\n getProject,\n getProjectData,\n createProject,\n updateProject,\n deleteProject,\n} from '../api/resources.js';\n\n// ─── 格式化工具 ──────────────────────────────────────\n\nconst PRIORITY_LABEL: Record<number, string> = {\n 0: '无',\n 1: '低',\n 3: '中',\n 5: '高',\n};\n\nfunction priorityText(priority?: number): string {\n const v = priority ?? 0;\n switch (v) {\n case 5:\n return pc.red('高');\n case 3:\n return pc.yellow('中');\n case 1:\n return pc.blue('低');\n default:\n return pc.dim('无');\n }\n}\n\nfunction statusIcon(status?: number): string {\n return status === 2 ? pc.green('✓') : '○';\n}\n\nfunction displayTaskList(tasks: Task[]): void {\n if (tasks.length === 0) {\n p.log.info(pc.dim(' (无任务)'));\n return;\n }\n\n for (const task of tasks) {\n const icon = statusIcon(task.status);\n const title =\n task.title.length > 30\n ? task.title.slice(0, 30) + '…'\n : task.title;\n const time = formatTaskTime(task);\n const timeStr = time ? pc.cyan(time) : '';\n console.log(\n ` ${icon} ${title} ${timeStr} ${priorityText(task.priority)}`\n );\n if (task.content) {\n const content =\n task.content.length > 50\n ? task.content.slice(0, 50) + '…'\n : task.content;\n console.log(` ${pc.dim(content)}`);\n }\n }\n}\n\n// ─── 命令实现 ────────────────────────────────────────\n\nasync function projectListCommand(): Promise<void> {\n const s = p.spinner();\n s.start('正在获取项目列表...');\n\n try {\n const projects = await getProjects();\n s.stop(`找到 ${projects.length} 个项目`);\n\n if (projects.length === 0) {\n p.outro(pc.yellow('没有找到任何项目'));\n return;\n }\n\n console.log('');\n for (const project of projects) {\n const status = project.closed ? pc.dim('已关闭') : pc.green('活跃');\n console.log(\n ` ${pc.bold(project.name)} ${pc.dim(project.id)}`\n );\n console.log(\n ` 类型: ${project.kind || '-'} 视图: ${project.viewMode || '-'} ${status}`\n );\n }\n console.log('');\n p.outro(`共 ${projects.length} 个项目`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectGetCommand(id: string): Promise<void> {\n const s = p.spinner();\n s.start('正在获取项目详情...');\n\n try {\n const project = await getProject(id);\n s.stop('获取成功');\n\n console.log('');\n console.log(` ${pc.bold('名称')}: ${project.name}`);\n console.log(` ${pc.bold('ID')}: ${project.id}`);\n console.log(` ${pc.bold('颜色')}: ${project.color || '-'}`);\n console.log(` ${pc.bold('类型')}: ${project.kind || '-'}`);\n console.log(` ${pc.bold('视图')}: ${project.viewMode || '-'}`);\n console.log(\n ` ${pc.bold('状态')}: ${project.closed ? '已关闭' : '活跃'}`\n );\n if (project.groupId)\n console.log(` ${pc.bold('分组')}: ${project.groupId}`);\n if (project.permission)\n console.log(` ${pc.bold('权限')}: ${project.permission}`);\n console.log('');\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectTasksCommand(\n id: string,\n options: { json?: boolean }\n): Promise<void> {\n try {\n const data = await getProjectData(id);\n\n if (options.json) {\n console.log(JSON.stringify(data.tasks, null, 2));\n return;\n }\n\n const s = p.spinner();\n s.start('正在获取项目任务...');\n s.stop(\n `项目「${data.project.name}」下有 ${data.tasks.length} 个任务`\n );\n\n if (data.tasks.length === 0) {\n p.outro(pc.yellow('该项目下没有任务'));\n return;\n }\n\n console.log('');\n displayTaskList(data.tasks);\n console.log('');\n p.outro(`共 ${data.tasks.length} 个任务`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectCreateCommand(\n name: string | undefined,\n options: {\n color?: string;\n viewMode?: string;\n kind?: string;\n }\n): Promise<void> {\n if (!name) {\n const input = await p.text({ message: '请输入项目名称' });\n if (p.isCancel(input)) {\n p.outro('已取消');\n return;\n }\n name = input;\n }\n\n const params: CreateProjectParams = { name };\n if (options.color) params.color = options.color;\n if (options.viewMode)\n params.viewMode = options.viewMode as CreateProjectParams['viewMode'];\n if (options.kind)\n params.kind = options.kind as CreateProjectParams['kind'];\n\n const s = p.spinner();\n s.start('正在创建项目...');\n\n try {\n const project = await createProject(params);\n s.stop('创建成功');\n p.outro(\n pc.green(`项目「${project.name}」已创建 (ID: ${project.id})`)\n );\n } catch (err) {\n s.stop('创建失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectUpdateCommand(\n id: string,\n options: {\n name?: string;\n color?: string;\n viewMode?: string;\n kind?: string;\n }\n): Promise<void> {\n const params: UpdateProjectParams = {};\n if (options.name) params.name = options.name;\n if (options.color) params.color = options.color;\n if (options.viewMode)\n params.viewMode = options.viewMode as UpdateProjectParams['viewMode'];\n if (options.kind)\n params.kind = options.kind as UpdateProjectParams['kind'];\n\n if (Object.keys(params).length === 0) {\n p.outro(\n pc.yellow(\n '未指定任何更新内容,使用 --name / --color / --view-mode / --kind 选项'\n )\n );\n return;\n }\n\n const s = p.spinner();\n s.start('正在更新项目...');\n\n try {\n const project = await updateProject(id, params);\n s.stop('更新成功');\n p.outro(pc.green(`项目「${project.name}」已更新`));\n } catch (err) {\n s.stop('更新失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectDeleteCommand(id: string): Promise<void> {\n const confirmed = await p.confirm({\n message: `确认删除项目 ${pc.red(id)}?此操作不可撤销`,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.outro('已取消');\n return;\n }\n\n const s = p.spinner();\n s.start('正在删除项目...');\n\n try {\n await deleteProject(id);\n s.stop('删除成功');\n p.outro(pc.green('项目已删除'));\n } catch (err) {\n s.stop('删除失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\n// ─── 注册命令 ────────────────────────────────────────\n\nexport function registerProjectCommands(cli: {\n command: (name: string, desc: string) => {\n option: (flag: string, desc: string) => {\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n}): void {\n cli\n .command('project-list', '列出所有项目')\n .action(projectListCommand);\n\n cli\n .command('project-get <id>', '获取项目详情')\n .action(projectGetCommand);\n\n cli\n .command('project-tasks <id>', '获取项目下的任务')\n .option('--json', '输出 JSON 格式')\n .action(projectTasksCommand);\n\n cli\n .command('project-create [name]', '创建项目')\n .option('--color <color>', '项目颜色,如 #F18181')\n .option('--view-mode <mode>', '视图模式: list / kanban / timeline')\n .option('--kind <kind>', '项目类型: TASK / NOTE')\n .action(projectCreateCommand);\n\n cli\n .command('project-update <id>', '更新项目')\n .option('--name <name>', '项目名称')\n .option('--color <color>', '项目颜色')\n .option('--view-mode <mode>', '视图模式')\n .option('--kind <kind>', '项目类型')\n .action(projectUpdateCommand);\n\n cli\n .command('project-delete <id>', '删除项目')\n .action(projectDeleteCommand);\n}\n","/**\n * 任务时间格式化工具\n */\n\n/**\n * 规范化日期字符串为 TickTick API 要求的格式\n * TickTick API 要求: \"2026-04-04T19:00:00.000+0800\"(有毫秒,时区无冒号)\n *\n * 支持输入格式:\n * - \"2026-04-04T19:00:00+08:00\" → \"2026-04-04T19:00:00.000+0800\"\n * - \"2026-04-04T19:00:00Z\" → \"2026-04-04T19:00:00.000+0000\"\n * - \"2026-04-04T19:00:00.123+0800\" → 保持不变\n */\nexport function normalizeTickTickDate(dateStr: string): string {\n let result = dateStr;\n // 补毫秒: \"T19:00:00+\" → \"T19:00:00.000+\"\n if (!/T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}/.test(result)) {\n result = result.replace(/(T\\d{2}:\\d{2}:\\d{2})([+\\-Z])/, '$1.000$2');\n }\n // 去时区冒号: \"+08:00\" → \"+0800\"\n result = result.replace(/([+\\-])(\\d{2}):(\\d{2})$/, '$1$2$3');\n // \"Z\" → \"+0000\"\n if (result.endsWith('Z')) {\n result = result.slice(0, -1) + '+0000';\n }\n return result;\n}\n\n/** 从 TickTick ISO 8601 日期字符串提取本地时间的 HH:mm */\nfunction extractHM(dateStr: string): string | null {\n // TickTick 返回格式如 \"2026-04-04T14:15:00+0000\" 或 \"2026-04-04T14:15:00+08:00\"\n // API 返回 UTC 时间,需转换为本地时间显示\n try {\n const d = new Date(dateStr);\n if (isNaN(d.getTime())) return null;\n const hours = d.getHours().toString().padStart(2, '0');\n const minutes = d.getMinutes().toString().padStart(2, '0');\n return `${hours}:${minutes}`;\n } catch {\n // 回退:直接从字符串提取 HH:mm\n const match = dateStr.match(/T(\\d{2}):(\\d{2})/);\n if (!match) return null;\n return `${match[1]}:${match[2]}`;\n }\n}\n\n/**\n * 格式化任务时间范围,用于表格显示\n * - 全天任务显示 \"全天\"\n * - 有起止时间显示 \"HH:mm-HH:mm\"\n * - 仅有开始时间显示 \"HH:mm\"\n * - 无时间显示空字符串\n */\nexport function formatTaskTime(task: {\n startDate?: string;\n dueDate?: string;\n isAllDay?: boolean;\n}): string {\n if (task.isAllDay && task.startDate) return '全天';\n if (!task.startDate) return '';\n\n const start = extractHM(task.startDate);\n if (!start) return '';\n\n if (task.dueDate) {\n const end = extractHM(task.dueDate);\n if (end && end !== start) return `${start}-${end}`;\n }\n\n return start;\n}\n","import { apiRequest } from './client.js';\nimport type {\n Project,\n ProjectData,\n Task,\n CreateProjectParams,\n UpdateProjectParams,\n CreateTaskParams,\n UpdateTaskParams,\n MoveTaskParams,\n CompletedTasksParams,\n FilterTasksParams,\n BatchTasksParams,\n UserPreference,\n UndoneTasksParams,\n} from '../types.js';\n\n// ─── Project API ─────────────────────────────────────\n\n/** 获取所有项目 */\nexport function getProjects(): Promise<Project[]> {\n return apiRequest<Project[]>('project');\n}\n\n/** 获取单个项目 */\nexport function getProject(projectId: string): Promise<Project> {\n return apiRequest<Project>(`project/${projectId}`);\n}\n\n/** 获取项目及任务数据 */\nexport function getProjectData(projectId: string): Promise<ProjectData> {\n return apiRequest<ProjectData>(`project/${projectId}/data`);\n}\n\n/** 创建项目 */\nexport function createProject(data: CreateProjectParams): Promise<Project> {\n return apiRequest<Project>('project', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 更新项目 */\nexport function updateProject(\n projectId: string,\n data: UpdateProjectParams\n): Promise<Project> {\n return apiRequest<Project>(`project/${projectId}`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 删除项目 */\nexport function deleteProject(projectId: string): Promise<void> {\n return apiRequest<void>(`project/${projectId}`, { method: 'DELETE' });\n}\n\n// ─── Task API ────────────────────────────────────────\n\n/** 获取任务 */\nexport function getTask(projectId: string, taskId: string): Promise<Task> {\n return apiRequest<Task>(`project/${projectId}/task/${taskId}`);\n}\n\n/** 创建任务 */\nexport function createTask(data: CreateTaskParams): Promise<Task> {\n return apiRequest<Task>('task', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 更新任务 */\nexport function updateTask(\n taskId: string,\n data: UpdateTaskParams\n): Promise<Task> {\n return apiRequest<Task>(`task/${taskId}`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 完成任务 */\nexport function completeTask(\n projectId: string,\n taskId: string\n): Promise<void> {\n return apiRequest<void>(`project/${projectId}/task/${taskId}/complete`, {\n method: 'POST',\n });\n}\n\n/** 删除任务 */\nexport function deleteTask(\n projectId: string,\n taskId: string\n): Promise<void> {\n return apiRequest<void>(`project/${projectId}/task/${taskId}`, {\n method: 'DELETE',\n });\n}\n\n/** 移动任务 */\nexport function moveTasks(\n moves: MoveTaskParams[]\n): Promise<Array<{ id: string; etag: string }>> {\n return apiRequest<Array<{ id: string; etag: string }>>('task/move', {\n method: 'POST',\n body: JSON.stringify(moves),\n });\n}\n\n/** 获取已完成任务 */\nexport function getCompletedTasks(\n params: CompletedTasksParams\n): Promise<Task[]> {\n return apiRequest<Task[]>('task/completed', {\n method: 'POST',\n body: JSON.stringify(params),\n });\n}\n\n/** 筛选任务 */\nexport function filterTasks(params: FilterTasksParams): Promise<Task[]> {\n return apiRequest<Task[]>('task/filter', {\n method: 'POST',\n body: JSON.stringify(params),\n });\n}\n\n// ─── 批量操作 ──────────────────────────────────────\n\n/** 批量添加任务(API 返回 { id2etag: {...} },不是 Task[]) */\nexport async function batchAddTasks(\n tasks: CreateTaskParams[]\n): Promise<{ count: number; id2etag?: Record<string, string> }> {\n const res = await apiRequest<Record<string, unknown>>('task/batch', {\n method: 'POST',\n body: JSON.stringify({ add: tasks }),\n });\n return {\n count: tasks.length,\n id2etag: (res?.id2etag ?? res) as Record<string, string> | undefined,\n };\n}\n\n/** 批量更新任务 */\nexport function batchUpdateTasks(\n tasks: UpdateTaskParams[]\n): Promise<void> {\n return apiRequest<void>('task/batch', {\n method: 'POST',\n body: JSON.stringify({ update: tasks }),\n });\n}\n\n/** 批量完成项目内任务 */\nexport async function completeTasksInProject(\n projectId: string,\n taskIds: string[]\n): Promise<{ completed: string[]; failed: string[] }> {\n const completed: string[] = [];\n const failed: string[] = [];\n for (const taskId of taskIds) {\n try {\n await completeTask(projectId, taskId);\n completed.push(taskId);\n } catch {\n failed.push(taskId);\n }\n }\n return { completed, failed };\n}\n\n// ─── 查询 ──────────────────────────────────────────\n\n/** 按 ID 查找任务(无需 projectId,同时搜索未完成和已完成任务) */\nexport async function getTaskById(taskId: string): Promise<Task> {\n // 并行获取未完成任务和已完成任务,确保覆盖所有任务\n // 注意:filterTasks API 有返回数量限制,改用 listUndoneTasksByDate 获取更完整的数据\n const [undoneTasks, completedTasks] = await Promise.all([\n listUndoneTasksByDate({}),\n getCompletedTasks({}),\n ]);\n const allTasks = [...undoneTasks, ...completedTasks];\n const task = allTasks.find((t) => t.id === taskId);\n if (!task) throw new Error(`任务 ${taskId} 不存在`);\n return task;\n}\n\n/** 获取用户偏好 */\nexport function getUserPreference(): Promise<UserPreference> {\n return apiRequest<UserPreference>('user/info');\n}\n\n/** 按日期范围获取未完成任务 */\nexport function listUndoneTasksByDate(\n params: UndoneTasksParams\n): Promise<Task[]> {\n const filterParams: FilterTasksParams = { status: [0] };\n if (params.projectIds) filterParams.projectIds = params.projectIds;\n if (params.startDate) filterParams.startDate = params.startDate;\n if (params.endDate) filterParams.endDate = params.endDate;\n return filterTasks(filterParams);\n}\n\n/** 按预设查询获取未完成任务 */\nexport function listUndoneTasksByTimeQuery(\n query: string\n): Promise<Task[]> {\n const now = new Date();\n let startDate: string;\n let endDate: string;\n\n const toISO = (d: Date) => d.toISOString();\n\n switch (query) {\n case 'today': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const end = new Date(start);\n end.setDate(end.getDate() + 1);\n startDate = toISO(start);\n endDate = toISO(end);\n break;\n }\n case 'tomorrow': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);\n const end = new Date(start);\n end.setDate(end.getDate() + 1);\n startDate = toISO(start);\n endDate = toISO(end);\n break;\n }\n case 'last24hour': {\n const start = new Date(now.getTime() - 24 * 60 * 60 * 1000);\n startDate = toISO(start);\n endDate = toISO(now);\n break;\n }\n case 'next24hour': {\n const end = new Date(now.getTime() + 24 * 60 * 60 * 1000);\n startDate = toISO(now);\n endDate = toISO(end);\n break;\n }\n case 'last7day': {\n const start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n startDate = toISO(start);\n endDate = toISO(now);\n break;\n }\n case 'next7day': {\n const end = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);\n startDate = toISO(now);\n endDate = toISO(end);\n break;\n }\n default:\n throw new Error(\n `不支持的查询预设: ${query},支持: today, tomorrow, last24hour, next24hour, last7day, next7day`\n );\n }\n\n return listUndoneTasksByDate({ startDate, endDate });\n}\n\n/** 搜索任务(关键词匹配,同时搜索未完成和已完成任务) */\nexport async function searchTask(keyword: string): Promise<Task[]> {\n // 并行获取未完成任务和已完成任务,确保覆盖所有任务\n // 注意:filterTasks API 有返回数量限制,改用 listUndoneTasksByDate 获取更完整的数据\n const [undoneTasks, completedTasks] = await Promise.all([\n listUndoneTasksByDate({}),\n getCompletedTasks({}),\n ]);\n\n // 合并并去重(按 id)\n const taskMap = new Map<string, Task>();\n for (const t of [...undoneTasks, ...completedTasks]) {\n taskMap.set(t.id, t);\n }\n const allTasks = Array.from(taskMap.values());\n\n const lower = keyword.toLowerCase();\n return allTasks.filter(\n (t) =>\n t.title.toLowerCase().includes(lower) ||\n (t.content && t.content.toLowerCase().includes(lower))\n );\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type {\n Project,\n Task,\n CreateTaskParams,\n UpdateTaskParams,\n} from '../types.js';\nimport { formatTaskTime, normalizeTickTickDate } from '../utils/format.js';\nimport {\n getProjects,\n getTask,\n createTask,\n updateTask,\n completeTask,\n deleteTask,\n moveTasks,\n getCompletedTasks,\n filterTasks,\n batchAddTasks,\n batchUpdateTasks,\n completeTasksInProject,\n getTaskById,\n listUndoneTasksByDate,\n listUndoneTasksByTimeQuery,\n searchTask,\n} from '../api/resources.js';\n\n// ─── 格式化工具 ──────────────────────────────────────\n\nfunction priorityText(priority?: number): string {\n const v = priority ?? 0;\n switch (v) {\n case 5:\n return pc.red('高');\n case 3:\n return pc.yellow('中');\n case 1:\n return pc.blue('低');\n default:\n return pc.dim('无');\n }\n}\n\nfunction statusIcon(status?: number): string {\n return status === 2 ? pc.green('✓') : '○';\n}\n\nfunction displayTaskDetail(task: Task): void {\n console.log('');\n console.log(` ${pc.bold(task.title)}`);\n console.log(` ${pc.dim('─'.repeat(40))}`);\n console.log(` ID: ${task.id}`);\n console.log(` 项目: ${task.projectId}`);\n console.log(` 优先级: ${priorityText(task.priority)}`);\n console.log(` 状态: ${task.status === 2 ? pc.green('已完成') : '待办'}`);\n if (task.isAllDay !== undefined)\n console.log(` 全天: ${task.isAllDay ? '是' : '否'}`);\n if (task.startDate)\n console.log(` 开始: ${task.startDate}`);\n if (task.dueDate)\n console.log(` 截止: ${task.dueDate}`);\n if (task.timeZone)\n console.log(` 时区: ${task.timeZone}`);\n if (task.kind)\n console.log(` 类型: ${task.kind}`);\n if (task.content) {\n console.log(` 内容:`);\n console.log(` ${task.content}`);\n }\n if (task.tags && task.tags.length > 0) {\n console.log(` 标签: ${task.tags.join(', ')}`);\n }\n if (task.items && task.items.length > 0) {\n console.log(` 子任务:`);\n for (const item of task.items) {\n const icon = item.status === 1 ? pc.green('✓') : '○';\n console.log(` ${icon} ${item.title}`);\n }\n }\n console.log('');\n}\n\nfunction displayTaskTable(tasks: Task[]): void {\n if (tasks.length === 0) {\n p.log.info(pc.dim(' (无任务)'));\n return;\n }\n\n for (const task of tasks) {\n const icon = statusIcon(task.status);\n const title =\n task.title.length > 30\n ? task.title.slice(0, 30) + '…'\n : task.title;\n const time = formatTaskTime(task);\n const timeStr = time ? pc.cyan(time) : '';\n console.log(\n ` ${icon} ${title} ${timeStr} ${pc.dim(task.id)} ${priorityText(task.priority)} ${pc.dim(task.projectId)}`\n );\n }\n}\n\n/** 交互式选择项目 */\nasync function selectProject(): Promise<string | undefined> {\n const s = p.spinner();\n s.start('正在获取项目列表...');\n const projects = await getProjects();\n s.stop('');\n\n if (projects.length === 0) {\n p.log.error('没有可用的项目,请先创建项目');\n return undefined;\n }\n\n const selected = await p.select({\n message: '选择项目',\n options: projects.map((proj: Project) => ({\n value: proj.id,\n label: proj.name,\n })),\n });\n\n if (p.isCancel(selected)) return undefined;\n return selected as string;\n}\n\n/** 解析优先级字符串 */\nfunction parsePriority(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const n = parseInt(value, 10);\n if ([0, 1, 3, 5].includes(n)) return n;\n return undefined;\n}\n\n// ─── 命令实现 ────────────────────────────────────────\n\nasync function taskAddCommand(\n title: string | undefined,\n options: {\n project?: string;\n content?: string;\n priority?: string;\n startDate?: string;\n dueDate?: string;\n allDay?: boolean;\n }\n): Promise<void> {\n if (!title) {\n const input = await p.text({ message: '请输入任务标题' });\n if (p.isCancel(input)) {\n p.outro('已取消');\n return;\n }\n title = input;\n }\n\n let projectId = options.project;\n if (!projectId) {\n projectId = await selectProject();\n if (!projectId) {\n p.outro('已取消');\n return;\n }\n }\n\n const params: CreateTaskParams = { title, projectId };\n if (options.content) params.content = options.content;\n if (options.priority) {\n const priority = parsePriority(options.priority);\n if (priority !== undefined) params.priority = priority;\n }\n if (options.startDate) params.startDate = normalizeTickTickDate(options.startDate);\n if (options.dueDate) params.dueDate = normalizeTickTickDate(options.dueDate);\n if (options.allDay !== undefined) params.isAllDay = options.allDay;\n\n const s = p.spinner();\n s.start('正在创建任务...');\n\n try {\n const task = await createTask(params);\n s.stop('创建成功');\n p.outro(pc.green(`任务「${task.title}」已创建 (ID: ${task.id})`));\n } catch (err) {\n s.stop('创建失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskGetCommand(\n projectId: string,\n taskId: string\n): Promise<void> {\n const s = p.spinner();\n s.start('正在获取任务...');\n\n try {\n const task = await getTask(projectId, taskId);\n s.stop('获取成功');\n displayTaskDetail(task);\n p.outro('任务详情如上');\n } catch (err) {\n s.stop('获取失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`获取任务失败 (projectId: ${projectId}, taskId: ${taskId})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-find <taskId> 或 tt task-search <关键词> 验证任务')\n );\n }\n}\n\nasync function taskDoneCommand(\n projectId: string,\n taskId: string\n): Promise<void> {\n const s = p.spinner();\n s.start('正在完成任务...');\n\n try {\n await completeTask(projectId, taskId);\n s.stop('完成成功');\n p.outro(pc.green('任务已完成'));\n } catch (err) {\n s.stop('操作失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`任务完成失败 (projectId: ${projectId}, taskId: ${taskId})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-search 检查任务是否存在或已完成')\n );\n }\n}\n\nasync function taskDeleteCommand(\n projectId: string,\n taskId: string\n): Promise<void> {\n const confirmed = await p.confirm({\n message: `确认删除任务 ${pc.red(taskId)}?`,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.outro('已取消');\n return;\n }\n\n const s = p.spinner();\n s.start('正在删除任务...');\n\n try {\n await deleteTask(projectId, taskId);\n s.stop('删除成功');\n p.outro(pc.green('任务已删除'));\n } catch (err) {\n s.stop('删除失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`删除任务失败 (projectId: ${projectId}, taskId: ${taskId})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-get <projectId> <taskId> 验证任务是否存在')\n );\n }\n}\n\nasync function taskUpdateCommand(\n taskId: string,\n options: {\n project?: string;\n title?: string;\n content?: string;\n priority?: string;\n startDate?: string;\n dueDate?: string;\n }\n): Promise<void> {\n if (!options.project) {\n p.outro(pc.red('请使用 -p/--project 指定项目 ID'));\n return;\n }\n\n const params: UpdateTaskParams = {\n id: taskId,\n projectId: options.project,\n };\n if (options.title) params.title = options.title;\n if (options.content) params.content = options.content;\n if (options.priority) {\n const priority = parsePriority(options.priority);\n if (priority !== undefined) params.priority = priority;\n }\n if (options.startDate) params.startDate = normalizeTickTickDate(options.startDate);\n if (options.dueDate) params.dueDate = normalizeTickTickDate(options.dueDate);\n\n const s = p.spinner();\n s.start('正在更新任务...');\n\n try {\n const task = await updateTask(taskId, params);\n s.stop('更新成功');\n p.outro(pc.green(`任务「${task.title}」已更新`));\n } catch (err) {\n s.stop('更新失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`更新任务失败 (taskId: ${taskId}, projectId: ${options.project})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-find <taskId> 验证任务是否存在')\n );\n }\n}\n\nasync function taskMoveCommand(\n taskId: string,\n options: {\n from?: string;\n to?: string;\n }\n): Promise<void> {\n if (!options.from || !options.to) {\n p.outro(\n pc.red('请使用 -f/--from 和 -t/--to 指定源和目标项目 ID')\n );\n return;\n }\n\n const s = p.spinner();\n s.start('正在移动任务...');\n\n try {\n const result = await moveTasks([\n {\n fromProjectId: options.from,\n toProjectId: options.to,\n taskId,\n },\n ]);\n s.stop('移动成功');\n p.outro(\n pc.green(\n `任务已移动 (etag: ${result[0]?.etag ?? '-'})`\n )\n );\n } catch (err) {\n s.stop('移动失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`移动任务失败 (taskId: ${taskId}, from: ${options.from}, to: ${options.to})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt project-list 验证项目 ID 是否有效')\n );\n }\n}\n\nasync function taskCompletedCommand(options: {\n project?: string;\n start?: string;\n end?: string;\n}): Promise<void> {\n const params: {\n projectIds?: string[];\n startDate?: string;\n endDate?: string;\n } = {};\n\n if (options.project) params.projectIds = [options.project];\n if (options.start) params.startDate = options.start;\n if (options.end) params.endDate = options.end;\n\n const s = p.spinner();\n s.start('正在获取已完成任务...');\n\n try {\n const tasks = await getCompletedTasks(params);\n s.stop(`找到 ${tasks.length} 个已完成任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow('没有找到已完成的任务'));\n return;\n }\n\n console.log('');\n displayTaskTable(tasks);\n console.log('');\n p.outro(`共 ${tasks.length} 个已完成任务`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskListCommand(options: {\n project?: string;\n start?: string;\n end?: string;\n status?: string;\n priority?: string;\n tag?: string;\n json?: boolean;\n}): Promise<void> {\n const params: {\n projectIds?: string[];\n startDate?: string;\n endDate?: string;\n status?: number[];\n priority?: number[];\n tag?: string[];\n } = {};\n\n if (options.project) params.projectIds = [options.project];\n if (options.start) params.startDate = options.start;\n if (options.end) params.endDate = options.end;\n if (options.status) {\n params.status = options.status.split(',').map((s) => parseInt(s, 10));\n }\n if (options.priority) {\n params.priority = options.priority\n .split(',')\n .map((s) => parseInt(s, 10));\n }\n if (options.tag) {\n params.tag = options.tag.split(',');\n }\n\n try {\n const tasks = await filterTasks(params);\n\n if (options.json) {\n console.log(JSON.stringify(tasks, null, 2));\n return;\n }\n\n const s = p.spinner();\n s.start('正在筛选任务...');\n s.stop(`找到 ${tasks.length} 个任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow('没有找到匹配的任务'));\n return;\n }\n\n console.log('');\n displayTaskTable(tasks);\n console.log('');\n p.outro(`共 ${tasks.length} 个任务`);\n } catch (err) {\n p.outro(pc.red((err as Error).message));\n }\n}\n\n// ─── 批量 / 高级命令 ────────────────────────────────\n\nasync function taskBatchAddCommand(\n jsonFile: string | undefined,\n options: { stdin?: boolean }\n): Promise<void> {\n let jsonStr: string;\n\n if (options.stdin || !jsonFile) {\n // 从 stdin 读取\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n jsonStr = Buffer.concat(chunks).toString('utf-8');\n } else {\n // 从文件读取\n const fs = await import('fs/promises');\n jsonStr = await fs.readFile(jsonFile, 'utf-8');\n }\n\n let tasks: CreateTaskParams[];\n try {\n tasks = JSON.parse(jsonStr);\n if (!Array.isArray(tasks)) {\n p.outro(pc.red('JSON 必须是任务数组'));\n return;\n }\n } catch {\n p.outro(pc.red('JSON 解析失败,请检查格式'));\n return;\n }\n\n // 规范化日期格式\n for (const task of tasks) {\n if (task.startDate) task.startDate = normalizeTickTickDate(task.startDate);\n if (task.dueDate) task.dueDate = normalizeTickTickDate(task.dueDate);\n }\n\n const s = p.spinner();\n s.start(`正在批量创建 ${tasks.length} 个任务...`);\n\n try {\n const result = await batchAddTasks(tasks);\n s.stop(`成功创建 ${result.count} 个任务`);\n console.log('');\n for (const task of tasks) {\n console.log(` ${pc.green('✓')} ${task.title}`);\n }\n console.log('');\n p.outro(`共创建 ${result.count} 个任务`);\n } catch (err) {\n s.stop('批量创建失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskBatchUpdateCommand(\n jsonFile: string | undefined,\n options: { stdin?: boolean }\n): Promise<void> {\n let jsonStr: string;\n\n if (options.stdin || !jsonFile) {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n jsonStr = Buffer.concat(chunks).toString('utf-8');\n } else {\n const fs = await import('fs/promises');\n jsonStr = await fs.readFile(jsonFile, 'utf-8');\n }\n\n let tasks: UpdateTaskParams[];\n try {\n tasks = JSON.parse(jsonStr);\n if (!Array.isArray(tasks)) {\n p.outro(pc.red('JSON 必须是任务数组'));\n return;\n }\n } catch {\n p.outro(pc.red('JSON 解析失败,请检查格式'));\n return;\n }\n\n const s = p.spinner();\n s.start(`正在批量更新 ${tasks.length} 个任务...`);\n\n try {\n await batchUpdateTasks(tasks);\n s.stop(`成功更新 ${tasks.length} 个任务`);\n p.outro(pc.green(`已更新 ${tasks.length} 个任务`));\n } catch (err) {\n s.stop('批量更新失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskBatchDoneCommand(\n projectId: string,\n options: {\n taskIds?: string;\n all?: boolean;\n force?: boolean;\n }\n): Promise<void> {\n let ids: string[];\n\n if (options.all) {\n // 获取项目下所有未完成任务\n const s = p.spinner();\n s.start('正在获取项目任务...');\n const tasks = await filterTasks({ projectIds: [projectId], status: [0] });\n s.stop(`找到 ${tasks.length} 个未完成任务`);\n ids = tasks.map((t) => t.id);\n } else if (options.taskIds) {\n ids = options.taskIds.split(',').map((s) => s.trim());\n } else {\n p.outro(pc.red('请使用 --task-ids <id1,id2,...> 或 --all'));\n return;\n }\n\n if (ids.length === 0) {\n p.outro(pc.yellow('没有需要完成的任务'));\n return;\n }\n\n // 确认\n if (!options.force) {\n console.log('');\n console.log(` 将完成 ${ids.length} 个任务:`);\n for (const id of ids) {\n console.log(` ${pc.dim(id)}`);\n }\n console.log('');\n const confirmed = await p.confirm({\n message: `确认完成这 ${ids.length} 个任务?`,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.outro('已取消');\n return;\n }\n }\n\n const s = p.spinner();\n s.start(`正在完成 ${ids.length} 个任务...`);\n\n try {\n const result = await completeTasksInProject(projectId, ids);\n s.stop('操作完成');\n p.outro(\n pc.green(`成功 ${result.completed.length} 个`) +\n (result.failed.length > 0\n ? pc.red(`,失败 ${result.failed.length} 个`)\n : '')\n );\n } catch (err) {\n s.stop('操作失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskFindCommand(taskId: string): Promise<void> {\n const s = p.spinner();\n s.start('正在查找任务...');\n\n try {\n const task = await getTaskById(taskId);\n s.stop('查找成功');\n displayTaskDetail(task);\n p.outro('任务详情如上');\n } catch (err) {\n s.stop('查找失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskUndoneCommand(options: {\n start?: string;\n end?: string;\n query?: string;\n project?: string;\n json?: boolean;\n}): Promise<void> {\n let tasks: Task[];\n\n try {\n if (options.query) {\n // 预设查询\n tasks = await listUndoneTasksByTimeQuery(options.query);\n } else {\n // 自定义日期范围\n const params: { startDate?: string; endDate?: string; projectIds?: string[] } = {};\n if (options.start) params.startDate = options.start;\n if (options.end) params.endDate = options.end;\n if (options.project) params.projectIds = [options.project];\n tasks = await listUndoneTasksByDate(params);\n }\n\n if (options.json) {\n console.log(JSON.stringify(tasks, null, 2));\n return;\n }\n\n const s = p.spinner();\n s.start('正在获取未完成任务...');\n s.stop(`找到 ${tasks.length} 个未完成任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow('没有找到未完成任务'));\n return;\n }\n\n console.log('');\n displayTaskTable(tasks);\n console.log('');\n p.outro(`共 ${tasks.length} 个未完成任务`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskSearchCommand(keyword: string): Promise<void> {\n const s = p.spinner();\n s.start(`正在搜索 \"${keyword}\"...`);\n\n try {\n const tasks = await searchTask(keyword);\n s.stop(`找到 ${tasks.length} 个匹配任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow(`没有找到包含 \"${keyword}\" 的任务`));\n return;\n }\n\n console.log('');\n for (const task of tasks) {\n const icon = statusIcon(task.status);\n // 高亮关键词\n const title = task.title.replace(\n new RegExp(keyword, 'gi'),\n (m) => pc.bold(pc.yellow(m))\n );\n console.log(` ${icon} ${title} ${pc.dim(task.id)} ${pc.dim(task.projectId)}`);\n }\n console.log('');\n p.outro(`共 ${tasks.length} 个匹配`);\n } catch (err) {\n s.stop('搜索失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\n// ─── 注册命令 ────────────────────────────────────────\n\nexport function registerTaskCommands(cli: {\n command: (name: string, desc: string) => {\n option: (flag: string, desc: string) => {\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n}): void {\n cli\n .command('task-add [title]', '创建任务')\n .option('-p, --project <id>', '项目 ID')\n .option('--content <text>', '任务内容')\n .option('--priority <n>', '优先级: 0(无) / 1(低) / 3(中) / 5(高)')\n .option('--start-date <date>', '开始日期')\n .option('--due-date <date>', '截止日期')\n .option('--all-day', '全天任务')\n .action(taskAddCommand);\n\n cli\n .command('task-get <projectId> <taskId>', '获取任务详情')\n .action(taskGetCommand);\n\n cli\n .command('task-done <projectId> <taskId>', '完成任务')\n .action(taskDoneCommand);\n\n cli\n .command('task-delete <projectId> <taskId>', '删除任务')\n .action(taskDeleteCommand);\n\n cli\n .command('task-update <taskId>', '更新任务')\n .option('-p, --project <id>', '项目 ID(必填)')\n .option('--title <title>', '任务标题')\n .option('--content <text>', '任务内容')\n .option('--priority <n>', '优先级')\n .option('--start-date <date>', '开始日期')\n .option('--due-date <date>', '截止日期')\n .action(taskUpdateCommand);\n\n cli\n .command('task-move <taskId>', '移动任务到其他项目')\n .option('-f, --from <id>', '源项目 ID')\n .option('-t, --to <id>', '目标项目 ID')\n .action(taskMoveCommand);\n\n cli\n .command('task-completed', '查看已完成任务')\n .option('-p, --project <id>', '按项目筛选')\n .option('--start <date>', '开始日期')\n .option('--end <date>', '结束日期')\n .action(taskCompletedCommand);\n\n cli\n .command('task-list', '筛选任务')\n .option('-p, --project <id>', '按项目筛选')\n .option('--start <date>', '开始日期')\n .option('--end <date>', '结束日期')\n .option('--status <n>', '状态,逗号分隔: 0(待办),2(已完成)')\n .option('--priority <n>', '优先级,逗号分隔: 0,1,3,5')\n .option('--tag <tag>', '标签,逗号分隔')\n .option('--json', '输出 JSON 格式')\n .action(taskListCommand);\n\n // ─── 批量 / 高级命令 ────────────────────────────\n\n cli\n .command('task-batch-add [jsonFile]', '批量创建任务')\n .option('--stdin', '从标准输入读取 JSON')\n .action(taskBatchAddCommand);\n\n cli\n .command('task-batch-update [jsonFile]', '批量更新任务')\n .option('--stdin', '从标准输入读取 JSON')\n .action(taskBatchUpdateCommand);\n\n cli\n .command('task-batch-done <projectId>', '批量完成任务')\n .option('--task-ids <ids>', '任务 ID 列表,逗号分隔')\n .option('--all', '完成项目下所有未完成任务')\n .option('--force', '跳过确认')\n .action(taskBatchDoneCommand);\n\n cli\n .command('task-find <taskId>', '按 ID 查找任务(无需项目 ID)')\n .action(taskFindCommand);\n\n cli\n .command('task-undone', '查看未完成任务')\n .option('--start <date>', '开始日期')\n .option('--end <date>', '结束日期')\n .option('--query <preset>', '预设查询: today|tomorrow|last24hour|next24hour|last7day|next7day')\n .option('-p, --project <id>', '按项目筛选')\n .option('--json', '输出 JSON 格式')\n .action(taskUndoneCommand);\n\n cli\n .command('task-search <keyword>', '搜索任务')\n .action(taskSearchCommand);\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport { getUserPreference } from '../api/resources.js';\n\nasync function userPrefCommand(): Promise<void> {\n const s = p.spinner();\n s.start('正在获取用户偏好...');\n\n try {\n const pref = await getUserPreference();\n s.stop('获取成功');\n\n console.log('');\n if (pref.timeZone) console.log(` 时区: ${pref.timeZone}`);\n if (pref.dateFormat !== undefined)\n console.log(` 日期格式: ${pref.dateFormat}`);\n if (pref.language) console.log(` 语言: ${pref.language}`);\n if (pref.theme) console.log(` 主题: ${pref.theme}`);\n\n // 如果所有字段都为空,显示原始数据\n if (!pref.timeZone && pref.dateFormat === undefined && !pref.language && !pref.theme) {\n console.log(pc.dim(' (未获取到偏好信息,API 可能不支持此端点)'));\n }\n console.log('');\n p.outro('用户偏好如上');\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red(`获取用户偏好失败: ${(err as Error).message}`));\n }\n}\n\n// ─── 注册命令 ────────────────────────────────────────\n\nexport function registerUserCommands(cli: {\n command: (name: string, desc: string) => {\n option: (flag: string, desc: string) => {\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n}): void {\n cli.command('user-pref', '查看用户偏好设置').action(userPrefCommand);\n}\n"],"mappings":"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","names":["text","path","text","s","p","pc","pc","s","cli","p","pc","priorityText","pc","statusIcon","s","fs","cli","p","pc","s","pc","cli"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/auth.ts","../src/utils/config.ts","../src/utils/endpoints.ts","../src/api/oauth.ts","../src/utils/server.ts","../src/api/client.ts","../src/commands/project.ts","../src/utils/format.ts","../src/api/resources.ts","../src/commands/task.ts","../src/commands/user.ts"],"sourcesContent":["import { cac } from 'cac';\nimport type { Region } from './types.js';\nimport { loginCommand, logoutCommand, whoamiCommand, configCommand } from './commands/auth.js';\nimport { registerProjectCommands } from './commands/project.js';\nimport { registerTaskCommands } from './commands/task.js';\nimport { registerUserCommands } from './commands/user.js';\n\n// cac v7 不支持空格子命令(如 'task list'),需要将 argv 预处理为连字符格式\nconst SUBCOMMAND_GROUPS = ['task', 'project', 'user'];\nconst argv = process.argv.slice(2);\nif (\n argv.length >= 2 &&\n SUBCOMMAND_GROUPS.includes(argv[0]) &&\n !argv[1].startsWith('-')\n) {\n argv.splice(0, 2, `${argv[0]}-${argv[1]}`);\n}\n\nconst cli = cac('tt');\n\n// 认证命令\ncli.command('login', '登录滴答清单').action(loginCommand);\ncli.command('logout', '登出').action(logoutCommand);\ncli.command('whoami', '查看登录状态').action(whoamiCommand);\ncli\n .command('config', '查看/设置配置')\n .option('--region <region>', '切换区域: cn (国内版) / global (国际版)')\n .action(async (options: { region?: string }) => {\n if (options.region && options.region !== 'cn' && options.region !== 'global') {\n console.error(`无效的区域: ${options.region},请使用 cn 或 global`);\n process.exit(1);\n }\n await configCommand({ region: options.region as Region | undefined });\n });\n\n// 项目命令\nregisterProjectCommands(cli);\n\n// 任务命令\nregisterTaskCommands(cli);\n\n// 用户命令\nregisterUserCommands(cli);\n\ncli.help();\ncli.parse(['', '', ...argv]);\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { Region, OAuthConfig } from '../types.js';\nimport { getOAuth, setOAuth, getToken, clearToken, isTokenValid, getRegion, setRegion } from '../utils/config.js';\nimport { getEndpoints } from '../utils/endpoints.js';\nimport { loginWithBrowser } from '../api/oauth.js';\nimport { apiRequest } from '../api/client.js';\n\nconst REGION_LABELS: Record<Region, string> = {\n cn: '国内版(滴答清单)',\n global: '国际版(TickTick)',\n};\n\n/** 引导用户输入 OAuth 凭证 */\nasync function promptOAuthCredentials(developerUrl: string): Promise<OAuthConfig | undefined> {\n p.log.info(`请访问 ${developerUrl} 获取凭证`);\n p.log.info('Redirect URI 设置为: http://localhost:3000/callback\\n');\n\n const clientId = await p.text({\n message: '请输入 Client ID',\n validate: (v) => (!v ? 'Client ID 不能为空' : undefined),\n });\n if (p.isCancel(clientId)) return undefined;\n\n const clientSecret = await p.text({\n message: '请输入 Client Secret',\n validate: (v) => (!v ? 'Client Secret 不能为空' : undefined),\n });\n if (p.isCancel(clientSecret)) return undefined;\n\n const oauth: OAuthConfig = { clientId, clientSecret };\n setOAuth(oauth);\n p.log.success('凭证已保存');\n return oauth;\n}\n\n/** tt login */\nexport async function loginCommand(): Promise<void> {\n const region = getRegion();\n const endpoints = getEndpoints(region);\n\n p.intro(pc.bgCyan(pc.black(` 滴答清单 CLI 登录 [${REGION_LABELS[region]}] `)));\n\n const token = getToken();\n if (token && isTokenValid()) {\n p.outro(pc.green('已登录,无需重复登录。使用 tt logout 先登出。'));\n return;\n }\n\n let oauth = getOAuth();\n\n // 检测凭证区域不匹配\n if (oauth?.region && oauth.region !== region) {\n p.log.warn(`当前区域为 ${REGION_LABELS[region]},但保存的凭证属于 ${REGION_LABELS[oauth.region]}`);\n p.log.warn('凭证与区域不匹配会导致登录失败\\n');\n const reconfigure = await p.confirm({\n message: `是否为 ${REGION_LABELS[region]} 重新配置凭证?`,\n });\n if (p.isCancel(reconfigure) || !reconfigure) {\n p.outro('已取消');\n return;\n }\n oauth = undefined;\n }\n\n // 旧凭证无区域标记,提示确认后再补充\n if (oauth && !oauth.region) {\n p.log.warn('保存的凭证未标记区域,可能与当前区域不匹配');\n const confirmRegion = await p.confirm({\n message: `这些凭证是否用于 ${REGION_LABELS[region]}?`,\n });\n if (p.isCancel(confirmRegion)) {\n p.outro('已取消');\n return;\n }\n if (confirmRegion) {\n setOAuth(oauth);\n p.log.success(`已将凭证标记为 ${REGION_LABELS[region]}`);\n } else {\n oauth = undefined;\n }\n }\n\n if (!oauth) {\n oauth = await promptOAuthCredentials(endpoints.developerUrl);\n if (!oauth) { p.outro('已取消'); return; }\n }\n\n const s = p.spinner();\n s.start('正在打开浏览器进行授权...');\n\n try {\n await loginWithBrowser(oauth);\n s.stop('授权完成');\n p.outro(pc.green('✔ 登录成功!'));\n } catch (err) {\n s.stop('登录失败');\n const msg = (err as Error).message;\n\n if (msg.includes('invalid_client') || msg.includes('TIMEOUT')) {\n p.log.error(pc.red('登录失败:凭证无效或与区域不匹配'));\n p.log.info(`当前区域:${REGION_LABELS[region]}`);\n p.log.info(`凭证来源:${oauth.region ? REGION_LABELS[oauth.region] : '未知'}\\n`);\n\n const action = await p.select({\n message: '请选择下一步操作',\n options: [\n { value: 'switch', label: `切换到${region === 'cn' ? '国际版' : '国内版'}` },\n { value: 'reconfig', label: '重新输入当前区域的凭证' },\n { value: 'exit', label: '退出' },\n ],\n });\n\n if (p.isCancel(action) || action === 'exit') {\n p.outro('已退出');\n return;\n }\n\n if (action === 'switch') {\n const newRegion: Region = region === 'cn' ? 'global' : 'cn';\n setRegion(newRegion);\n p.log.success(`已切换到 ${REGION_LABELS[newRegion]},请重新运行 tt login`);\n p.outro('区域已切换');\n return;\n }\n\n if (action === 'reconfig') {\n await promptOAuthCredentials(endpoints.developerUrl);\n p.outro('凭证已更新,请重新运行 tt login');\n return;\n }\n }\n\n p.outro(pc.red(`✖ ${msg}`));\n process.exit(1);\n }\n}\n\n/** tt logout */\nexport async function logoutCommand(): Promise<void> {\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 登出 ')));\n clearToken();\n p.outro(pc.green('✔ 已登出'));\n}\n\n/** tt whoami */\nexport async function whoamiCommand(): Promise<void> {\n const region = getRegion();\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 状态 ')));\n\n const token = getToken();\n if (!token) {\n p.outro(pc.yellow('未登录,请先运行 tt login'));\n return;\n }\n\n const s = p.spinner();\n s.start('正在验证登录状态...');\n\n try {\n await apiRequest<unknown[]>('project');\n s.stop('验证完成');\n\n const expiresIn = token.expiresAt - Date.now();\n if (expiresIn <= 0) {\n p.outro(pc.yellow('Token 已失效,请运行 tt login 重新登录'));\n return;\n }\n\n const hours = Math.floor(expiresIn / 3600000);\n const minutes = Math.floor((expiresIn % 3600000) / 60000);\n p.log.success(pc.green(`已登录 [${REGION_LABELS[region]}]`));\n p.log.info(`Token 有效期: 剩余 ${hours} 小时 ${minutes} 分钟`);\n p.outro('一切正常');\n } catch {\n s.stop('验证失败');\n p.outro(pc.red('Token 已失效,请运行 tt login 重新登录'));\n }\n}\n\n/** tt config [--region cn|global] */\nexport async function configCommand(args?: { region?: Region }): Promise<void> {\n if (args?.region) {\n const oldRegion = getRegion();\n setRegion(args.region);\n clearToken();\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 配置 ')));\n p.log.success(`已切换到 ${REGION_LABELS[args.region]}`);\n if (oldRegion !== args.region) {\n p.log.warn('区域已变更,请重新运行 tt login');\n }\n p.outro('配置已更新');\n return;\n }\n\n const region = getRegion();\n p.intro(pc.bgCyan(pc.black(' 滴答清单 CLI 配置 ')));\n p.log.info(`区域: ${REGION_LABELS[region]}`);\n\n const oauth = getOAuth();\n if (oauth) {\n p.log.info(`Client ID: ${oauth.clientId}`);\n p.log.info(`Client Secret: ${oauth.clientSecret.substring(0, 8)}${'*'.repeat(Math.max(0, oauth.clientSecret.length - 8))}`);\n } else {\n p.log.warn('尚未配置 OAuth 凭证');\n }\n\n const token = getToken();\n if (token) {\n p.log.info(`Token: ${token.accessToken.substring(0, 8)}...`);\n p.log.info(`过期时间: ${new Date(token.expiresAt).toLocaleString('zh-CN')}`);\n } else {\n p.log.info('Token: 未登录');\n }\n\n p.log.info('\\n使用 tt config --region cn/global 切换区域');\n p.outro('配置信息如上');\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport type { AppConfig, OAuthConfig, Region, TokenData } from '../types.js';\n\n/** 配置目录,可通过环境变量覆盖(测试用) */\nfunction getConfigDir(): string {\n return process.env.TT_CLI_CONFIG_DIR ?? path.join(os.homedir(), '.tt-cli');\n}\n\nconst CONFIG_FILE = 'config.json';\n\nfunction getConfigPath(): string {\n return path.join(getConfigDir(), CONFIG_FILE);\n}\n\nfunction ensureConfigDir(): void {\n const dir = getConfigDir();\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n}\n\nfunction readConfig(): AppConfig {\n const configPath = getConfigPath();\n if (!fs.existsSync(configPath)) return {};\n return JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n}\n\nfunction writeConfig(config: AppConfig): void {\n ensureConfigDir();\n fs.writeFileSync(getConfigPath(), JSON.stringify(config, null, 2));\n}\n\n/** 读取区域设置,默认国内版 */\nexport function getRegion(): Region {\n return readConfig().region ?? 'cn';\n}\n\n/** 保存区域设置 */\nexport function setRegion(region: Region): void {\n const config = readConfig();\n config.region = region;\n writeConfig(config);\n}\n\n/** 读取 OAuth 凭证 */\nexport function getOAuth(): OAuthConfig | undefined {\n return readConfig().oauth;\n}\n\n/** 保存 OAuth 凭证(同时记录当前区域) */\nexport function setOAuth(oauth: OAuthConfig): void {\n const config = readConfig();\n config.oauth = { ...oauth, region: getRegion() };\n writeConfig(config);\n}\n\n/** 获取凭证所属区域 */\nexport function getOAuthRegion(): Region | undefined {\n return readConfig().oauth?.region;\n}\n\n/** 读取 Token */\nexport function getToken(): TokenData | undefined {\n return readConfig().token;\n}\n\n/** 保存 Token */\nexport function setToken(token: TokenData): void {\n const config = readConfig();\n config.token = token;\n writeConfig(config);\n}\n\n/** 清除 Token(保留 OAuth 凭证) */\nexport function clearToken(): void {\n const config = readConfig();\n delete config.token;\n writeConfig(config);\n}\n\n/** Token 是否有效(未过期且剩余 > 5 分钟) */\nexport function isTokenValid(): boolean {\n const token = getToken();\n if (!token) return false;\n return Date.now() < token.expiresAt - 5 * 60 * 1000;\n}\n","import type { Region, RegionEndpoints } from '../types.js';\n\n/** 区域接口地址映射 */\nconst ENDPOINTS: Record<Region, RegionEndpoints> = {\n cn: {\n authUrl: 'https://dida365.com/oauth/authorize',\n tokenUrl: 'https://dida365.com/oauth/token',\n apiBase: 'https://api.dida365.com/open/v1/',\n developerUrl: 'https://developer.dida365.com/app',\n },\n global: {\n authUrl: 'https://ticktick.com/oauth/authorize',\n tokenUrl: 'https://ticktick.com/oauth/token',\n apiBase: 'https://api.ticktick.com/open/v1/',\n developerUrl: 'https://developer.ticktick.com/app',\n },\n};\n\n/** 获取指定区域的接口地址 */\nexport function getEndpoints(region: Region): RegionEndpoints {\n return ENDPOINTS[region];\n}\n","import crypto from 'crypto';\nimport open from 'open';\nimport type { OAuthConfig, TokenData, TokenResponse } from '../types.js';\nimport { getOAuth, getToken, setToken, getRegion } from '../utils/config.js';\nimport { getEndpoints } from '../utils/endpoints.js';\nimport { createCallbackServer } from '../utils/server.js';\n\nconst SCOPES = 'tasks:read tasks:write';\nconst DEFAULT_PORT = 3000;\n\n/** 生成随机 state(防 CSRF) */\nexport function generateState(): string {\n return crypto.randomBytes(16).toString('hex');\n}\n\n/** 构建授权 URL */\nexport function buildAuthUrl(config: OAuthConfig, state: string, port: number, region: 'cn' | 'global' = 'cn'): string {\n const endpoints = getEndpoints(region);\n const redirectUri = `http://localhost:${port}/callback`;\n const params = new URLSearchParams({\n client_id: config.clientId,\n response_type: 'code',\n redirect_uri: redirectUri,\n scope: SCOPES,\n state,\n });\n return `${endpoints.authUrl}?${params.toString()}`;\n}\n\n/** 用授权码换取 Token */\nexport async function exchangeCode(\n config: OAuthConfig,\n code: string,\n port: number\n): Promise<TokenData> {\n const region = getRegion();\n const endpoints = getEndpoints(region);\n const redirectUri = `http://localhost:${port}/callback`;\n const credentials = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64');\n\n const response = await fetch(endpoints.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Authorization': `Basic ${credentials}`,\n },\n body: new URLSearchParams({\n code,\n grant_type: 'authorization_code',\n redirect_uri: redirectUri,\n scope: SCOPES,\n }).toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Token 交换失败: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n return {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\n/** 刷新 Token */\nexport async function refreshAccessToken(): Promise<TokenData> {\n const oauth = getOAuth();\n const token = getToken();\n const region = getRegion();\n const endpoints = getEndpoints(region);\n\n if (!oauth || !token) {\n throw new Error('未登录,请先运行 tt login');\n }\n\n const credentials = Buffer.from(`${oauth.clientId}:${oauth.clientSecret}`).toString('base64');\n\n const response = await fetch(endpoints.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Authorization': `Basic ${credentials}`,\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: token.refreshToken,\n }).toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Token 刷新失败: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n const newToken: TokenData = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n setToken(newToken);\n return newToken;\n}\n\n/** 完整登录流程 */\nexport async function loginWithBrowser(config: OAuthConfig, port = DEFAULT_PORT): Promise<TokenData> {\n const region = getRegion();\n const state = generateState();\n const authUrl = buildAuthUrl(config, state, port, region);\n\n // 先启动服务器\n const codePromise = createCallbackServer(state, port);\n\n // 再打开浏览器\n await open(authUrl);\n\n // 等待回调(含超时处理)\n let callbackResult: { code: string; close: () => void };\n try {\n callbackResult = await codePromise;\n } catch (err) {\n if ((err as Error).message === 'TIMEOUT') {\n throw new Error(\n '登录超时(2 分钟未收到授权回调)。\\n' +\n '可能原因:\\n' +\n ' 1. 浏览器授权页面显示了错误(如 invalid_client)\\n' +\n ' 2. 凭证与当前区域不匹配\\n' +\n ` 当前区域:${region === 'cn' ? '国内版(dida365.com)' : '国际版(ticktick.com)'}\\n` +\n '建议:检查浏览器页面错误,或尝试切换区域/重新配置凭证'\n );\n }\n throw err;\n }\n\n // 交换 token\n const token = await exchangeCode(config, callbackResult.code, port);\n setToken(token);\n\n // 关闭服务器\n callbackResult.close();\n\n return token;\n}\n","import http from 'http';\n\ninterface CallbackResult {\n code: string;\n close: () => void;\n}\n\n/**\n * 创建临时本地 HTTP 服务器,等待 OAuth2 回调\n * 返回 Promise,在收到合法回调时 resolve,超时 2 分钟后 reject\n */\nexport function createCallbackServer(\n expectedState: string,\n port: number\n): Promise<CallbackResult> {\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url!, `http://localhost:${port}`);\n\n if (url.pathname !== '/callback') {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n const code = url.searchParams.get('code');\n const state = url.searchParams.get('state');\n\n if (state !== expectedState) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end('<h1>授权失败:state 不匹配</h1>');\n if (!settled) { settled = true; reject(new Error('CSRF state 不匹配')); }\n server.close();\n return;\n }\n\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end('<h1>授权失败:缺少 code 参数</h1>');\n if (!settled) { settled = true; reject(new Error('缺少授权码')); }\n server.close();\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end('<html><body style=\"display:flex;justify-content:center;align-items:center;height:100vh;font-family:sans-serif\"><h1>✅ 授权成功!请返回终端。</h1></body></html>');\n\n if (!settled) {\n settled = true;\n resolve({\n code,\n close: () => server.close(),\n });\n }\n });\n\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (!settled) {\n settled = true;\n if (err.code === 'EADDRINUSE') {\n reject(new Error(`端口 ${port} 已被占用,请关闭占用该端口的程序或等待重试`));\n } else {\n reject(err);\n }\n }\n });\n\n server.listen(port);\n\n // 2 分钟超时\n setTimeout(() => {\n if (!settled) {\n settled = true;\n server.close();\n reject(new Error('TIMEOUT'));\n }\n }, 120_000);\n });\n}\n","import { getOAuth, getToken, isTokenValid, getRegion } from '../utils/config.js';\nimport { getEndpoints } from '../utils/endpoints.js';\nimport { refreshAccessToken } from './oauth.js';\n\n/** 获取有效的 access token(自动刷新) */\nasync function getValidToken(): Promise<string> {\n const oauth = getOAuth();\n const token = getToken();\n\n if (!oauth || !token) {\n throw new Error('未登录,请先运行 tt login');\n }\n\n if (isTokenValid()) {\n return token.accessToken;\n }\n\n const newToken = await refreshAccessToken();\n return newToken.accessToken;\n}\n\n/** 发送 API 请求 */\nexport async function apiRequest<T>(path: string, options?: RequestInit): Promise<T> {\n const token = await getValidToken();\n const endpoints = getEndpoints(getRegion());\n\n const response = await fetch(`${endpoints.apiBase}${path}`, {\n ...options,\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`API 请求失败: ${response.status} ${text}`);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n // 读取响应文本,处理空 body(TickTick 部分 API 返回 200 + 空 body)\n const text = await response.text();\n if (!text || text.trim() === '') {\n return undefined as T;\n }\n\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new Error(\n `API 响应 JSON 解析失败 (HTTP ${response.status})\\n` +\n `路径: ${path}\\n` +\n `原始响应: ${text.substring(0, 500)}\\n` +\n `建议: 请检查 API 端点是否正确,或尝试 tt task-search 验证数据`\n );\n }\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { Task, CreateProjectParams, UpdateProjectParams } from '../types.js';\nimport { formatTaskTime } from '../utils/format.js';\nimport {\n getProjects,\n getProject,\n getProjectData,\n createProject,\n updateProject,\n deleteProject,\n} from '../api/resources.js';\n\n// ─── 格式化工具 ──────────────────────────────────────\n\nconst PRIORITY_LABEL: Record<number, string> = {\n 0: '无',\n 1: '低',\n 3: '中',\n 5: '高',\n};\n\nfunction priorityText(priority?: number): string {\n const v = priority ?? 0;\n switch (v) {\n case 5:\n return pc.red('高');\n case 3:\n return pc.yellow('中');\n case 1:\n return pc.blue('低');\n default:\n return pc.dim('无');\n }\n}\n\nfunction statusIcon(status?: number): string {\n return status === 2 ? pc.green('✓') : '○';\n}\n\nfunction displayTaskList(tasks: Task[]): void {\n if (tasks.length === 0) {\n p.log.info(pc.dim(' (无任务)'));\n return;\n }\n\n for (const task of tasks) {\n const icon = statusIcon(task.status);\n const title =\n task.title.length > 30\n ? task.title.slice(0, 30) + '…'\n : task.title;\n const time = formatTaskTime(task);\n const timeStr = time ? pc.cyan(time) : '';\n console.log(\n ` ${icon} ${title} ${timeStr} ${priorityText(task.priority)}`\n );\n if (task.content) {\n const content =\n task.content.length > 50\n ? task.content.slice(0, 50) + '…'\n : task.content;\n console.log(` ${pc.dim(content)}`);\n }\n }\n}\n\n// ─── 命令实现 ────────────────────────────────────────\n\nasync function projectListCommand(): Promise<void> {\n const s = p.spinner();\n s.start('正在获取项目列表...');\n\n try {\n const projects = await getProjects();\n s.stop(`找到 ${projects.length} 个项目`);\n\n if (projects.length === 0) {\n p.outro(pc.yellow('没有找到任何项目'));\n return;\n }\n\n console.log('');\n for (const project of projects) {\n const status = project.closed ? pc.dim('已关闭') : pc.green('活跃');\n console.log(\n ` ${pc.bold(project.name)} ${pc.dim(project.id)}`\n );\n console.log(\n ` 类型: ${project.kind || '-'} 视图: ${project.viewMode || '-'} ${status}`\n );\n }\n console.log('');\n p.outro(`共 ${projects.length} 个项目`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectGetCommand(id: string): Promise<void> {\n const s = p.spinner();\n s.start('正在获取项目详情...');\n\n try {\n const project = await getProject(id);\n s.stop('获取成功');\n\n console.log('');\n console.log(` ${pc.bold('名称')}: ${project.name}`);\n console.log(` ${pc.bold('ID')}: ${project.id}`);\n console.log(` ${pc.bold('颜色')}: ${project.color || '-'}`);\n console.log(` ${pc.bold('类型')}: ${project.kind || '-'}`);\n console.log(` ${pc.bold('视图')}: ${project.viewMode || '-'}`);\n console.log(\n ` ${pc.bold('状态')}: ${project.closed ? '已关闭' : '活跃'}`\n );\n if (project.groupId)\n console.log(` ${pc.bold('分组')}: ${project.groupId}`);\n if (project.permission)\n console.log(` ${pc.bold('权限')}: ${project.permission}`);\n console.log('');\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectTasksCommand(\n id: string,\n options: { json?: boolean }\n): Promise<void> {\n try {\n const data = await getProjectData(id);\n\n if (options.json) {\n console.log(JSON.stringify(data.tasks, null, 2));\n return;\n }\n\n const s = p.spinner();\n s.start('正在获取项目任务...');\n s.stop(\n `项目「${data.project.name}」下有 ${data.tasks.length} 个任务`\n );\n\n if (data.tasks.length === 0) {\n p.outro(pc.yellow('该项目下没有任务'));\n return;\n }\n\n console.log('');\n displayTaskList(data.tasks);\n console.log('');\n p.outro(`共 ${data.tasks.length} 个任务`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectCreateCommand(\n name: string | undefined,\n options: {\n color?: string;\n viewMode?: string;\n kind?: string;\n }\n): Promise<void> {\n if (!name) {\n const input = await p.text({ message: '请输入项目名称' });\n if (p.isCancel(input)) {\n p.outro('已取消');\n return;\n }\n name = input;\n }\n\n const params: CreateProjectParams = { name };\n if (options.color) params.color = options.color;\n if (options.viewMode)\n params.viewMode = options.viewMode as CreateProjectParams['viewMode'];\n if (options.kind)\n params.kind = options.kind as CreateProjectParams['kind'];\n\n const s = p.spinner();\n s.start('正在创建项目...');\n\n try {\n const project = await createProject(params);\n s.stop('创建成功');\n p.outro(\n pc.green(`项目「${project.name}」已创建 (ID: ${project.id})`)\n );\n } catch (err) {\n s.stop('创建失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectUpdateCommand(\n id: string,\n options: {\n name?: string;\n color?: string;\n viewMode?: string;\n kind?: string;\n }\n): Promise<void> {\n const params: UpdateProjectParams = {};\n if (options.name) params.name = options.name;\n if (options.color) params.color = options.color;\n if (options.viewMode)\n params.viewMode = options.viewMode as UpdateProjectParams['viewMode'];\n if (options.kind)\n params.kind = options.kind as UpdateProjectParams['kind'];\n\n if (Object.keys(params).length === 0) {\n p.outro(\n pc.yellow(\n '未指定任何更新内容,使用 --name / --color / --view-mode / --kind 选项'\n )\n );\n return;\n }\n\n const s = p.spinner();\n s.start('正在更新项目...');\n\n try {\n const project = await updateProject(id, params);\n s.stop('更新成功');\n p.outro(pc.green(`项目「${project.name}」已更新`));\n } catch (err) {\n s.stop('更新失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function projectDeleteCommand(id: string): Promise<void> {\n const confirmed = await p.confirm({\n message: `确认删除项目 ${pc.red(id)}?此操作不可撤销`,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.outro('已取消');\n return;\n }\n\n const s = p.spinner();\n s.start('正在删除项目...');\n\n try {\n await deleteProject(id);\n s.stop('删除成功');\n p.outro(pc.green('项目已删除'));\n } catch (err) {\n s.stop('删除失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\n// ─── 注册命令 ────────────────────────────────────────\n\nexport function registerProjectCommands(cli: {\n command: (name: string, desc: string) => {\n option: (flag: string, desc: string) => {\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n}): void {\n cli\n .command('project-list', '列出所有项目')\n .action(projectListCommand);\n\n cli\n .command('project-get <id>', '获取项目详情')\n .action(projectGetCommand);\n\n cli\n .command('project-tasks <id>', '获取项目下的任务')\n .option('--json', '输出 JSON 格式')\n .action(projectTasksCommand);\n\n cli\n .command('project-create [name]', '创建项目')\n .option('--color <color>', '项目颜色,如 #F18181')\n .option('--view-mode <mode>', '视图模式: list / kanban / timeline')\n .option('--kind <kind>', '项目类型: TASK / NOTE')\n .action(projectCreateCommand);\n\n cli\n .command('project-update <id>', '更新项目')\n .option('--name <name>', '项目名称')\n .option('--color <color>', '项目颜色')\n .option('--view-mode <mode>', '视图模式')\n .option('--kind <kind>', '项目类型')\n .action(projectUpdateCommand);\n\n cli\n .command('project-delete <id>', '删除项目')\n .action(projectDeleteCommand);\n}\n","/**\n * 任务时间格式化工具\n */\n\n/**\n * 规范化日期字符串为 TickTick API 要求的格式\n * TickTick API 要求: \"2026-04-04T19:00:00.000+0800\"(有毫秒,时区无冒号)\n *\n * 支持输入格式:\n * - \"2026-04-04T19:00\" → \"2026-04-04T19:00:00.000+0800\"(补秒+毫秒+时区)\n * - \"2026-04-04T19:00:00\" → \"2026-04-04T19:00:00.000+0800\"(补毫秒+时区)\n * - \"2026-04-04T19:00:00+08:00\" → \"2026-04-04T19:00:00.000+0800\"\n * - \"2026-04-04T19:00:00Z\" → \"2026-04-04T19:00:00.000+0000\"\n * - \"2026-04-04T19:00:00.123+0800\" → 保持不变\n */\nexport function normalizeTickTickDate(dateStr: string): string {\n let result = dateStr;\n // 1. 补秒: \"T19:00\" → \"T19:00:00\"(无秒数的情况)\n result = result.replace(/(T\\d{2}:\\d{2})(?![.:]|\\d)/, '$1:00');\n // 2. 补时区: 无时区后缀时默认 +0800(先补时区,确保后续补毫秒能匹配到 [+-Z])\n if (!/[Zz]$|[+\\-]\\d{2}:?\\d{2}$/.test(result)) {\n result += '+0800';\n }\n // 3. 补毫秒: \"T19:00:00+\" → \"T19:00:00.000+\"\n if (!/T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}/.test(result)) {\n result = result.replace(/(T\\d{2}:\\d{2}:\\d{2})([+\\-Z])/, '$1.000$2');\n }\n // 4. 去时区冒号: \"+08:00\" → \"+0800\"\n result = result.replace(/([+\\-])(\\d{2}):(\\d{2})$/, '$1$2$3');\n // 5. \"Z\" → \"+0000\"\n if (result.endsWith('Z')) {\n result = result.slice(0, -1) + '+0000';\n }\n return result;\n}\n\n/** 从 TickTick ISO 8601 日期字符串提取本地时间的 HH:mm */\nfunction extractHM(dateStr: string): string | null {\n // TickTick 返回格式如 \"2026-04-04T14:15:00+0000\" 或 \"2026-04-04T14:15:00+08:00\"\n // API 返回 UTC 时间,需转换为本地时间显示\n try {\n const d = new Date(dateStr);\n if (isNaN(d.getTime())) return null;\n const hours = d.getHours().toString().padStart(2, '0');\n const minutes = d.getMinutes().toString().padStart(2, '0');\n return `${hours}:${minutes}`;\n } catch {\n // 回退:直接从字符串提取 HH:mm\n const match = dateStr.match(/T(\\d{2}):(\\d{2})/);\n if (!match) return null;\n return `${match[1]}:${match[2]}`;\n }\n}\n\n/**\n * 格式化任务时间范围,用于表格显示\n * - 全天任务显示 \"全天\"\n * - 有起止时间显示 \"HH:mm-HH:mm\"\n * - 仅有开始时间显示 \"HH:mm\"\n * - 无时间显示空字符串\n */\nexport function formatTaskTime(task: {\n startDate?: string;\n dueDate?: string;\n isAllDay?: boolean;\n}): string {\n if (task.isAllDay && task.startDate) return '全天';\n if (!task.startDate) return '';\n\n const start = extractHM(task.startDate);\n if (!start) return '';\n\n if (task.dueDate) {\n const end = extractHM(task.dueDate);\n if (end && end !== start) return `${start}-${end}`;\n }\n\n return start;\n}\n","import { apiRequest } from './client.js';\nimport type {\n Project,\n ProjectData,\n Task,\n CreateProjectParams,\n UpdateProjectParams,\n CreateTaskParams,\n UpdateTaskParams,\n MoveTaskParams,\n CompletedTasksParams,\n FilterTasksParams,\n BatchTasksParams,\n UserPreference,\n UndoneTasksParams,\n} from '../types.js';\n\n// ─── Project API ─────────────────────────────────────\n\n/** 获取所有项目 */\nexport function getProjects(): Promise<Project[]> {\n return apiRequest<Project[]>('project');\n}\n\n/** 获取单个项目 */\nexport function getProject(projectId: string): Promise<Project> {\n return apiRequest<Project>(`project/${projectId}`);\n}\n\n/** 获取项目及任务数据 */\nexport function getProjectData(projectId: string): Promise<ProjectData> {\n return apiRequest<ProjectData>(`project/${projectId}/data`);\n}\n\n/** 创建项目 */\nexport function createProject(data: CreateProjectParams): Promise<Project> {\n return apiRequest<Project>('project', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 更新项目 */\nexport function updateProject(\n projectId: string,\n data: UpdateProjectParams\n): Promise<Project> {\n return apiRequest<Project>(`project/${projectId}`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 删除项目 */\nexport function deleteProject(projectId: string): Promise<void> {\n return apiRequest<void>(`project/${projectId}`, { method: 'DELETE' });\n}\n\n// ─── Task API ────────────────────────────────────────\n\n/** 获取任务 */\nexport function getTask(projectId: string, taskId: string): Promise<Task> {\n return apiRequest<Task>(`project/${projectId}/task/${taskId}`);\n}\n\n/** 创建任务 */\nexport function createTask(data: CreateTaskParams): Promise<Task> {\n return apiRequest<Task>('task', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 更新任务 */\nexport function updateTask(\n taskId: string,\n data: UpdateTaskParams\n): Promise<Task> {\n return apiRequest<Task>(`task/${taskId}`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n}\n\n/** 完成任务 */\nexport function completeTask(\n projectId: string,\n taskId: string\n): Promise<void> {\n return apiRequest<void>(`project/${projectId}/task/${taskId}/complete`, {\n method: 'POST',\n });\n}\n\n/** 删除任务 */\nexport function deleteTask(\n projectId: string,\n taskId: string\n): Promise<void> {\n return apiRequest<void>(`project/${projectId}/task/${taskId}`, {\n method: 'DELETE',\n });\n}\n\n/** 移动任务 */\nexport function moveTasks(\n moves: MoveTaskParams[]\n): Promise<Array<{ id: string; etag: string }>> {\n return apiRequest<Array<{ id: string; etag: string }>>('task/move', {\n method: 'POST',\n body: JSON.stringify(moves),\n });\n}\n\n/** 获取已完成任务 */\nexport function getCompletedTasks(\n params: CompletedTasksParams\n): Promise<Task[]> {\n return apiRequest<Task[]>('task/completed', {\n method: 'POST',\n body: JSON.stringify(params),\n });\n}\n\n/** 筛选任务 */\nexport function filterTasks(params: FilterTasksParams): Promise<Task[]> {\n return apiRequest<Task[]>('task/filter', {\n method: 'POST',\n body: JSON.stringify(params),\n });\n}\n\n// ─── 批量操作 ──────────────────────────────────────\n\n/** 批量添加任务(API 返回 { id2etag: {...} },不是 Task[]) */\nexport async function batchAddTasks(\n tasks: CreateTaskParams[]\n): Promise<{ count: number; id2etag?: Record<string, string> }> {\n const res = await apiRequest<Record<string, unknown>>('task/batch', {\n method: 'POST',\n body: JSON.stringify({ add: tasks }),\n });\n return {\n count: tasks.length,\n id2etag: (res?.id2etag ?? res) as Record<string, string> | undefined,\n };\n}\n\n/** 批量更新任务 */\nexport function batchUpdateTasks(\n tasks: UpdateTaskParams[]\n): Promise<void> {\n return apiRequest<void>('task/batch', {\n method: 'POST',\n body: JSON.stringify({ update: tasks }),\n });\n}\n\n/** 批量完成项目内任务 */\nexport async function completeTasksInProject(\n projectId: string,\n taskIds: string[]\n): Promise<{ completed: string[]; failed: string[] }> {\n const completed: string[] = [];\n const failed: string[] = [];\n for (const taskId of taskIds) {\n try {\n await completeTask(projectId, taskId);\n completed.push(taskId);\n } catch {\n failed.push(taskId);\n }\n }\n return { completed, failed };\n}\n\n// ─── 查询 ──────────────────────────────────────────\n\n/** 按 ID 查找任务(无需 projectId,同时搜索未完成和已完成任务) */\nexport async function getTaskById(taskId: string): Promise<Task> {\n // 并行获取未完成任务和已完成任务,确保覆盖所有任务\n // 注意:filterTasks API 有返回数量限制,改用 listUndoneTasksByDate 获取更完整的数据\n const [undoneTasks, completedTasks] = await Promise.all([\n listUndoneTasksByDate({}),\n getCompletedTasks({}),\n ]);\n const allTasks = [...undoneTasks, ...completedTasks];\n const task = allTasks.find((t) => t.id === taskId);\n if (!task) throw new Error(`任务 ${taskId} 不存在`);\n return task;\n}\n\n/** 获取用户偏好 */\nexport function getUserPreference(): Promise<UserPreference> {\n return apiRequest<UserPreference>('user/info');\n}\n\n/** 按日期范围获取未完成任务 */\nexport function listUndoneTasksByDate(\n params: UndoneTasksParams\n): Promise<Task[]> {\n const filterParams: FilterTasksParams = { status: [0] };\n if (params.projectIds) filterParams.projectIds = params.projectIds;\n if (params.startDate) filterParams.startDate = params.startDate;\n if (params.endDate) filterParams.endDate = params.endDate;\n return filterTasks(filterParams);\n}\n\n/** 按预设查询获取未完成任务 */\nexport function listUndoneTasksByTimeQuery(\n query: string\n): Promise<Task[]> {\n const now = new Date();\n let startDate: string;\n let endDate: string;\n\n const toISO = (d: Date) => d.toISOString();\n\n switch (query) {\n case 'today': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const end = new Date(start);\n end.setDate(end.getDate() + 1);\n startDate = toISO(start);\n endDate = toISO(end);\n break;\n }\n case 'tomorrow': {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);\n const end = new Date(start);\n end.setDate(end.getDate() + 1);\n startDate = toISO(start);\n endDate = toISO(end);\n break;\n }\n case 'last24hour': {\n const start = new Date(now.getTime() - 24 * 60 * 60 * 1000);\n startDate = toISO(start);\n endDate = toISO(now);\n break;\n }\n case 'next24hour': {\n const end = new Date(now.getTime() + 24 * 60 * 60 * 1000);\n startDate = toISO(now);\n endDate = toISO(end);\n break;\n }\n case 'last7day': {\n const start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n startDate = toISO(start);\n endDate = toISO(now);\n break;\n }\n case 'next7day': {\n const end = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);\n startDate = toISO(now);\n endDate = toISO(end);\n break;\n }\n default:\n throw new Error(\n `不支持的查询预设: ${query},支持: today, tomorrow, last24hour, next24hour, last7day, next7day`\n );\n }\n\n return listUndoneTasksByDate({ startDate, endDate });\n}\n\n/** 搜索任务(关键词匹配,同时搜索未完成和已完成任务) */\nexport async function searchTask(keyword: string): Promise<Task[]> {\n // 并行获取未完成任务和已完成任务,确保覆盖所有任务\n // 注意:filterTasks API 有返回数量限制,改用 listUndoneTasksByDate 获取更完整的数据\n const [undoneTasks, completedTasks] = await Promise.all([\n listUndoneTasksByDate({}),\n getCompletedTasks({}),\n ]);\n\n // 合并并去重(按 id)\n const taskMap = new Map<string, Task>();\n for (const t of [...undoneTasks, ...completedTasks]) {\n taskMap.set(t.id, t);\n }\n const allTasks = Array.from(taskMap.values());\n\n const lower = keyword.toLowerCase();\n return allTasks.filter(\n (t) =>\n t.title.toLowerCase().includes(lower) ||\n (t.content && t.content.toLowerCase().includes(lower))\n );\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type {\n Project,\n Task,\n CreateTaskParams,\n UpdateTaskParams,\n} from '../types.js';\nimport { formatTaskTime, normalizeTickTickDate } from '../utils/format.js';\nimport {\n getProjects,\n getTask,\n createTask,\n updateTask,\n completeTask,\n deleteTask,\n moveTasks,\n getCompletedTasks,\n filterTasks,\n batchAddTasks,\n batchUpdateTasks,\n completeTasksInProject,\n getTaskById,\n listUndoneTasksByDate,\n listUndoneTasksByTimeQuery,\n searchTask,\n} from '../api/resources.js';\n\n// ─── 格式化工具 ──────────────────────────────────────\n\nfunction priorityText(priority?: number): string {\n const v = priority ?? 0;\n switch (v) {\n case 5:\n return pc.red('高');\n case 3:\n return pc.yellow('中');\n case 1:\n return pc.blue('低');\n default:\n return pc.dim('无');\n }\n}\n\nfunction statusIcon(status?: number): string {\n return status === 2 ? pc.green('✓') : '○';\n}\n\nfunction displayTaskDetail(task: Task): void {\n console.log('');\n console.log(` ${pc.bold(task.title)}`);\n console.log(` ${pc.dim('─'.repeat(40))}`);\n console.log(` ID: ${task.id}`);\n console.log(` 项目: ${task.projectId}`);\n console.log(` 优先级: ${priorityText(task.priority)}`);\n console.log(` 状态: ${task.status === 2 ? pc.green('已完成') : '待办'}`);\n if (task.isAllDay !== undefined)\n console.log(` 全天: ${task.isAllDay ? '是' : '否'}`);\n if (task.startDate)\n console.log(` 开始: ${task.startDate}`);\n if (task.dueDate)\n console.log(` 截止: ${task.dueDate}`);\n if (task.timeZone)\n console.log(` 时区: ${task.timeZone}`);\n if (task.kind)\n console.log(` 类型: ${task.kind}`);\n if (task.content) {\n console.log(` 内容:`);\n console.log(` ${task.content}`);\n }\n if (task.tags && task.tags.length > 0) {\n console.log(` 标签: ${task.tags.join(', ')}`);\n }\n if (task.items && task.items.length > 0) {\n console.log(` 子任务:`);\n for (const item of task.items) {\n const icon = item.status === 1 ? pc.green('✓') : '○';\n console.log(` ${icon} ${item.title}`);\n }\n }\n console.log('');\n}\n\nfunction displayTaskTable(tasks: Task[]): void {\n if (tasks.length === 0) {\n p.log.info(pc.dim(' (无任务)'));\n return;\n }\n\n for (const task of tasks) {\n const icon = statusIcon(task.status);\n const title =\n task.title.length > 30\n ? task.title.slice(0, 30) + '…'\n : task.title;\n const time = formatTaskTime(task);\n const timeStr = time ? pc.cyan(time) : '';\n console.log(\n ` ${icon} ${title} ${timeStr} ${pc.dim(task.id)} ${priorityText(task.priority)} ${pc.dim(task.projectId)}`\n );\n }\n}\n\n/** 交互式选择项目 */\nasync function selectProject(): Promise<string | undefined> {\n const s = p.spinner();\n s.start('正在获取项目列表...');\n const projects = await getProjects();\n s.stop('');\n\n if (projects.length === 0) {\n p.log.error('没有可用的项目,请先创建项目');\n return undefined;\n }\n\n const selected = await p.select({\n message: '选择项目',\n options: projects.map((proj: Project) => ({\n value: proj.id,\n label: proj.name,\n })),\n });\n\n if (p.isCancel(selected)) return undefined;\n return selected as string;\n}\n\n/** 解析优先级字符串 */\nfunction parsePriority(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const n = parseInt(value, 10);\n if ([0, 1, 3, 5].includes(n)) return n;\n return undefined;\n}\n\n// ─── 命令实现 ────────────────────────────────────────\n\nasync function taskAddCommand(\n title: string | undefined,\n options: {\n project?: string;\n content?: string;\n priority?: string;\n startDate?: string;\n dueDate?: string;\n allDay?: boolean;\n }\n): Promise<void> {\n if (!title) {\n const input = await p.text({ message: '请输入任务标题' });\n if (p.isCancel(input)) {\n p.outro('已取消');\n return;\n }\n title = input;\n }\n\n let projectId = options.project;\n if (!projectId) {\n projectId = await selectProject();\n if (!projectId) {\n p.outro('已取消');\n return;\n }\n }\n\n const params: CreateTaskParams = { title, projectId };\n if (options.content) params.content = options.content;\n if (options.priority) {\n const priority = parsePriority(options.priority);\n if (priority !== undefined) params.priority = priority;\n }\n if (options.startDate) params.startDate = normalizeTickTickDate(options.startDate);\n if (options.dueDate) params.dueDate = normalizeTickTickDate(options.dueDate);\n if (options.allDay !== undefined) params.isAllDay = options.allDay;\n\n const s = p.spinner();\n s.start('正在创建任务...');\n\n try {\n const task = await createTask(params);\n s.stop('创建成功');\n p.outro(pc.green(`任务「${task.title}」已创建 (ID: ${task.id})`));\n } catch (err) {\n s.stop('创建失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskGetCommand(\n projectId: string,\n taskId: string\n): Promise<void> {\n const s = p.spinner();\n s.start('正在获取任务...');\n\n try {\n const task = await getTask(projectId, taskId);\n s.stop('获取成功');\n displayTaskDetail(task);\n p.outro('任务详情如上');\n } catch (err) {\n s.stop('获取失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`获取任务失败 (projectId: ${projectId}, taskId: ${taskId})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-find <taskId> 或 tt task-search <关键词> 验证任务')\n );\n }\n}\n\nasync function taskDoneCommand(\n projectId: string,\n taskId: string\n): Promise<void> {\n const s = p.spinner();\n s.start('正在完成任务...');\n\n try {\n await completeTask(projectId, taskId);\n s.stop('完成成功');\n p.outro(pc.green('任务已完成'));\n } catch (err) {\n s.stop('操作失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`任务完成失败 (projectId: ${projectId}, taskId: ${taskId})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-search 检查任务是否存在或已完成')\n );\n }\n}\n\nasync function taskDeleteCommand(\n projectId: string,\n taskId: string\n): Promise<void> {\n const confirmed = await p.confirm({\n message: `确认删除任务 ${pc.red(taskId)}?`,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.outro('已取消');\n return;\n }\n\n const s = p.spinner();\n s.start('正在删除任务...');\n\n try {\n await deleteTask(projectId, taskId);\n s.stop('删除成功');\n p.outro(pc.green('任务已删除'));\n } catch (err) {\n s.stop('删除失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`删除任务失败 (projectId: ${projectId}, taskId: ${taskId})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-get <projectId> <taskId> 验证任务是否存在')\n );\n }\n}\n\nasync function taskUpdateCommand(\n taskId: string,\n options: {\n project?: string;\n title?: string;\n content?: string;\n priority?: string;\n startDate?: string;\n dueDate?: string;\n }\n): Promise<void> {\n if (!options.project) {\n p.outro(pc.red('请使用 -p/--project 指定项目 ID'));\n return;\n }\n\n const params: UpdateTaskParams = {\n id: taskId,\n projectId: options.project,\n };\n if (options.title) params.title = options.title;\n if (options.content) params.content = options.content;\n if (options.priority) {\n const priority = parsePriority(options.priority);\n if (priority !== undefined) params.priority = priority;\n }\n if (options.startDate) params.startDate = normalizeTickTickDate(options.startDate);\n if (options.dueDate) params.dueDate = normalizeTickTickDate(options.dueDate);\n\n const s = p.spinner();\n s.start('正在更新任务...');\n\n try {\n const task = await updateTask(taskId, params);\n s.stop('更新成功');\n p.outro(pc.green(`任务「${task.title}」已更新`));\n } catch (err) {\n s.stop('更新失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`更新任务失败 (taskId: ${taskId}, projectId: ${options.project})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt task-find <taskId> 验证任务是否存在')\n );\n }\n}\n\nasync function taskMoveCommand(\n taskId: string,\n options: {\n from?: string;\n to?: string;\n }\n): Promise<void> {\n if (!options.from || !options.to) {\n p.outro(\n pc.red('请使用 -f/--from 和 -t/--to 指定源和目标项目 ID')\n );\n return;\n }\n\n const s = p.spinner();\n s.start('正在移动任务...');\n\n try {\n const result = await moveTasks([\n {\n fromProjectId: options.from,\n toProjectId: options.to,\n taskId,\n },\n ]);\n s.stop('移动成功');\n p.outro(\n pc.green(\n `任务已移动 (etag: ${result[0]?.etag ?? '-'})`\n )\n );\n } catch (err) {\n s.stop('移动失败');\n const msg = (err as Error).message;\n p.outro(\n pc.red(`移动任务失败 (taskId: ${taskId}, from: ${options.from}, to: ${options.to})\\n`) +\n pc.red(`${msg}\\n`) +\n pc.yellow('排查建议: 运行 tt project-list 验证项目 ID 是否有效')\n );\n }\n}\n\nasync function taskCompletedCommand(options: {\n project?: string;\n start?: string;\n end?: string;\n}): Promise<void> {\n const params: {\n projectIds?: string[];\n startDate?: string;\n endDate?: string;\n } = {};\n\n if (options.project) params.projectIds = [options.project];\n if (options.start) params.startDate = options.start;\n if (options.end) params.endDate = options.end;\n\n const s = p.spinner();\n s.start('正在获取已完成任务...');\n\n try {\n const tasks = await getCompletedTasks(params);\n s.stop(`找到 ${tasks.length} 个已完成任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow('没有找到已完成的任务'));\n return;\n }\n\n console.log('');\n displayTaskTable(tasks);\n console.log('');\n p.outro(`共 ${tasks.length} 个已完成任务`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskListCommand(options: {\n project?: string;\n start?: string;\n end?: string;\n status?: string;\n priority?: string;\n tag?: string;\n json?: boolean;\n}): Promise<void> {\n const params: {\n projectIds?: string[];\n startDate?: string;\n endDate?: string;\n status?: number[];\n priority?: number[];\n tag?: string[];\n } = {};\n\n if (options.project) params.projectIds = [options.project];\n if (options.start) params.startDate = options.start;\n if (options.end) params.endDate = options.end;\n if (options.status) {\n params.status = options.status.split(',').map((s) => parseInt(s, 10));\n }\n if (options.priority) {\n params.priority = options.priority\n .split(',')\n .map((s) => parseInt(s, 10));\n }\n if (options.tag) {\n params.tag = options.tag.split(',');\n }\n\n try {\n const tasks = await filterTasks(params);\n\n if (options.json) {\n console.log(JSON.stringify(tasks, null, 2));\n return;\n }\n\n const s = p.spinner();\n s.start('正在筛选任务...');\n s.stop(`找到 ${tasks.length} 个任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow('没有找到匹配的任务'));\n return;\n }\n\n console.log('');\n displayTaskTable(tasks);\n console.log('');\n p.outro(`共 ${tasks.length} 个任务`);\n } catch (err) {\n p.outro(pc.red((err as Error).message));\n }\n}\n\n// ─── 批量 / 高级命令 ────────────────────────────────\n\nasync function taskBatchAddCommand(\n jsonFile: string | undefined,\n options: { stdin?: boolean }\n): Promise<void> {\n let jsonStr: string;\n\n if (options.stdin || !jsonFile) {\n // 从 stdin 读取\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n jsonStr = Buffer.concat(chunks).toString('utf-8');\n } else {\n // 从文件读取\n const fs = await import('fs/promises');\n jsonStr = await fs.readFile(jsonFile, 'utf-8');\n }\n\n let tasks: CreateTaskParams[];\n try {\n tasks = JSON.parse(jsonStr);\n if (!Array.isArray(tasks)) {\n p.outro(pc.red('JSON 必须是任务数组'));\n return;\n }\n } catch {\n p.outro(pc.red('JSON 解析失败,请检查格式'));\n return;\n }\n\n // 规范化日期格式\n for (const task of tasks) {\n if (task.startDate) task.startDate = normalizeTickTickDate(task.startDate);\n if (task.dueDate) task.dueDate = normalizeTickTickDate(task.dueDate);\n }\n\n const s = p.spinner();\n s.start(`正在批量创建 ${tasks.length} 个任务...`);\n\n try {\n const result = await batchAddTasks(tasks);\n s.stop(`成功创建 ${result.count} 个任务`);\n console.log('');\n for (const task of tasks) {\n console.log(` ${pc.green('✓')} ${task.title}`);\n }\n console.log('');\n p.outro(`共创建 ${result.count} 个任务`);\n } catch (err) {\n s.stop('批量创建失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskBatchUpdateCommand(\n jsonFile: string | undefined,\n options: { stdin?: boolean }\n): Promise<void> {\n let jsonStr: string;\n\n if (options.stdin || !jsonFile) {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n jsonStr = Buffer.concat(chunks).toString('utf-8');\n } else {\n const fs = await import('fs/promises');\n jsonStr = await fs.readFile(jsonFile, 'utf-8');\n }\n\n let tasks: UpdateTaskParams[];\n try {\n tasks = JSON.parse(jsonStr);\n if (!Array.isArray(tasks)) {\n p.outro(pc.red('JSON 必须是任务数组'));\n return;\n }\n } catch {\n p.outro(pc.red('JSON 解析失败,请检查格式'));\n return;\n }\n\n // 规范化日期格式\n for (const task of tasks) {\n if (task.startDate) task.startDate = normalizeTickTickDate(task.startDate);\n if (task.dueDate) task.dueDate = normalizeTickTickDate(task.dueDate);\n }\n\n const s = p.spinner();\n s.start(`正在批量更新 ${tasks.length} 个任务...`);\n\n try {\n await batchUpdateTasks(tasks);\n s.stop(`成功更新 ${tasks.length} 个任务`);\n p.outro(pc.green(`已更新 ${tasks.length} 个任务`));\n } catch (err) {\n s.stop('批量更新失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskBatchDoneCommand(\n projectId: string,\n options: {\n taskIds?: string;\n all?: boolean;\n force?: boolean;\n }\n): Promise<void> {\n let ids: string[];\n\n if (options.all) {\n // 获取项目下所有未完成任务\n const s = p.spinner();\n s.start('正在获取项目任务...');\n const tasks = await filterTasks({ projectIds: [projectId], status: [0] });\n s.stop(`找到 ${tasks.length} 个未完成任务`);\n ids = tasks.map((t) => t.id);\n } else if (options.taskIds) {\n ids = options.taskIds.split(',').map((s) => s.trim());\n } else {\n p.outro(pc.red('请使用 --task-ids <id1,id2,...> 或 --all'));\n return;\n }\n\n if (ids.length === 0) {\n p.outro(pc.yellow('没有需要完成的任务'));\n return;\n }\n\n // 确认\n if (!options.force) {\n console.log('');\n console.log(` 将完成 ${ids.length} 个任务:`);\n for (const id of ids) {\n console.log(` ${pc.dim(id)}`);\n }\n console.log('');\n const confirmed = await p.confirm({\n message: `确认完成这 ${ids.length} 个任务?`,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.outro('已取消');\n return;\n }\n }\n\n const s = p.spinner();\n s.start(`正在完成 ${ids.length} 个任务...`);\n\n try {\n const result = await completeTasksInProject(projectId, ids);\n s.stop('操作完成');\n p.outro(\n pc.green(`成功 ${result.completed.length} 个`) +\n (result.failed.length > 0\n ? pc.red(`,失败 ${result.failed.length} 个`)\n : '')\n );\n } catch (err) {\n s.stop('操作失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskFindCommand(taskId: string): Promise<void> {\n const s = p.spinner();\n s.start('正在查找任务...');\n\n try {\n const task = await getTaskById(taskId);\n s.stop('查找成功');\n displayTaskDetail(task);\n p.outro('任务详情如上');\n } catch (err) {\n s.stop('查找失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskUndoneCommand(options: {\n start?: string;\n end?: string;\n query?: string;\n project?: string;\n json?: boolean;\n}): Promise<void> {\n let tasks: Task[];\n\n try {\n if (options.query) {\n // 预设查询\n tasks = await listUndoneTasksByTimeQuery(options.query);\n } else {\n // 自定义日期范围\n const params: { startDate?: string; endDate?: string; projectIds?: string[] } = {};\n if (options.start) params.startDate = options.start;\n if (options.end) params.endDate = options.end;\n if (options.project) params.projectIds = [options.project];\n tasks = await listUndoneTasksByDate(params);\n }\n\n if (options.json) {\n console.log(JSON.stringify(tasks, null, 2));\n return;\n }\n\n const s = p.spinner();\n s.start('正在获取未完成任务...');\n s.stop(`找到 ${tasks.length} 个未完成任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow('没有找到未完成任务'));\n return;\n }\n\n console.log('');\n displayTaskTable(tasks);\n console.log('');\n p.outro(`共 ${tasks.length} 个未完成任务`);\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\nasync function taskSearchCommand(keyword: string): Promise<void> {\n const s = p.spinner();\n s.start(`正在搜索 \"${keyword}\"...`);\n\n try {\n const tasks = await searchTask(keyword);\n s.stop(`找到 ${tasks.length} 个匹配任务`);\n\n if (tasks.length === 0) {\n p.outro(pc.yellow(`没有找到包含 \"${keyword}\" 的任务`));\n return;\n }\n\n console.log('');\n for (const task of tasks) {\n const icon = statusIcon(task.status);\n // 高亮关键词\n const title = task.title.replace(\n new RegExp(keyword, 'gi'),\n (m) => pc.bold(pc.yellow(m))\n );\n console.log(` ${icon} ${title} ${pc.dim(task.id)} ${pc.dim(task.projectId)}`);\n }\n console.log('');\n p.outro(`共 ${tasks.length} 个匹配`);\n } catch (err) {\n s.stop('搜索失败');\n p.outro(pc.red((err as Error).message));\n }\n}\n\n// ─── 注册命令 ────────────────────────────────────────\n\nexport function registerTaskCommands(cli: {\n command: (name: string, desc: string) => {\n option: (flag: string, desc: string) => {\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n}): void {\n cli\n .command('task-add [title]', '创建任务')\n .option('-p, --project <id>', '项目 ID')\n .option('--content <text>', '任务内容')\n .option('--priority <n>', '优先级: 0(无) / 1(低) / 3(中) / 5(高)')\n .option('--start-date <date>', '开始日期')\n .option('--due-date <date>', '截止日期')\n .option('--all-day', '全天任务')\n .action(taskAddCommand);\n\n cli\n .command('task-get <projectId> <taskId>', '获取任务详情')\n .action(taskGetCommand);\n\n cli\n .command('task-done <projectId> <taskId>', '完成任务')\n .action(taskDoneCommand);\n\n cli\n .command('task-delete <projectId> <taskId>', '删除任务')\n .action(taskDeleteCommand);\n\n cli\n .command('task-update <taskId>', '更新任务')\n .option('-p, --project <id>', '项目 ID(必填)')\n .option('--title <title>', '任务标题')\n .option('--content <text>', '任务内容')\n .option('--priority <n>', '优先级')\n .option('--start-date <date>', '开始日期')\n .option('--due-date <date>', '截止日期')\n .action(taskUpdateCommand);\n\n cli\n .command('task-move <taskId>', '移动任务到其他项目')\n .option('-f, --from <id>', '源项目 ID')\n .option('-t, --to <id>', '目标项目 ID')\n .action(taskMoveCommand);\n\n cli\n .command('task-completed', '查看已完成任务')\n .option('-p, --project <id>', '按项目筛选')\n .option('--start <date>', '开始日期')\n .option('--end <date>', '结束日期')\n .action(taskCompletedCommand);\n\n cli\n .command('task-list', '筛选任务')\n .option('-p, --project <id>', '按项目筛选')\n .option('--start <date>', '开始日期')\n .option('--end <date>', '结束日期')\n .option('--status <n>', '状态,逗号分隔: 0(待办),2(已完成)')\n .option('--priority <n>', '优先级,逗号分隔: 0,1,3,5')\n .option('--tag <tag>', '标签,逗号分隔')\n .option('--json', '输出 JSON 格式')\n .action(taskListCommand);\n\n // ─── 批量 / 高级命令 ────────────────────────────\n\n cli\n .command('task-batch-add [jsonFile]', '批量创建任务')\n .option('--stdin', '从标准输入读取 JSON')\n .action(taskBatchAddCommand);\n\n cli\n .command('task-batch-update [jsonFile]', '批量更新任务')\n .option('--stdin', '从标准输入读取 JSON')\n .action(taskBatchUpdateCommand);\n\n cli\n .command('task-batch-done <projectId>', '批量完成任务')\n .option('--task-ids <ids>', '任务 ID 列表,逗号分隔')\n .option('--all', '完成项目下所有未完成任务')\n .option('--force', '跳过确认')\n .action(taskBatchDoneCommand);\n\n cli\n .command('task-find <taskId>', '按 ID 查找任务(无需项目 ID)')\n .action(taskFindCommand);\n\n cli\n .command('task-undone', '查看未完成任务')\n .option('--start <date>', '开始日期')\n .option('--end <date>', '结束日期')\n .option('--query <preset>', '预设查询: today|tomorrow|last24hour|next24hour|last7day|next7day')\n .option('-p, --project <id>', '按项目筛选')\n .option('--json', '输出 JSON 格式')\n .action(taskUndoneCommand);\n\n cli\n .command('task-search <keyword>', '搜索任务')\n .action(taskSearchCommand);\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport { getUserPreference } from '../api/resources.js';\n\nasync function userPrefCommand(): Promise<void> {\n const s = p.spinner();\n s.start('正在获取用户偏好...');\n\n try {\n const pref = await getUserPreference();\n s.stop('获取成功');\n\n console.log('');\n if (pref.timeZone) console.log(` 时区: ${pref.timeZone}`);\n if (pref.dateFormat !== undefined)\n console.log(` 日期格式: ${pref.dateFormat}`);\n if (pref.language) console.log(` 语言: ${pref.language}`);\n if (pref.theme) console.log(` 主题: ${pref.theme}`);\n\n // 如果所有字段都为空,显示原始数据\n if (!pref.timeZone && pref.dateFormat === undefined && !pref.language && !pref.theme) {\n console.log(pc.dim(' (未获取到偏好信息,API 可能不支持此端点)'));\n }\n console.log('');\n p.outro('用户偏好如上');\n } catch (err) {\n s.stop('获取失败');\n p.outro(pc.red(`获取用户偏好失败: ${(err as Error).message}`));\n }\n}\n\n// ─── 注册命令 ────────────────────────────────────────\n\nexport function registerUserCommands(cli: {\n command: (name: string, desc: string) => {\n option: (flag: string, desc: string) => {\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n action: (fn: (...args: unknown[]) => Promise<void>) => unknown;\n };\n}): void {\n cli.command('user-pref', '查看用户偏好设置').action(userPrefCommand);\n}\n"],"mappings":"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","names":["text","path","text","s","p","pc","pc","s","cli","p","pc","priorityText","pc","statusIcon","s","fs","cli","p","pc","s","pc","cli"]}
|
package/package.json
CHANGED
package/src/commands/task.ts
CHANGED
|
@@ -533,6 +533,12 @@ async function taskBatchUpdateCommand(
|
|
|
533
533
|
return;
|
|
534
534
|
}
|
|
535
535
|
|
|
536
|
+
// 规范化日期格式
|
|
537
|
+
for (const task of tasks) {
|
|
538
|
+
if (task.startDate) task.startDate = normalizeTickTickDate(task.startDate);
|
|
539
|
+
if (task.dueDate) task.dueDate = normalizeTickTickDate(task.dueDate);
|
|
540
|
+
}
|
|
541
|
+
|
|
536
542
|
const s = p.spinner();
|
|
537
543
|
s.start(`正在批量更新 ${tasks.length} 个任务...`);
|
|
538
544
|
|
package/src/utils/format.ts
CHANGED
|
@@ -7,19 +7,27 @@
|
|
|
7
7
|
* TickTick API 要求: "2026-04-04T19:00:00.000+0800"(有毫秒,时区无冒号)
|
|
8
8
|
*
|
|
9
9
|
* 支持输入格式:
|
|
10
|
-
* - "2026-04-04T19:00
|
|
11
|
-
* - "2026-04-04T19:00:
|
|
10
|
+
* - "2026-04-04T19:00" → "2026-04-04T19:00:00.000+0800"(补秒+毫秒+时区)
|
|
11
|
+
* - "2026-04-04T19:00:00" → "2026-04-04T19:00:00.000+0800"(补毫秒+时区)
|
|
12
|
+
* - "2026-04-04T19:00:00+08:00" → "2026-04-04T19:00:00.000+0800"
|
|
13
|
+
* - "2026-04-04T19:00:00Z" → "2026-04-04T19:00:00.000+0000"
|
|
12
14
|
* - "2026-04-04T19:00:00.123+0800" → 保持不变
|
|
13
15
|
*/
|
|
14
16
|
export function normalizeTickTickDate(dateStr: string): string {
|
|
15
17
|
let result = dateStr;
|
|
16
|
-
//
|
|
18
|
+
// 1. 补秒: "T19:00" → "T19:00:00"(无秒数的情况)
|
|
19
|
+
result = result.replace(/(T\d{2}:\d{2})(?![.:]|\d)/, '$1:00');
|
|
20
|
+
// 2. 补时区: 无时区后缀时默认 +0800(先补时区,确保后续补毫秒能匹配到 [+-Z])
|
|
21
|
+
if (!/[Zz]$|[+\-]\d{2}:?\d{2}$/.test(result)) {
|
|
22
|
+
result += '+0800';
|
|
23
|
+
}
|
|
24
|
+
// 3. 补毫秒: "T19:00:00+" → "T19:00:00.000+"
|
|
17
25
|
if (!/T\d{2}:\d{2}:\d{2}\.\d{3}/.test(result)) {
|
|
18
26
|
result = result.replace(/(T\d{2}:\d{2}:\d{2})([+\-Z])/, '$1.000$2');
|
|
19
27
|
}
|
|
20
|
-
// 去时区冒号: "+08:00" → "+0800"
|
|
28
|
+
// 4. 去时区冒号: "+08:00" → "+0800"
|
|
21
29
|
result = result.replace(/([+\-])(\d{2}):(\d{2})$/, '$1$2$3');
|
|
22
|
-
// "Z" → "+0000"
|
|
30
|
+
// 5. "Z" → "+0000"
|
|
23
31
|
if (result.endsWith('Z')) {
|
|
24
32
|
result = result.slice(0, -1) + '+0000';
|
|
25
33
|
}
|