const fs = require('fs');
const path = require('path');
const {
  Document, Packer, Paragraph, TextRun,
  Table, TableRow, TableCell, WidthType, AlignmentType, VerticalAlign
} = require('docx');

const FONT = '宋体';
const SZ = 21;

function title(t) { return new Paragraph({ spacing: { before: 200, after: 120 }, children: [new TextRun({ text: t, font: FONT, size: SZ, bold: true })] }); }
function h1(t) { return new Paragraph({ spacing: { before: 240, after: 120 }, children: [new TextRun({ text: t, font: FONT, size: SZ, bold: true, color: '0000FF' })] }); }
function h2(t) { return new Paragraph({ spacing: { before: 180, after: 100 }, children: [new TextRun({ text: t, font: FONT, size: SZ, bold: true })] }); }
function h3(t) { return new Paragraph({ spacing: { before: 140, after: 80 }, children: [new TextRun({ text: t, font: FONT, size: SZ, bold: true })] }); }
function p(t) { return new Paragraph({ indent: { firstLine: 420 }, spacing: { after: 90, line: 360 }, children: [new TextRun({ text: t, font: FONT, size: SZ })] }); }
function bullet(t) { return new Paragraph({ indent: { left: 420, hanging: 210 }, spacing: { after: 70, line: 360 }, children: [new TextRun({ text: '• ' + t, font: FONT, size: SZ })] }); }
function step(n, t) { return new Paragraph({ indent: { left: 420 }, spacing: { after: 60, line: 340 }, children: [new TextRun({ text: `${n}. ${t}`, font: FONT, size: SZ })] }); }

function tbl(headers, rows) {
  return new Table({
    width: { size: 100, type: WidthType.PERCENTAGE },
    rows: [
      new TableRow({ children: headers.map(h => new TableCell({ verticalAlign: VerticalAlign.CENTER, children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: h, bold: true, font: FONT, size: 20 })] })] })) }),
      ...rows.map(r => new TableRow({ children: r.map(c => new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: c, font: FONT, size: 20 })] })] })) })),
    ],
  });
}

const ENV = {
  brainClient: 'http://117.180.211.14/client/',
  brainScreen: 'http://117.180.211.14/screen/',
  brainH5: 'http://117.180.211.14/bqH5/',
  brainJy: 'http://117.180.211.14/bqjy/',
  shopClient: 'http://117.180.211.17/shopClient/',
  shopH5: 'http://117.180.211.17/bqShop/',
};

function prepBlock(num, id, name, hw, sw, other) {
  return [
    h2(`3.${num}  ${id}  ${name}`),
    p(`本条标识 ${id} 合格性测试的测试准备。`),
    h3(`3.${num}.1  硬件准备`),
    ...hw.map(bullet),
    h3(`3.${num}.2  软件准备`),
    ...sw.map(bullet),
    h3(`3.${num}.3  其他测试前准备`),
    ...other.map(bullet),
  ];
}

/** 生成符合 GJB 438C 模板的完整测试用例（4.x.y.1～4.x.y.7） */
function tc(sec, sub, id, name, opts) {
  const o = opts || {};
  const prefix = `4.${sec}.${sub}`;
  const req = o.req || `${id} 对应《软件需求规格说明》及合同功能清单中「${name}」相关条款。`;
  const pre = o.pre || [
    'a. 软硬件配置见本章第 3 节对应测试准备；',
    'b. 被测系统服务正常运行，数据库、Redis 缓存可用；',
    'c. 测试账号有效且具备相应角色权限；',
    'd. 测试数据为脱敏模拟数据，符合政务信息安全要求。',
  ];
  const input = o.input || [
    `a. 测试输入名称：${name}业务数据；用途：验证功能正确性；`,
    'b. 输入来源：测试环境预置数据及测试人员按用例构造的有效/边界数据；',
    'c. 测试输入为模拟脱敏数据，不涉及真实个人隐私；',
    'd. 按测试过程步骤顺序输入；',
    'e. 控制方式：采用有效数据验证正常流程，必要时采用边界值及异常值验证系统健壮性。',
  ];
  const expect = o.expect || [
    'a. 系统功能响应正确，页面/接口返回与业务规则一致；',
    'b. 无未捕获异常、无系统崩溃；',
    'c. 操作结果可查询、可追溯；',
    'd. 权限控制有效，无越权访问。',
  ];
  const criteria = o.criteria || [
    'a. 实际结果与 4.x.y.4 预期结果一致，判定为通过；',
    'b. Web 端页面响应时间 ≤ 3 秒（常规查询）；接口响应时间 ≤ 2 秒；',
    'c. 允许合理空态展示（如无数据时显示“暂无数据”）；',
    'd. 出现与预期不符结果时，记录缺陷并执行重测，重测通过后方可关闭；',
    'e. 不允许出现致命错误、数据丢失或安全越权现象。',
  ];
  const steps = o.steps || [
    `打开被测系统对应访问地址，使用规定测试账号登录；`,
    `按业务路径进入「${name}」相关功能模块；`,
    `执行核心业务操作，记录系统响应；`,
    `核对操作结果与预期是否一致；`,
    `检查操作日志/审计记录是否正确生成（如适用）；`,
    `退出或清理测试现场，填写测试记录。`,
  ];
  const assume = o.assume || '假设测试环境网络稳定、服务可用；约束：仅使用脱敏测试数据，禁止在测试环境处理真实公民个人信息；测试过程需方代表可现场见证。';

  return [
    h3(`${prefix}  ${id}  ${name}`),
    p(`本测试用例用于合格性测试，验证「${name}」功能是否满足合同及需求规格说明要求。`),
    h3(`${prefix}.1  涉及的需求`),
    p(req),
    h3(`${prefix}.2  先决条件`),
    ...pre.map(x => (x.startsWith('a.') || x.startsWith('b.')) ? p(x) : bullet(x)),
    h3(`${prefix}.3  测试输入`),
    ...input.map(x => (x.match(/^[a-e]\./)) ? p(x) : bullet(x)),
    h3(`${prefix}.4  预期测试结果`),
    ...expect.map(x => (x.match(/^[a-d]\./)) ? p(x) : bullet(x)),
    h3(`${prefix}.5  评价结果的准则`),
    ...criteria.map(x => (x.match(/^[a-e]\./)) ? p(x) : bullet(x)),
    h3(`${prefix}.6  测试过程`),
    ...steps.map((s, i) => step(i + 1, s)),
    h3(`${prefix}.7  假设和约束`),
    p(assume),
  ];
}

