106 lines
5.3 KiB
JavaScript
106 lines
5.3 KiB
JavaScript
import Router from "koa-router";
|
||
import { HandlerEscortRecord } from "../handler/escort_record.js";
|
||
import { HandlerHealthProfile } from "../handler/health_profile.js";
|
||
import { HandlerResource } from "../handler/resource.js";
|
||
import { HandlerEmployee } from "../handler/employee.js";
|
||
import ResponseUtil from "../utils/responseUtil.js";
|
||
import { getUserByToken } from "../utils/user_service.js";
|
||
|
||
/**
|
||
* 鉴权中间件:校验 token 并将用户信息挂到 ctx.state.user
|
||
* token→user 结果带 5 分钟进程内缓存(见 utils/user_service.js)
|
||
*/
|
||
async function requireAuth(ctx, next) {
|
||
const token = ctx.header["token"] || ctx.header["authorization"] || ctx.request.query?.token;
|
||
if (!token) {
|
||
ResponseUtil.unauthorized(ctx, "缺少token");
|
||
return;
|
||
}
|
||
|
||
const user = await getUserByToken(token);
|
||
if (!user) {
|
||
ResponseUtil.unauthorized(ctx, "登录已失效");
|
||
return;
|
||
}
|
||
ctx.state.user = user;
|
||
await next();
|
||
}
|
||
|
||
/**
|
||
* 管理员校验中间件:仅管理端小程序绑定的账号可访问管理端接口
|
||
* 与 WS 管理端 agent 的校验口径保持一致(app 中是否存在 wxapp-escort-admin)
|
||
*/
|
||
async function requireAdmin(ctx, next) {
|
||
const user = ctx.state.user;
|
||
if (!user || !user.app || !("wxapp-escort-admin" in user.app)) {
|
||
ResponseUtil.forbidden(ctx, "无管理员权限");
|
||
return;
|
||
}
|
||
await next();
|
||
}
|
||
|
||
function printRoutes(stack) {
|
||
for (const layer of stack) {
|
||
if (layer.path) {
|
||
const methods = layer.methods.filter(m => m !== '_all');
|
||
methods.forEach(m => console.log(` [${m.toUpperCase()}] ${layer.path}`));
|
||
}
|
||
}
|
||
}
|
||
|
||
function registerRoutes(app) {
|
||
const router = new Router({ prefix: '/health' });
|
||
|
||
const handlerEscortRecord = new HandlerEscortRecord();
|
||
const handlerHealthProfile = new HandlerHealthProfile();
|
||
const handlerResource = new HandlerResource();
|
||
const handlerEmployee = new HandlerEmployee();
|
||
|
||
// 敏感数据路由需要登录后访问
|
||
router.get("/escort-record/my", requireAuth, handlerEscortRecord.getMyRecords.bind(handlerEscortRecord));
|
||
router.get("/escort-record/attendant", requireAuth, handlerEscortRecord.getAttendantRecords.bind(handlerEscortRecord));
|
||
// 全量查询属管理端能力,必须管理员
|
||
router.get("/escort-record", requireAuth, requireAdmin, handlerEscortRecord.getRecords.bind(handlerEscortRecord));
|
||
router.get("/escort-record/:id", requireAuth, handlerEscortRecord.getRecordById.bind(handlerEscortRecord));
|
||
router.post("/escort-record", requireAuth, handlerEscortRecord.createRecord.bind(handlerEscortRecord));
|
||
router.put("/escort-record/:id", requireAuth, handlerEscortRecord.updateRecord.bind(handlerEscortRecord));
|
||
router.patch("/escort-record/:id/status", requireAuth, handlerEscortRecord.updateStatus.bind(handlerEscortRecord));
|
||
router.delete("/escort-record/:id", requireAuth, handlerEscortRecord.deleteRecord.bind(handlerEscortRecord));
|
||
|
||
// C 端"我的健康档案":userId 一律取自 token,必须注册在 /health-profile/:id 之前
|
||
router.get("/health-profile/mine", requireAuth, handlerHealthProfile.getMyProfiles.bind(handlerHealthProfile));
|
||
router.post("/health-profile/mine", requireAuth, handlerHealthProfile.createMyProfile.bind(handlerHealthProfile));
|
||
router.get("/health-profile/mine/:id", requireAuth, handlerHealthProfile.getMyProfileById.bind(handlerHealthProfile));
|
||
router.put("/health-profile/mine/:id", requireAuth, handlerHealthProfile.updateMyProfile.bind(handlerHealthProfile));
|
||
router.delete("/health-profile/mine/:id", requireAuth, handlerHealthProfile.deleteMyProfile.bind(handlerHealthProfile));
|
||
|
||
// 以下为管理端档案接口(C 端一律走 /mine),必须管理员
|
||
router.get("/health-profile", requireAuth, requireAdmin, handlerHealthProfile.getProfiles.bind(handlerHealthProfile));
|
||
router.get("/health-profile/:id", requireAuth, requireAdmin, handlerHealthProfile.getProfileById.bind(handlerHealthProfile));
|
||
router.post("/health-profile", requireAuth, requireAdmin, handlerHealthProfile.createProfile.bind(handlerHealthProfile));
|
||
router.put("/health-profile/:id", requireAuth, requireAdmin, handlerHealthProfile.updateProfile.bind(handlerHealthProfile));
|
||
router.delete("/health-profile/:id", requireAuth, requireAdmin, handlerHealthProfile.deleteProfile.bind(handlerHealthProfile));
|
||
|
||
router.get("/service", handlerResource.getServices.bind(handlerResource));
|
||
router.get("/agreement", handlerResource.getAgreement.bind(handlerResource));
|
||
router.get("/hospital-info", handlerResource.getHospitalInfo.bind(handlerResource));
|
||
router.get("/hospital-ranking", handlerResource.getHospitalRanking.bind(handlerResource));
|
||
router.get("/department-rankings", handlerResource.getDepartmentRankings.bind(handlerResource));
|
||
router.get("/ai-quick-questions", handlerResource.getAiQuickQuestions.bind(handlerResource));
|
||
|
||
// 陪诊师公示(公开):面向 C 端患者展示陪同人员信息。
|
||
// 与上面的 /service、/agreement 一样属公示类资源,不加 requireAuth
|
||
router.get("/attendant", handlerEmployee.getAttendants.bind(handlerEmployee));
|
||
// 单个陪诊师详情。必须注册在 /attendant 之后,避免被它抢匹配
|
||
router.get("/attendant/:id", handlerEmployee.getAttendantById.bind(handlerEmployee));
|
||
|
||
app.use(router.routes());
|
||
app.use(router.allowedMethods());
|
||
|
||
console.log('API Routes:');
|
||
printRoutes(router.stack);
|
||
|
||
return router;
|
||
}
|
||
|
||
export default registerRoutes; |