import { DBModel } from "../models/index.js"; import ResponseUtil from "../utils/responseUtil.js"; /** * 陪诊师公示:面向 C 端患者的公开信息展示 * * 依据 GB/T 47801—2026 4.2.1.5「陪同人员信息公示机制」组织字段: * 基本信息 —— 培训记录、服务年限、累计服务次数 * 专业技能 —— 擅长服务场景、特殊技能(语言) * * 两条红线: * 1. 白名单式输出,绝不返回手机号 / 身份证号 / 证书编号原文; * 「资质已核验」只对外给布尔值,不给编号 * 2. 不输出评分。attendantInfo.rating 是默认 5.0 的裸值, * 后端尚无评价数据来源,公示它等于无依据背书 */ class HandlerEmployee { // 姓名脱敏:只留姓 + 「陪诊师」,不给全名,降低私下联系(跳单)的可能 static maskName(name) { const trimmed = String(name || "").trim(); if (!trimmed) return "陪诊师"; return trimmed.slice(0, 1) + "陪诊师"; } // 白名单式脱敏:逐字段挑选,避免 employee 文档整体外泄 static toPublicAttendant(employee) { const profile = employee.profile || {}; const work = employee.work || {}; const info = employee.attendantInfo || {}; return { id: employee._id, name: HandlerEmployee.maskName(profile.name), avatar: profile.avatar || "", sex: profile.sex || "", workYears: work.workYears || 0, qualificationVerified: !!work.qualification, specialties: info.specialties || [], serviceAreas: info.serviceAreas || [], languages: info.languages || [], orderCount: info.orderCount || 0, introduction: employee.introduction || "", }; } // 公开的陪诊师列表。 // 与 /service、/agreement 等公示类资源一致,不加 requireAuth—— // 公示信息本身不敏感,且避免登录态异常导致页面空白 async getAttendants(ctx) { try { const page = parseInt(ctx.request.query.page) || 1; const pageSize = parseInt(ctx.request.query.pageSize) || 50; // 只取在职陪诊员。 // 排序不按 attendantInfo.rating(无可信来源),改按服务年限 / 累计接单数 const list = await DBModel.Employee.find({ role: "attendant", status: "active", }) .sort({ "work.workYears": -1, "attendantInfo.orderCount": -1 }) .skip((page - 1) * pageSize) .limit(pageSize) .exec(); return ResponseUtil.success( ctx, { attendants: list.map(HandlerEmployee.toPublicAttendant) }, "查询成功" ); } catch (err) { return ResponseUtil.internalError(ctx, err.message); } } } export { HandlerEmployee };