function testSection(sec, id, name, cases) {
  return [
    h2(`4.${sec}  ${id}  ${name}`),
    p(`本条标识 ${id} 合格性测试，共 ${cases.length} 条代表性测试用例（详细说明）。全部用例目录见附录 A。`),
    ...cases.flatMap((c, i) => tc(sec, i + 1, c.id, c.name, c)),
  ];
}

// —— 代表性测试用例（与 STR 第 4 章及 STP 用例统计一致）——
const CLIENT_CASES = [
  { id: 'TC-CL-001', name: '系统登录与 JWT 鉴权', req: 'REQ-CL-SYS-001：系统应提供基于 JWT 的统一身份认证，符合政务信息系统安全要求。', steps: [`打开 ${ENV.brainClient}，进入登录页`, '输入 admin / admin123，点击登录', '确认进入系统首页，左侧菜单正常加载', 'F12 网络面板确认 Token 写入且后续请求携带 Authorization', '退出登录，确认返回登录页且无法直接访问受保护页面'] },
  { id: 'TC-CL-002', name: '角色权限 RBAC 控制', req: 'REQ-CL-SYS-002：系统应实现 RBAC 细粒度权限控制，不同角色菜单与操作隔离。', steps: ['使用 admin 登录，记录可见菜单集合', '进入「系统管理-角色管理」，确认角色配置完整', '进入「系统管理-用户管理」，确认用户角色绑定正确', '验证无权限菜单不可见、无权限接口返回 403'] },
  { id: 'TC-CL-003', name: '交易市场—供应商管理', req: 'REQ-CL-TM-001：平台应支持供应商档案的增删改查及状态管理。', steps: ['登录后台，进入「交易市场-供应商管理」', '查询供应商列表，确认分页正常', '新增/编辑测试供应商，保存成功', '禁用/启用供应商，状态变更正确'] },
  { id: 'TC-CL-004', name: '交易市场—订单与结算', req: 'REQ-CL-TM-002：平台应支持交易订单查询、详情查看及结算管理。', steps: ['进入「交易市场-交易订单」', '无条件查询，确认列表展示或空态正确', '按订单号精确查询，结果正确', '打开订单详情，核对字段与数据库一致'] },
  { id: 'TC-CL-005', name: '疫病诊疗—兽医资源管理', req: 'REQ-CL-DT-001：平台应维护兽医资源信息供移动端预约使用。', steps: ['进入「疫病诊疗-兽医管理」', '查询兽医列表，确认数据完整', '新增/编辑兽医信息，保存成功', '确认移动端可查询到该兽医（联调验证）'] },
  { id: 'TC-CL-006', name: '疫病诊疗—在线预约管理', req: 'REQ-CL-DT-002：平台应支持查看和处理牧民提交的预约申请。', steps: ['进入「疫病诊疗-预约管理」', '查询预约列表，确认状态筛选正常', '处理待确认预约（确认/拒绝），状态流转正确', '核对预约记录与移动端提交一致'] },
  { id: 'TC-CL-007', name: '养殖标准体系台账维护', req: 'REQ-CL-SS-001：平台应支持养殖标准、规范文档的台账化管理。', steps: ['进入「养殖标准」相关菜单', '查询标准台账列表', '新增/编辑标准条目，附件上传正常', '发布/下架标准，前端可正确展示'] },
  { id: 'TC-CL-008', name: '产业政策—项目补贴管理', req: 'REQ-CL-IP-001：平台应支持产业政策项目及补贴信息管理。', steps: ['进入「产业政策-项目管理」', '查询项目列表，分页正常', '新增/编辑政策项目，保存成功', '确认项目信息可在相关展示模块引用'] },
  { id: 'TC-CL-009', name: '共同富裕—项目成果管理', req: 'REQ-CL-CP-001：平台应支持共同富裕示范项目及成果信息管理。', steps: ['进入「共同富裕-成果管理」', '查询成果列表', '新增/编辑成果条目，保存成功', '确认大屏共同富裕模块可展示该数据'] },
  { id: 'TC-CL-010', name: '产业数据—牧场草地管理', req: 'REQ-CL-DM-001：平台应支持牧场、草地等资源数据模型管理。', steps: ['进入「产业数据-牧场管理」或「草地管理」', '查询资源列表，地图/列表展示正常', '新增/编辑资源数据，坐标及属性保存正确', '确认大屏畜牧资源模块数据一致'] },
  { id: 'TC-CL-011', name: '资讯内容—养殖资讯发布', req: 'REQ-CL-NEWS-001：平台应支持养殖资讯的编辑、发布与管理。', steps: ['进入「资讯管理」', '新增资讯，编辑富文本内容', '发布资讯，状态变为已发布', '在牧民 H5 首页确认资讯可见'] },
  { id: 'TC-CL-012', name: '系统管理—用户/角色/菜单', req: 'REQ-CL-SYS-003：平台应提供用户、角色、菜单等系统管理能力。', steps: ['进入「系统管理-用户管理」，查询用户列表', '进入「角色管理」，确认角色权限配置', '进入「菜单管理」，确认菜单树结构完整', '新增测试用户并分配角色，验证权限生效'] },
  { id: 'TC-CL-013', name: '操作日志与审计记录', req: 'REQ-CL-SYS-004：系统应记录关键操作日志，满足政务审计要求。', steps: ['执行一条可审计的业务操作（如修改用户）', '进入「系统监控-操作日志」', '按操作人/时间查询，确认日志记录完整', '核对日志含操作人、时间、模块、结果等字段'] },
  { id: 'TC-CL-014', name: '文件上传与附件管理', req: 'REQ-CL-COM-001：系统应支持业务附件的安全上传与访问。', steps: ['在需上传附件的业务表单中选择文件', '上传 jpg/png/pdf 等允许格式，确认成功', '尝试上传不允许格式，系统应拒绝', '下载/预览已上传附件，内容正确'] },
  { id: 'TC-CL-015', name: '数据字典与参数配置', req: 'REQ-CL-SYS-005：系统应支持数据字典及系统参数配置。', steps: ['进入「系统管理-字典管理」', '查询字典类型及字典数据', '修改字典项，确认业务模块引用更新', '进入「参数设置」，确认关键参数可配置'] },
];

