"use strict"; import mongoose from "mongoose"; /** * 陪诊记录Schema定义 * * 用于记录和管理陪诊服务全流程数据,包含以下主要分类: * - 基础信息:userId(订单提交用户) * - 患者信息:patient(姓名、电话、性别、年龄、身份证号) * - 陪诊服务:escort(服务ID、服务名称) * - 就诊信息:hospital(医院省份、名称、地址、科室、医生、病历号) * - 时间安排:schedule(预约时间、开始时间、结束时间、时长) * - 陪诊员信息:attendant(陪诊员ID、姓名) * - 费用信息:payment(总费用、已支付、支付状态) * - 备注信息:notes(患者备注、陪诊记录、就诊摘要) * - 状态信息:status(陪诊状态) * - 元数据:meta(创建时间、更新时间) */ const EscortRecordSchema = mongoose.Schema( { /** * 提交订单的用户ID(订单创建者) * @type {ObjectId} * @ref user */ userId: { type: mongoose.Schema.Types.ObjectId, ref: "user", index: true, comment: "提交订单用户ID" }, /** * 患者信息 - 就诊患者的基本信息 */ patient: { name: { type: String, default: "", comment: "患者姓名" }, mobile: { type: String, default: "", comment: "患者联系电话" }, sex: { type: String, enum: ["male", "female"], comment: "患者性别" }, age: { type: Number, default: 0, comment: "患者年龄" }, idnumber: { type: String, default: "", comment: "患者身份证号" }, }, /** * 陪诊服务信息 - 选择的陪诊服务配置 */ escort: { serviceId: { type: Number, default: -1, comment: "陪诊服务ID" }, serviceName: { type: String, default: "", comment: "陪诊服务名称" }, }, /** * 就诊信息 - 医院和科室相关信息 */ hospital: { province: { type: String, default: "", comment: "就诊医院省份" }, name: { type: String, default: "", comment: "就诊医院名称" }, address: { type: String, default: "", comment: "医院详细地址" }, department: { type: String, default: "", comment: "就诊科室" }, doctor: { type: String, default: "", comment: "就诊医生" }, medicalRecordNo: { type: String, default: "", comment: "病历号" }, }, /** * 时间信息 - 陪诊服务的时间安排 */ schedule: { date: { type: Date, default: Date.now, comment: "预约就诊日期" }, startTime: { type: String, default: "", comment: "陪诊实际开始时间" }, endTime: { type: String, default: "", comment: "陪诊实际结束时间" }, duration: { type: Number, default: 60, comment: "陪诊时长(分钟)" }, }, /** * 陪诊员信息 - 为患者提供服务的陪诊员 */ attendant: { id: { type: mongoose.Schema.Types.ObjectId, ref: "user", index: true, comment: "陪诊员用户ID" }, name: { type: String, default: "", comment: "陪诊员姓名" }, sex: { type: String, enum: ["none", "male", "female"], comment: "陪诊员性别" }, }, /** * 费用信息 - 服务费用相关 */ payment: { totalFee: { type: Number, default: 0, comment: "陪诊服务总费用(元)" }, paidFee: { type: Number, default: 0, comment: "已支付费用(元)" }, status: { type: String, enum: ["unpaid", "partial", "paid", "refunded"], default: "unpaid", comment: "支付状态:未支付、部分支付、已支付、已退款", }, }, /** * 备注信息 - 陪诊过程中的记录 */ notes: { patientNote: { type: String, default: "", comment: "患者备注/特殊需求" }, escortNote: { type: String, default: "", comment: "陪诊员服务记录" }, medicalSummary: { type: String, default: "", comment: "就诊摘要" }, }, /** * 陪诊状态 * - pending: 待确认 - 订单已创建,等待确认 * - confirmed: 已确认 - 订单已确认,等待服务 * - in_progress: 进行中 - 陪诊服务正在进行 * - completed: 已完成 - 陪诊服务已完成 * - cancelled: 已取消 - 订单已取消 */ status: { type: String, enum: ["pending", "confirmed", "in_progress", "completed", "cancelled"], default: "pending", comment: "陪诊状态:待确认、已确认、进行中、已完成、已取消", }, /** * 元数据 - 系统管理信息 */ meta: { createtime: { type: Date, default: Date.now, comment: "创建时间" }, updatetime: { type: Date, default: Date.now, comment: "更新时间" }, }, }, { minimize: false, strict: false, collection: "escort_record", timestamps: false, } ); /** * 根据用户ID查找陪诊记录 * * @param {ObjectId} userId - 订单提交用户ID * @param {Object} options - 查询选项 * @param {number} [options.page=1] - 页码 * @param {number} [options.pageSize=20] - 每页数量 * @param {string} [options.status] - 状态筛选 * @param {Function} [cb] - 可选的回调函数 * @returns {Promise} 陪诊记录列表(按预约日期倒序) */ EscortRecordSchema.statics.findRecordsByUser = async function (userId, options = {}, cb) { const { page = 1, pageSize = 20, status } = options; const filter = { userId }; if (status) { filter.status = status; } const skip = (page - 1) * pageSize; return await this.find(filter) .sort({ "schedule.date": -1 }) .skip(skip) .limit(pageSize) .exec(cb); }; /** * 根据陪诊员ID查找陪诊记录 * * @param {ObjectId} attendantId - 陪诊员用户ID * @param {Object} options - 查询选项 * @param {number} [options.page=1] - 页码 * @param {number} [options.pageSize=20] - 每页数量 * @param {string} [options.status] - 状态筛选 * @param {Function} [cb] - 可选的回调函数 * @returns {Promise} 陪诊记录列表(按预约日期倒序) */ EscortRecordSchema.statics.findRecordsByAttendant = async function (attendantId, options = {}, cb) { const { page = 1, pageSize = 20, status } = options; const filter = { "attendant.id": attendantId }; if (status) { filter.status = status; } const skip = (page - 1) * pageSize; return await this.find(filter) .sort({ "schedule.date": -1 }) .skip(skip) .limit(pageSize) .exec(cb); }; /** * 创建陪诊记录 * * @param {Object} record - 陪诊记录对象 * @param {Function} [cb] - 可选的回调函数 * @returns {Promise} 创建的陪诊记录 */ EscortRecordSchema.statics.createRecord = async function (record, cb) { record.meta = { createtime: Date.now(), updatetime: Date.now(), }; const newRecord = new this(record); return await newRecord.save(cb); }; /** * 更新陪诊记录 * * @param {ObjectId} id - 记录ID * @param {Object} update - 要更新的字段 * @param {Function} [cb] - 可选的回调函数 * @returns {Promise} 更新后的记录,失败返回null */ EscortRecordSchema.statics.updateRecord = async function (id, update, cb) { try { update["meta.updatetime"] = Date.now(); return await this.findByIdAndUpdate(id, { $set: update }, { new: true }, cb); } catch (error) { console.error("更新陪诊记录失败:", error); return null; } }; /** * 根据ID查找陪诊记录 * * @param {ObjectId} id - 记录ID * @param {Function} [cb] - 可选的回调函数 * @returns {Promise} 陪诊记录,不存在返回null */ EscortRecordSchema.statics.findRecordById = async function (id, cb) { return await this.findById(id).exec(cb); }; /** * 根据状态查找陪诊记录 * * @param {string} status - 状态 * @param {Object} options - 查询选项 * @param {number} [options.page=1] - 页码 * @param {number} [options.pageSize=20] - 每页数量 * @param {Function} [cb] - 可选的回调函数 * @returns {Promise} 陪诊记录列表 */ EscortRecordSchema.statics.findRecordsByStatus = async function (status, options = {}, cb) { const { page = 1, pageSize = 20 } = options; const skip = (page - 1) * pageSize; return await this.find({ status }) .sort({ "schedule.date": -1 }) .skip(skip) .limit(pageSize) .exec(cb); }; /** * 删除陪诊记录 * * @param {ObjectId} id - 记录ID * @param {Function} [cb] - 可选的回调函数 * @returns {Promise} 删除的记录,失败返回null */ EscortRecordSchema.statics.deleteRecord = async function (id, cb) { try { return await this.findByIdAndDelete(id, cb); } catch (error) { console.error("删除陪诊记录失败:", error); return null; } }; // ==================== 索引定义 ==================== /** * 用户ID索引 - 用于快速查询用户的陪诊记录 */ EscortRecordSchema.index({ userId: 1, "schedule.date": -1 }); /** * 陪诊员ID索引 - 用于快速查询陪诊员的服务记录 */ EscortRecordSchema.index({ "attendant.id": 1, status: 1, "schedule.date": -1 }); /** * 状态索引 - 用于快速按状态筛选记录 */ EscortRecordSchema.index({ status: 1 }); /** * 医院名称索引 - 用于快速按医院筛选记录 */ EscortRecordSchema.index({ "hospital.name": 1 }); export { EscortRecordSchema };