运行手册
本文档是项目运行的唯一事实来源。后续操作优先按本文档执行,若实际命令与文档不符,先验证真实行为,再更新本文档。
技术栈
| 层级 |
技术 |
版本 |
| 前端框架 |
React + TypeScript |
^19 |
| 构建工具 |
Vite |
^6 |
| 后端框架 |
Express.js |
^4 |
| 数据库 |
SQLite(WAL 模式) |
内置 node:sqlite |
| 包管理器 |
npm |
>= 18 |
| 图表库 |
Recharts |
latest |
| 图标库 |
Lucide React |
latest |
| 进程管理 |
concurrently |
latest |
| 测试框架 |
Jest + Supertest |
latest |
本地环境
环境变量
| 变量 |
默认值 |
说明 |
API_PORT |
8787 |
后端 API 监听端口 |
端口清单
依赖服务
安装
若 node_modules 已存在,跳过此步骤。
开发命令
全栈启动(推荐)
同时启动:
- API 服务(
node --watch server/index.js)监听 127.0.0.1:8787
- 前端 Vite 开发服务器监听
localhost:5173,API 请求代理至 8787
单独启动
后端启动(独立,不热重载)
构建
- 前端编译输出至
dist/
- TypeScript 类型检查:
tsc -b
- 两者均通过才算构建成功
测试
运行 server/tests/integration.test.cjs,覆盖所有 API 端点的集成测试。测试使用独立临时数据库,测试完成后自动清理。
数据库
数据文件
- 开发数据库:
data/reporter-station.db(SQLite)
- WAL 文件:
data/reporter-station.db-wal(Write-Ahead Log)
- SHM 文件:
data/reporter-station.db-shm
迁移管理
使用 migrations/_runner.js 管理所有 schema 变更:
迁移按文件名数字前缀顺序执行(001~009)。新增迁移时,使用下一个可用数字前缀。
数据库结构
work_records(V0.1)
| 字段 |
类型 |
说明 |
id |
TEXT PK |
主键,格式 WK-YYYYMMDD-XXXX |
title |
TEXT |
工作标题 |
type |
TEXT |
工作类型(文字稿件/视频供稿/...) |
reporter |
TEXT |
记者姓名 |
station |
TEXT |
所属记者站 |
occurred_date |
TEXT |
发生/刊发日期 |
platform |
TEXT |
媒体/平台 |
status |
TEXT |
状态(draft/station_review/headquarters_review/returned/archived) |
score |
INTEGER |
考核得分(可为 null) |
description |
TEXT |
工作说明 |
review_note |
TEXT |
审核意见 |
updated_at |
TEXT |
更新时间 |
audit_logs(V0.1)
| 字段 |
类型 |
说明 |
id |
INTEGER PK |
自增主键 |
record_id |
TEXT FK |
关联 work_records.id |
actor_role |
TEXT |
操作者角色 |
actor_name |
TEXT |
操作者姓名 |
action |
TEXT |
操作类型(submit/pass/return) |
from_status |
TEXT |
原状态 |
to_status |
TEXT |
新状态 |
score |
INTEGER |
打分 |
note |
TEXT |
意见 |
created_at |
TEXT |
操作时间 |
people(V0.1.1)
| 字段 |
类型 |
说明 |
id |
INTEGER PK |
自增主键 |
code |
TEXT UNIQUE |
人员编码 |
name |
TEXT |
姓名 |
role |
TEXT |
角色(headquarters/station/reporter) |
title |
TEXT |
职务 |
phone |
TEXT |
联系电话 |
station |
TEXT |
所属记者站 |
status |
TEXT |
状态(active/inactive) |
joined_at |
TEXT |
入职日期 |
stations(V0.1.1)
| 字段 |
类型 |
说明 |
id |
INTEGER PK |
自增主键 |
code |
TEXT UNIQUE |
记者站编码 |
name |
TEXT |
记者站名称 |
region |
TEXT |
所属区域 |
established_at |
TEXT |
成立日期 |
notices(V0.1.1)
| 字段 |
类型 |
说明 |
id |
INTEGER PK |
自增主键 |
title |
TEXT |
通知标题 |
content |
TEXT |
通知内容 |
type |
TEXT |
类型(notice/circular/guide) |
priority |
TEXT |
优先级(normal/important/urgent) |
created_by |
TEXT |
创建人 |
created_at |
TEXT |
创建时间 |
expire_at |
TEXT |
过期时间 |
rules(V0.2)
| 字段 |
类型 |
说明 |
id |
INTEGER PK |
自增主键 |
code |
TEXT UNIQUE |
规则编码 |
name |
TEXT |
规则名称 |
description |
TEXT |
规则说明 |
period_type |
TEXT |
周期类型(quarterly/custom) |
period_start |
TEXT |
周期开始日期 |
period_end |
TEXT |
周期结束日期 |
status |
TEXT |
状态(draft/active/archived) |
version |
INTEGER |
版本号 |
parent_id |
INTEGER FK |
父版本 ID |
created_by |
TEXT |
创建人 |
created_at |
TEXT |
创建时间 |
updated_at |
TEXT |
更新时间 |
rule_items(V0.2)
| 字段 |
类型 |
说明 |
id |
INTEGER PK |
自增主键 |
rule_id |
INTEGER FK |
关联 rules.id |
category |
TEXT |
指标类别(quantity/quality/efficiency/compliance) |
name |
TEXT |
指标名称 |
metric_key |
TEXT |
指标键名 |
weight |
REAL |
权重 |
min_score |
REAL |
最低分 |
max_score |
REAL |
最高分 |
formula_type |
TEXT |
计算公式类型 |
formula_params |
TEXT |
公式参数(JSON) |
display_order |
INTEGER |
排序 |
enabled |
INTEGER |
是否启用 |
scores(V0.2)
| 字段 |
类型 |
说明 |
id |
INTEGER PK |
自增主键 |
rule_id |
INTEGER FK |
关联 rules.id |
station |
TEXT |
站点名称 |
period |
TEXT |
考核周期 |
period_type |
TEXT |
周期类型 |
total_score |
REAL |
综合得分 |
quality_score |
REAL |
质量分 |
quantity_score |
REAL |
数量分 |
efficiency_score |
REAL |
时效分 |
compliance_score |
REAL |
合规分 |
items |
TEXT |
明细(JSON 数组) |
computed_at |
TEXT |
计算时间 |
API 接口文档
认证
所有 API 请求需携带 HTTP header:
核心接口
| 方法 |
路径 |
角色 |
说明 |
| GET |
/api/health |
公开 |
健康检查 |
| GET |
/api/records |
全部 |
查询工作记录(按角色隔离) |
| POST |
/api/records |
reporter/station |
新建记录 |
| PATCH |
/api/records/:id/review |
station/hq |
审核(通过/退回) |
| GET |
/api/records/:id/audit |
全部 |
流转记录(按角色隔离) |
人员与站点(V0.1.1)
| 方法 |
路径 |
角色 |
说明 |
| GET |
/api/people |
全部 |
查询人员列表 |
| POST |
/api/people |
station |
新建人员 |
| PATCH |
/api/people/:id |
station/hq |
编辑人员 |
| GET |
/api/stations |
全部 |
查询记者站列表 |
| POST |
/api/stations |
hq |
新建记者站 |
通知公告(V0.1.1)
| 方法 |
路径 |
角色 |
说明 |
| GET |
/api/notices |
全部 |
查询通知列表 |
| POST |
/api/notices |
hq |
发布通知 |
| POST |
/api/notices/:id/read |
全部 |
标记已读 |
| GET |
/api/notices/unread-count |
全部 |
未读数量 |
统计(V0.1.1)
| 方法 |
路径 |
角色 |
说明 |
| GET |
/api/stats/overview |
全部 |
总览统计(站点角色仅限本站) |
| GET |
/api/stats/records |
hq |
记录统计(支持按周期/站点/类型筛选) |
| GET |
/api/stats/scores |
hq |
评分统计(支持按周期/站点筛选) |
考核规则(V0.2)
| 方法 |
路径 |
角色 |
说明 |
| GET |
/api/rules |
hq |
查询规则列表(支持 status 筛选) |
| GET |
/api/rules/:id |
hq |
查询规则详情(含指标项) |
| POST |
/api/rules |
hq |
创建规则(含指标项) |
| PATCH |
/api/rules/:id |
hq |
编辑规则(草稿状态) |
| POST |
/api/rules/:id/activate |
hq |
激活规则 |
评分(V0.2)
| 方法 |
路径 |
角色 |
说明 |
| GET |
/api/scores |
hq |
查询评分列表(支持 period/station 筛选) |
| GET |
/api/scores/:id |
hq |
查询评分详情(含明细) |
| POST |
/api/scores/compute |
hq |
触发评分计算 |
请求示例
常见问题
Q1:端口 8787 被占用
Q2:端口 5173 被占用
Q3:SQLite WAL 文件导致"database is locked"
- 通常因多个进程同时写入
- 解决:确保只有一个服务实例运行
- WAL 文件异常时,删除
.db-wal 和 .db-shm 后重启服务
Q4:前端热重载不生效
- 确认 Vite dev server 正在运行(看终端输出 "ready in xxx ms")
- 清除浏览器缓存或使用无痕模式
Q5:迁移执行失败
Q6:TypeScript 类型错误
Q7:npm run build 失败
- 先确认 TypeScript 无误:
npx tsc -b
- 查看 Vite 构建输出中的具体错误
- 检查是否有新增依赖未安装
Q8:seed 数据消失
- 原因:
work_records 表已有数据时,seed 逻辑不执行
- 解决:手动删除数据库文件后重启服务,或使用
node migrations/_runner.js reset
后续开发参考
- 需求文档:
pmdocs/0-req-RSMS.md
- 产品文档:
pmdocs/1-prd-RSMS.md
- 任务文档:
pmdocs/2-task-RSMS.md
- 架构决策:
pmdocs/adr/
- 需求变更:
pmdocs/changes/
- 原始需求参考:
req.md