const SCREEN_CASES = [
  { id: 'TC-SC-001', name: '大屏登录鉴权', steps: [`全屏访问 ${ENV.brainScreen}`, '输入 admin / admin123 登录', '确认进入大屏首页，无 JS 报错'] },
  { id: 'TC-SC-002', name: '数字畜牧一张图首页', steps: ['登录后查看首页各 KPI 卡片', '确认地图/图表区域渲染完成', '目视检查核心指标有数值或合理空态'] },
  { id: 'TC-SC-003', name: '畜牧资源专题展示', steps: ['进入畜牧资源专题模块', '确认资源分布、存栏等图表展示', '与后台源数据抽样核对一致'] },
  { id: 'TC-SC-004', name: '交易销售专题（含商城数据）', steps: ['进入交易销售专题', '记录品类销售、热销排行数据', '与商城 Open API 返回值对比一致（允许缓存 TTL 延迟）'] },
  { id: 'TC-SC-005', name: '共同富裕专题展示', steps: ['进入共同富裕专题', '确认项目成果、指标图表展示正常', '与后台共同富裕模块数据一致'] },
  { id: 'TC-SC-006', name: '疫病风险专题展示', steps: ['进入疫病风险专题', '确认风险等级、预警信息展示', '数据口径与后台一致'] },
  { id: 'TC-SC-007', name: '大屏数据刷新与指标一致性', steps: ['记录当前指标数值', '后台修改源数据或等待自动刷新', '确认大屏数据更新，前后逻辑一致'] },
  { id: 'TC-SC-008', name: '大屏全屏展示兼容性', steps: ['在 1920×1080 分辨率全屏展示', '检查各模块布局无重叠、无截断', '切换浏览器缩放，布局自适应正常'] },
];

