const BASE = 'http://localhost:8080/api/v1' async function api(path, options = {}) { const res = await fetch(`${BASE}${path}`, options) const text = await res.text() let json = null try { json = JSON.parse(text) } catch { /* empty body */ } if (!res.ok) { throw new Error(`${options.method || 'GET'} ${path} -> ${res.status} ${text}`) } return json } function auth(token) { return { 'content-type': 'application/json', authorization: `Bearer ${token}` } } async function main() { const login = await api('/auth/login', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ username: 'admin', password: 'Admin@2026' }), }) const token = login.data.accessToken console.log('登录成功\n') const daysFromNow = (n) => { const d = new Date(Date.now() + n * 86400000) const pad = (x) => String(x).padStart(2, '0') return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` } const issues = [ { title: '【演示】登录页面白屏无法进入系统', description: '输入正确账号密码点击登录后,页面白屏无任何响应,控制台报 React 渲染错误。', status: 'draft', priority: 'high', phase: '测试阶段', subProject: '前端开发', category: '界面问题', impactLevel: '严重', impactScope: '影响全部用户', assigneeId: 2, reviewerId: 1, departmentId: 2, deadline: daysFromNow(7), }, { title: '【演示】CSV 导出中文乱码', description: '导出指摘列表 CSV 后,用 Excel 打开中文标题显示为乱码,需在文件头加 BOM。', status: 'pending', priority: 'medium', phase: '编码阶段', subProject: '后端开发', category: '功能缺陷', impactLevel: '一般', impactScope: '仅本页面', assigneeId: 3, reviewerId: 1, departmentId: 3, deadline: daysFromNow(5), }, { title: '【演示】Dashboard 统计图表不渲染', description: '工作台首页图表区域空白,ECharts 容器高度为 0,需确认图表初始化时机。', status: 'in_progress', priority: 'high', phase: '测试阶段', subProject: '前端开发', category: '界面问题', impactLevel: '较大', impactScope: '影响部分模块', assigneeId: 2, reviewerId: 1, departmentId: 2, deadline: daysFromNow(3), attachments: [{ name: 'screenshot-dashboard-blank.png', content: 'PNG 占位:Dashboard 图表白屏截图(演示数据)' }], }, { title: '【演示】Agent 审批卡点击无响应', description: 'Agent 执行后弹出审批卡,点击批准/驳回按钮无反应,接口 500。', status: 'in_progress', priority: 'urgent', phase: '编码阶段', subProject: '后端开发', category: '功能缺陷', impactLevel: '严重', impactScope: '影响全部用户', assigneeId: 3, reviewerId: 1, departmentId: 4, deadline: daysFromNow(2), agent: { goal: '查找登录白屏相似案例并生成对应方案', action: 'approve-pending' }, }, { title: '【演示】通知铃铛未读数量不更新', description: '收到状态流转通知后,右上角铃铛未读数仍为 0,需刷新才显示。', status: 'pending_confirm', priority: 'medium', phase: '上线阶段', subProject: '通知模块', category: '功能缺陷', impactLevel: '一般', impactScope: '仅本页面', assigneeId: 3, reviewerId: 1, departmentId: 2, deadline: daysFromNow(6), }, { title: '【演示】附件下载返回 404', description: '点击附件下载按钮,接口返回 404,MinIO 对象与数据库记录不一致。', status: 'closed', priority: 'low', phase: '测试阶段', subProject: '后端开发', category: '功能缺陷', impactLevel: '一般', impactScope: '仅本页面', assigneeId: 2, reviewerId: 1, departmentId: 2, deadline: daysFromNow(-3), attachments: [{ name: 'error-log.txt', content: '2026-08-01 10:23:45 ERROR download attachment 404' }], }, { title: '【演示】逾期未处理的紧急指摘', description: '该指摘已超过整改截止日期仍未处理,需催办担当者。', status: 'pending', priority: 'urgent', phase: '上线阶段', subProject: '数据库', category: '数据问题', impactLevel: '严重', impactScope: '影响全部用户', assigneeId: 3, reviewerId: 1, departmentId: 3, deadline: daysFromNow(-1), }, { title: '【演示】Agent 方案被驳回回退人工', description: 'Agent 生成方案后经审批被驳回,回退人工模式由担当者手动处理。', status: 'in_progress', priority: 'high', phase: '编码阶段', subProject: '前端开发', category: '需求变更', impactLevel: '较大', impactScope: '影响部分模块', assigneeId: 2, reviewerId: 1, departmentId: 4, deadline: daysFromNow(4), agent: { goal: '自动生成附件下载修复方案', action: 'reject' }, }, { title: '【演示】CSV 导出大数据量性能', description: '导出 1 万条指摘时接口耗时超过 30 秒,前端超时。', status: 'closed', priority: 'medium', phase: '编码阶段', subProject: '后端开发', category: '性能问题', impactLevel: '较大', impactScope: '影响部分模块', assigneeId: 3, reviewerId: 1, departmentId: 3, deadline: daysFromNow(-2), }, { title: '【演示】多状态流转完整链路验证', description: '该指摘完整走完 草稿→待对应→对应中→待确认→已关闭 全链路,用于演示状态机与流转日志。', status: 'closed', priority: 'medium', phase: '需求阶段', subProject: '业务验证', category: '需求变更', impactLevel: '一般', impactScope: '仅本页面', assigneeId: 2, reviewerId: 1, departmentId: 3, deadline: daysFromNow(-5), }, ] const FLOW = { draft: [], pending: ['pending'], in_progress: ['pending', 'in_progress'], pending_confirm: ['pending', 'in_progress', 'pending_confirm'], closed: ['pending', 'in_progress', 'pending_confirm', 'closed'], } const created = [] for (const [i, it] of issues.entries()) { const num = String(i + 1).padStart(2, '0') const { status, attachments, agent, ...payload } = it const res = await api('/issues', { method: 'POST', headers: auth(token), body: JSON.stringify(payload), }) const issue = res.data console.log(`[${num}] 创建 ${issue.issueNo} - ${issue.title}`) for (const s of FLOW[status] || []) { await api(`/issues/${issue.id}/status`, { method: 'PATCH', headers: auth(token), body: JSON.stringify({ status: s, remark: '演示流转' }), }) console.log(` 流转 -> ${s}`) } if (attachments && attachments.length) { for (const a of attachments) { const fd = new FormData() fd.append('file', new Blob([a.content], { type: 'text/plain' }), a.name) await api(`/issues/${issue.id}/attachments`, { method: 'POST', headers: { authorization: `Bearer ${token}` }, body: fd }) console.log(` 上传附件 ${a.name}`) } } if (agent) { const exec = await api('/agent/execute', { method: 'POST', headers: auth(token), body: JSON.stringify({ issueId: issue.id, goal: agent.goal }), }) const planId = exec.data.planId console.log(` Agent 执行 -> plan#${planId}`) if (agent.action === 'approve-pending') { console.log(` Agent 审批保持 pending(演示审批中)`) } else if (agent.action === 'reject') { await api(`/agent/approval/${planId}/reject`, { method: 'POST', headers: auth(token), body: JSON.stringify({ comment: '方案不适用,请人工处理' }), }) console.log(` Agent 已驳回 plan#${planId}`) } } created.push(issue) } console.log(`\n完成:共创建 ${created.length} 条演示数据`) } main().catch((e) => { console.error('失败:', e.message); process.exit(1) })