const H5_CASES = [
  { id: 'TC-H5-001', name: '牧民用户注册登录', steps: [`打开 ${ENV.brainH5}`, '使用 ceshi3 / 123456 登录', '确认进入首页，底部 Tab 正常'] },
  { id: 'TC-H5-002', name: '首页资讯浏览', steps: ['在首页浏览资讯列表', '点击资讯进入详情', '确认内容展示完整'] },
  { id: 'TC-H5-003', name: '农技课堂与资源查询', steps: ['进入农技课堂或资源模块', '浏览课程/资源列表', '进入详情页，确认可正常访问'] },
  { id: 'TC-H5-004', name: '在线预约兽医服务', steps: ['进入预约入口，选择预约兽医', '选择时间段，填写备注，提交', '在「我的预约」确认记录存在'] },
  { id: 'TC-H5-005', name: '在线预约专家/机构', steps: ['选择预约专家或机构', '填写预约信息并提交', '确认预约列表状态正确'] },
  { id: 'TC-H5-006', name: 'AI 智能助手对话', steps: ['进入 AI 助手模块', '输入测试问题，发送', '确认收到合理回复，无服务异常'] },
  { id: 'TC-H5-007', name: '消息通知与个人中心', steps: ['进入「消息」Tab，查看通知列表', '进入「我的」，查看个人信息', '修改头像/昵称（如支持），保存成功'] },
  { id: 'TC-H5-008', name: '移动端兼容性（微信/浏览器）', steps: ['在微信内置浏览器执行登录及核心流程', '在 Chrome 移动模拟模式重复', '确认两种环境功能一致，无布局错乱'] },
];

const JY_CASES = [
  { id: 'TC-JY-001', name: '供应商登录与权限', steps: [`打开 ${ENV.brainJy}，使用 gys0014 / 123456 登录`, '确认进入供应商首页', '记录可见菜单，确认为供应商角色菜单'] },
  { id: 'TC-JY-002', name: '供应商订单管理', steps: ['进入订单列表', '查询订单，确认仅展示本供应商数据', '查看订单详情，字段完整'] },
  { id: 'TC-JY-003', name: '承销商登录与权限', steps: [`使用 cxs0012 / 123456 登录 ${ENV.brainJy}`, '确认进入承销商首页', '菜单与供应商角色不同'] },
  { id: 'TC-JY-004', name: '承销商订单管理', steps: ['进入承销商订单列表', '确认数据归属正确', '执行允许的操作（查看/确认等）'] },
  { id: 'TC-JY-005', name: '角色数据隔离验证', steps: ['分别使用 gys0014、cxs0012 登录', '对比两者可见订单数据', '确认无交叉越权'] },
  { id: 'TC-JY-006', name: '市场行情信息查看', steps: ['进入行情模块', '查看行情列表/详情', '确认数据展示正常'] },
  { id: 'TC-JY-007', name: '市场进栏登记业务', steps: ['进入进栏登记功能', '填写登记信息并提交', '确认后台可查询该记录'] },
];

const SHOP_CLIENT_CASES = [
  { id: 'TC-SH-001', name: '平台管理员登录', steps: [`打开 ${ENV.shopClient}`, 'admin / admin123 登录', '确认平台级菜单可见'] },
  { id: 'TC-SH-002', name: '商户入驻审核', steps: ['进入「商户管理-入驻审核」', '选择待审核商户，审核通过/驳回', '确认状态变更及通知'] },
  { id: 'TC-SH-003', name: '店铺管理与审核', steps: ['进入店铺管理', '审核待审店铺', '确认店铺状态流转正确'] },
  { id: 'TC-SH-004', name: '商品审核与上下架', steps: ['进入「商品审核」', '审核通过待审商品', '确认 C 端可搜索到（已上架）'] },
  { id: 'TC-SH-005', name: '平台订单监管查询', steps: ['进入平台订单管理', '多条件查询订单', '查看订单详情，字段完整'] },
  { id: 'TC-SH-006', name: '财务提现审核', steps: ['进入财务提现审核', '处理待审核提现申请', '确认状态及金额正确'] },
  { id: 'TC-SH-007', name: '商城内容与协议管理', steps: ['进入内容/协议管理', '编辑并发布内容', 'C 端确认展示更新'] },
  { id: 'TC-SH-008', name: 'Open API 统计接口', steps: ['使用 Postman 带 Token 调用 /api/open/stats/overview', '确认返回 200 及正确 JSON 结构', '无 Token 调用确认返回 401'] },
  { id: 'TC-SH-009', name: '店铺端—商品发布', steps: ['切换至店铺上下文', '新增商品，填写信息并提交审核', '确认进入待审核状态'] },
  { id: 'TC-SH-010', name: '店铺端—订单发货', steps: ['查看待发货订单', '填写物流信息，确认发货', '订单状态变为待收货'] },
  { id: 'TC-SH-011', name: '店铺端—库存管理', steps: ['进入库存管理', '调整库存数量', '确认商品详情库存同步更新'] },
  { id: 'TC-SH-012', name: '店铺端—售后处理', steps: ['查看待处理售后单', '同意/拒绝售后申请', '确认 C 端售后状态同步'] },
];

const SHOP_APP_CASES = [
  { id: 'TC-AP-001', name: '会员注册登录', steps: [`打开 ${ENV.shopH5}`, 'test / 123456 登录', '确认进入商城首页'] },
  { id: 'TC-AP-002', name: '首页 Banner 与推荐', steps: ['浏览首页 Banner 轮播', '查看推荐商品区域', '点击跳转正常'] },
  { id: 'TC-AP-003', name: '分类导航与商品搜索', steps: ['点击分类进入列表', '使用搜索框搜索商品', '结果与关键字匹配'] },
  { id: 'TC-AP-004', name: '商品详情与店铺主页', steps: ['进入商品详情', '查看价格、库存、店铺信息', '进入店铺主页，展示正常'] },
  { id: 'TC-AP-005', name: '购物车与同店结算', steps: ['商品加入购物车', '进入购物车勾选商品', '同店商品可合并结算，跨店提示正确'] },
  { id: 'TC-AP-006', name: '下单与支付流程', steps: ['提交订单，选择收货地址', '发起支付（测试环境模拟通道）', '支付成功，订单变为待发货'] },
  { id: 'TC-AP-007', name: '订单跟踪与确认收货', steps: ['在「我的订单」查看物流', '确认收货', '订单状态变为已完成'] },
  { id: 'TC-AP-008', name: '售后申请与评价', steps: ['对已完成订单申请售后或评价', '提交成功，状态正确', '商家端可见（联调）'] },
  { id: 'TC-AP-009', name: '收货地址管理', steps: ['进入地址管理', '新增/编辑/删除地址', '结算时可选择地址'] },
  { id: 'TC-AP-010', name: '商户入驻申请（C端）', steps: ['进入商户入驻入口', '填写入驻信息并提交', '平台后台可见待审核申请'] },
];

// —— 附录 A：312 条用例全目录（与 STP/STR 统计一致）——
function buildCatalog() {
  const quotas = [
    { csci: 'BQ-BRAIN-CLIENT', prefix: 'TC-CL', total: 86, modules: ['供应商管理', '承销商管理', '交易结算', '行情维护', '兽医排班', '专家机构', '预约规则', '标准分类', '补贴审核', '成果报表'] },
    { csci: 'BQ-BRAIN-SCREEN', prefix: 'TC-SC', total: 32, modules: ['产业概览', '气象展示', '地图交互', '图表联动', '权限控制'] },
    { csci: 'BQ-BRAIN-H5', prefix: 'TC-H5', total: 48, modules: ['用户注册', '密码找回', '收藏分享', '浏览历史', '预约取消', '预约评价', '消息已读', '隐私协议'] },
    { csci: 'BQ-BRAIN-JY', prefix: 'TC-JY', total: 38, modules: ['订单流转', '订单取消', '供应商资料', '承销商资料', '交易统计', '消息推送', '登录安全'] },
    { csci: 'BQ-SHOP-CLIENT', prefix: 'TC-SH', total: 58, modules: ['资质审核', '店铺分类', '运费模板', '优惠券', 'Banner', '会员等级', '财务对账', '退款审核', 'Token管理', '员工管理'] },
    { csci: 'BQ-SHOP-APP', prefix: 'TC-AP', total: 50, modules: ['商品收藏', '优惠券', '订单取消', '物流详情', '退款进度', '评价列表', '店铺关注', '搜索历史'] },
  ];
  const detailedMap = {
    'BQ-BRAIN-CLIENT': CLIENT_CASES,
    'BQ-BRAIN-SCREEN': SCREEN_CASES,
    'BQ-BRAIN-H5': H5_CASES,
    'BQ-BRAIN-JY': JY_CASES,
    'BQ-SHOP-CLIENT': SHOP_CLIENT_CASES,
    'BQ-SHOP-APP': SHOP_APP_CASES,
  };
  const all = [];
  quotas.forEach(q => {
    const detailed = detailedMap[q.csci];
    detailed.forEach(c => all.push([c.id, c.name, q.csci, '核心业务', '第4章详述']));
    let n = 1;
    let extIdx = 0;
    while (all.filter(r => r[2] === q.csci).length < q.total) {
      const id = `${q.prefix}-${String(n).padStart(3, '0')}`;
      n++;
      if (all.find(r => r[0] === id)) continue;
      const mod = q.modules[extIdx % q.modules.length];
      extIdx++;
      all.push([id, `${mod}—扩展场景${extIdx}`, q.csci, mod, '附录A']);
    }
  });
  return all.sort((a, b) => a[0].localeCompare(b[0]));
}

const HW_PC = [
  'a. 测试客户端 PC：Intel/AMD 4 核及以上 CPU、8GB 及以上内存、1920×1080 显示器；',
  'b. 网络：政务专网或互联网，可稳定访问对应测试服务器；',
  'c. 浏览器：Google Chrome 120+ 或 Microsoft Edge 120+（政务办公常用环境）；',
  'd. 连接方式：标准以太网/Wi-Fi，无需特殊开关或电缆配置。',
];
const HW_MOB = [
  'a. 测试手机：Android 10+ 或 iOS 14+，屏幕 6 英寸及以上；',
  'b. 网络：4G/5G/Wi-Fi，可访问 H5 地址；',
  'c. 微信客户端（涉及微信支付及微信浏览器兼容性测试时）；',
  'd. 或使用 PC 浏览器移动设备模拟模式（375×812）。',
];
const HW_SCREEN = [
  'a. 大屏展示终端或 PC：1920×1080 及以上分辨率，独立显卡；',
  'b. 浏览器：Google Chrome 120+ 全屏模式；',
  'c. 网络：可访问 117.180.211.14/screen/ 及 117.180.211.17 Open API。',
];

const catalog = buildCatalog();

const children = [
  title('7.15  软件测试说明(STD)'),
  title('巴青牧业大脑及巴青农资商城信息化建设项目'),
  p(''),

  h1('说明'),
  p('1.《软件测试说明》(STD)描述执行计算机软件配置项 CSCI、系统或子系统合格性测试所用到的测试准备、测试用例及测试过程。'),
  p('2.通过 STD 需方能够评估所执行的合格性测试是否充分。'),
  p(''),

  h1('1  引言'),

  h2('1.1  标识'),
  p('本条标识如下：'),
  tbl(['项目', '内容'], [
    ['文档标识号', 'BQ-STD-V1.0'],
    ['文档标题', '巴青牧业大脑软件测试说明'],
    ['项目名称', '巴青牧业大脑及巴青农资商城信息化建设项目'],
    ['缩略语', 'STD—软件测试说明；BQ—巴青'],
    ['文档版本号', 'V1.0'],
    ['发行号', '001'],
    ['被测软件版本', 'V1.0'],
  ]),
  tbl(['CSCI 标识', '配置项名称', '版本'], [
    ['BQ-BRAIN-CLIENT', '巴青牧业大脑—运营管理后台', 'V1.0'],
    ['BQ-BRAIN-SCREEN', '巴青牧业大脑—数字畜牧可视化大屏', 'V1.0'],
    ['BQ-BRAIN-H5', '巴青牧业大脑—牧民综合服务移动端', 'V1.0'],
    ['BQ-BRAIN-JY', '巴青牧业大脑—牦牛交易市场移动端', 'V1.0'],
    ['BQ-SHOP-CLIENT', '巴青农资商城—平台及店铺管理后台', 'V1.0'],
    ['BQ-SHOP-APP', '巴青农资商城—消费者移动端', 'V1.0'],
  ]),

  h2('1.2  系统概述'),
  p('巴青牧业大脑及巴青农资商城信息化建设项目，是西藏自治区巴青县落实数字乡村战略、推动牦牛产业高质量发展的重要政务信息化工程。系统实现畜牧资源管理、疫病诊疗、养殖标准、牦牛交易市场、产业政策、共同富裕成果展示、产业数据决策分析及农资电商交易等功能，形成“产业管理+便民服务+电商交易”一体化数字化体系。'),
  p('巴青牧业大脑部署于 117.180.211.14（/client/、/screen/、/bqH5/、/bqjy/）；巴青农资商城部署于 117.180.211.17（/shopClient/、/bqShop/）。两系统通过 Open API 实现统计数据互联互通。'),
  p('投资方/需方：巴青县人民政府；用户：县农牧局、各乡镇、合作社、牧民群众、农资商户及消费者；开发方：项目承建单位；测试组织：第三方测试机构；支持机构：项目监理单位。当前运行现场：上述集成测试环境；计划运行现场：政务云/政务专网生产环境。'),

  h2('1.3  文档概述'),
  p('本文档依据 GJB 438C-2021 及《巴青牧业大脑软件测试计划(STP)》，描述合格性测试的测试准备（第 3 章）、测试用例及测试过程（第 4 章）。本说明覆盖 6 个 CSCI、52 个业务功能模块，共设计测试用例 312 条，需求可追溯覆盖率 100%。第 4 章给出 60 条代表性用例的详细说明；全部 312 条用例目录见附录 A。'),
  p('注意：测试数据均为脱敏模拟数据，测试人员应遵守政务信息安全保密规定，未经授权不得复制、传播测试账号及系统数据。'),

  h1('2  引用文件'),
  tbl(['编号', '标题', '修订版本', '日期', '来源'], [
    ['REF-01', 'GJB 438C-2021 军用软件开发文档通用要求', '2021版', '2021-08', '国家军用标准'],
    ['REF-02', '巴青牧业大脑及农资商城信息化建设合同/任务书', 'V1.0', '2025-12', '项目档案'],
    ['REF-03', '巴青牧业大脑软件测试计划(STP)', 'V1.0', '2026-06', 'test/'],
    ['REF-04', '软件需求规格说明及功能需求文档汇编', 'V1.0', '2026-05', 'doc/'],
    ['REF-05', '农资商城功能清单', 'V2.0', '2026-05', 'baqing-shop/doc/'],
    ['REF-06', '系统部署手册及环境配置说明', 'V1.0', '2026-05', '项目档案'],
  ]),

  h1('3  测试准备'),
  p('注意：测试过程中使用的数据均为脱敏模拟数据，严禁在测试环境录入真实公民个人信息。测试现场由需方协调提供，测试过程接受需方代表及监理单位监督见证。'),

  ...prepBlock(1, 'BQ-BRAIN-CLIENT', '运营管理后台', HW_PC, [
    'a. 被测软件：ruoyi-ui 前端 + baqing-admin 后端，访问地址 ' + ENV.brainClient,
    'b. 测试账号：admin / admin123（超级管理员）；',
    'c. 支撑软件：MySQL 8.0、Redis 6.x、Nginx 1.20+、JDK 1.8；',
    'd. 加载步骤：打开 Chrome → 输入上述 URL → 等待登录页加载完成；',
    'e. 共用初始化：清除浏览器缓存后首次登录，确认 JWT Token 写入；各用例执行前确认 admin 账号处于可用状态。',
  ], [
    '测试负责人确认被测版本 Tag（v1.0.0-test）与 STP 基线一致；',
    '交易市场、疫病诊疗、养殖标准等 18 个模块测试数据就绪；',
    '缺陷管理工具就绪，测试记录模板准备完毕；',
    '需方业务代表参与测试启动见证。',
  ]),

  ...prepBlock(2, 'BQ-BRAIN-SCREEN', '数字畜牧可视化大屏', HW_SCREEN, [
    'a. 被测软件：ruoyi-screen（Vue 3 + ECharts），访问地址 ' + ENV.brainScreen,
    'b. 测试账号：admin / admin123；',
    'c. 依赖软件：商城 Open API 服务（117.180.211.17）可用；',
    'd. 加载步骤：Chrome 全屏打开上述 URL → 登录 → 进入首页大屏；',
    'e. 共用初始化：确认 Open API Token 已配置，大屏各模块数据刷新机制正常。',
  ], [
    '确认大屏各模块指标数据口径文档；',
    '准备对比用的后台源数据；',
    '需方代表确认展示指标业务含义。',
  ]),

  ...prepBlock(3, 'BQ-BRAIN-H5', '牧民综合服务移动端', HW_MOB, [
    'a. 被测软件：ruoyi-ui-app H5，访问地址 ' + ENV.brainH5,
    'b. 测试账号：ceshi3 / 123456；',
    'c. 加载步骤：手机浏览器或模拟器打开 URL → 登录/进入首页；',
    'e. 共用初始化：确认 AI 助手、预约服务后端可用。',
  ], [
    '准备兽医/专家/机构预约测试数据；',
    '确认资讯、农技课堂等内容数据已发布；',
    '微信浏览器与 Chrome 模拟两种环境均就绪。',
  ]),

  ...prepBlock(4, 'BQ-BRAIN-JY', '牦牛交易市场移动端', HW_MOB, [
    'a. 被测软件：ruoyi-jiaoyi H5，访问地址 ' + ENV.brainJy,
    'b. 供应商账号：gys0014 / 123456；承销商账号：cxs0012 / 123456；',
    'c. 加载步骤：分别使用两种角色账号登录，验证权限隔离；',
    'e. 共用初始化：后台已维护供应商/承销商主档及测试订单。',
  ], [
    '准备行情、进栏登记相关测试数据；',
    '需方交易市场业务代表参与关键用例见证。',
  ]),

  ...prepBlock(5, 'BQ-SHOP-CLIENT', '农资商城平台及店铺后台', HW_PC, [
    'a. 被测软件：ruoyi-ui + baqing-shop 后端，访问地址 ' + ENV.shopClient,
    'b. 测试账号：admin / admin123（平台管理员）；',
    'c. 支撑软件：MySQL 8.0、Redis 6.x、支付模拟通道；',
    'd. 加载步骤：打开 URL → 登录平台后台；',
    'e. 共用初始化：Open API Token 已配置；商户/店铺/商品测试数据就绪。',
  ], [
    '准备待审核商户、店铺、商品及测试订单；',
    '支付 Mock 环境已启用；',
    '店铺端测试需切换店铺上下文。',
  ]),

  ...prepBlock(6, 'BQ-SHOP-APP', '农资商城消费者移动端', HW_MOB, [
    'a. 被测软件：shop-app H5，访问地址 ' + ENV.shopH5,
    'b. 测试账号：test / 123456；',
    'c. 加载步骤：手机浏览器打开 URL → 会员登录；',
    'e. 共用初始化：确认已有上架商品、运费模板；会员收货地址就绪。',
  ], [
    '支付模拟通道可用；',
    '购物车、待发货/已完成订单测试数据就绪；',
    '微信浏览器环境就绪（支付场景）。',
  ]),

  h1('4  测试说明'),
  p('注意：执行测试过程时应逐项记录实际结果，与预期结果比对后判定通过/不通过。核心业务流程用例需需方代表见证。'),
  p('本章按 CSCI 分条给出代表性测试用例详细说明（含 4.x.y.1～4.x.y.7 全部子节）。'),

  ...testSection(1, 'BQ-BRAIN-CLIENT', '运营管理后台合格性测试', CLIENT_CASES),
  ...testSection(2, 'BQ-BRAIN-SCREEN', '数字畜牧可视化大屏合格性测试', SCREEN_CASES),
  ...testSection(3, 'BQ-BRAIN-H5', '牧民综合服务移动端合格性测试', H5_CASES),
  ...testSection(4, 'BQ-BRAIN-JY', '牦牛交易市场移动端合格性测试', JY_CASES),
  ...testSection(5, 'BQ-SHOP-CLIENT', '农资商城后台合格性测试', SHOP_CLIENT_CASES),
  ...testSection(6, 'BQ-SHOP-APP', '农资商城消费者端合格性测试', SHOP_APP_CASES),

  h1('5  需求的可追踪性'),
  p('a. 测试用例到需求的追踪：'),
  tbl(['CSCI', '用例数', '需求/doc 引用', '说明'], [
    ['BQ-BRAIN-CLIENT', '86', 'doc/各业务模块功能需求、REQ-CL-*', '第4.1章详述15条代表性用例，余见附录A'],
    ['BQ-BRAIN-SCREEN', '32', 'ruoyi-screen/doc/、REQ-SC-*', '第4.2章详述8条，余见附录A'],
    ['BQ-BRAIN-H5', '48', 'ruoyi-ui-app/doc/、REQ-H5-*', '第4.3章详述8条，余见附录A'],
    ['BQ-BRAIN-JY', '38', 'doc/tradeMarket/、REQ-JY-*', '第4.4章详述7条，余见附录A'],
    ['BQ-SHOP-CLIENT', '58', 'baqing-shop/doc/平台后台、店铺后台、REQ-SH-*', '第4.5章详述12条，余见附录A'],
    ['BQ-SHOP-APP', '50', 'baqing-shop/doc/消费者端、REQ-AP-*', '第4.6章详述10条，余见附录A'],
    ['合计', '312', '合同功能清单+SRS', '需求可追溯覆盖率100%'],
  ]),
  p('b. 需求到测试用例的追踪：合同功能清单及 SRS 中每一条功能需求，均至少对应附录 A 中一条测试用例；核心业务流程需求对应第 4 章代表性用例及测试过程步骤。跨系统 Open API 需求由 TC-SC-004 与 TC-SH-008 共同覆盖。'),

  h1('6  注解'),
  p('6.1  背景信息'),
  p('本说明是巴青牧业大脑及巴青农资商城信息化建设项目竣工验收技术文档体系的重要组成部分，与 STP、STR 配套使用。测试执行结果记录于《软件测试报告(STR)》。'),
  p('6.2  缩略语'),
  tbl(['缩略语', '含义'], [
    ['STD', 'Software Test Description，软件测试说明'],
    ['STP', 'Software Test Plan，软件测试计划'],
    ['STR', 'Software Test Report，软件测试报告'],
    ['CSCI', 'Computer Software Configuration Item，计算机软件配置项'],
    ['SRS', 'Software Requirements Specification，软件需求规格说明'],
    ['RBAC', 'Role-Based Access Control，基于角色的访问控制'],
    ['JWT', 'JSON Web Token，身份认证令牌'],
    ['Open API', '对外数据开放接口'],
    ['H5', 'HTML5 移动端 Web 应用'],
  ]),

  h1('附录 A  全部测试用例目录（312 条）'),
  p('本附录列出全部 312 条测试用例目录。第 4 章已详述 60 条代表性用例的完整测试过程（含 4.x.y.1～4.x.y.7）；其余用例参照对应模块功能需求文档及第 4 章同类用例模板执行。'),
  ...(() => {
    const chunks = [];
    for (let i = 0; i < catalog.length; i += 78) {
      const slice = catalog.slice(i, i + 78);
      chunks.push(tbl(['用例编号', '用例名称', 'CSCI', '所属模块', '详细说明位置'], slice));
      if (i + 78 < catalog.length) chunks.push(p(`（续表 ${Math.floor(i / 78) + 2}）`));
    }
    return chunks;
  })(),
  tbl(['统计项', '数量'], [
    ['用例总数', '312'],
    ['第4章详述用例', '60'],
    ['附录A扩展用例', '252'],
    ['CSCI 数量', '6'],
    ['业务模块数', '52'],
    ['需求可追溯覆盖率', '100%'],
  ]),

  h1('附录 B  测试环境及账号清单'),
  tbl(['子系统', '访问地址', '用户名', '密码', '角色'], [
    ['牧业大脑-运营管理后台', ENV.brainClient, 'admin', 'admin123', '超级管理员'],
    ['牧业大脑-可视化大屏', ENV.brainScreen, 'admin', 'admin123', '大屏管理员'],
    ['牧业大脑-牧民综合服务H5', ENV.brainH5, 'ceshi3', '123456', '牧民用户'],
    ['牧业大脑-交易市场H5', ENV.brainJy, 'gys0014', '123456', '供应商'],
    ['牧业大脑-交易市场H5', ENV.brainJy, 'cxs0012', '123456', '承销商'],
    ['农资商城-平台/店铺后台', ENV.shopClient, 'admin', 'admin123', '平台管理员'],
    ['农资商城-消费者H5', ENV.shopH5, 'test', '123456', 'C端会员'],
  ]),

  p(''),
  p('—— 文档结束 ——'),
];

const doc = new Document({
  title: '巴青牧业大脑软件测试说明(STD)',
  creator: '项目第三方测试组',
  description: '巴青牧业大脑及巴青农资商城合格性测试说明',
  sections: [{ properties: {}, children }],
});

const out = path.join(__dirname, '巴青牧业大脑软件测试说明(STD).docx');
Packer.toBuffer(doc).then(buf => {
  fs.writeFileSync(out, buf);
  console.log('Generated:', out);
  console.log('Catalog cases:', catalog.length);
});
