start
This commit is contained in:
304
models/schema/escort_record.js
Normal file
304
models/schema/escort_record.js
Normal file
@@ -0,0 +1,304 @@
|
||||
"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<Array>} 陪诊记录列表(按预约日期倒序)
|
||||
*/
|
||||
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<Array>} 陪诊记录列表(按预约日期倒序)
|
||||
*/
|
||||
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<Object>} 创建的陪诊记录
|
||||
*/
|
||||
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<Object|null>} 更新后的记录,失败返回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<Object|null>} 陪诊记录,不存在返回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<Array>} 陪诊记录列表
|
||||
*/
|
||||
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<Object|null>} 删除的记录,失败返回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 };
|
||||
246
models/schema/org.js
Normal file
246
models/schema/org.js
Normal file
@@ -0,0 +1,246 @@
|
||||
"use strict";
|
||||
|
||||
import mongoose from "mongoose";
|
||||
|
||||
/**
|
||||
* 医院Schema定义
|
||||
*
|
||||
* 包含5个主要分类块:基本信息、位置信息、联系方式、服务信息和元数据。
|
||||
* 用于记录和管理医院信息,支持陪诊服务的医院选择功能。
|
||||
*/
|
||||
const HospitalSchema = mongoose.Schema(
|
||||
{
|
||||
// 基本信息 - 医院的核心标识信息
|
||||
basic: {
|
||||
name: { type: String, required: true, comment: "医院名称" },
|
||||
shortName: { type: String, default: "", comment: "医院简称" },
|
||||
pinyin: { type: String, default: "", comment: "医院名称拼音,用于搜索" },
|
||||
pinyinFL: { type: String, default: "", comment: "医院名称拼音首字母,用于搜索" },
|
||||
level: {
|
||||
type: String,
|
||||
enum: ["tertiary", "secondary", "primary", "other"],
|
||||
default: "other",
|
||||
comment: "医院等级:三级、二级、一级、其他",
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: ["general", "specialized", "traditional_chinese", "integrated", "other"],
|
||||
default: "general",
|
||||
comment: "医院类型:综合医院、专科医院、中医医院、中西医结合医院、其他",
|
||||
},
|
||||
description: { type: String, default: "", comment: "医院简介" },
|
||||
logo: { type: String, default: "", comment: "医院Logo地址" },
|
||||
},
|
||||
|
||||
// 位置信息 - 医院的地理位置
|
||||
location: {
|
||||
province: { type: String, default: "", comment: "省份" },
|
||||
city: { type: String, default: "", comment: "城市" },
|
||||
district: { type: String, default: "", comment: "区县" },
|
||||
address: { type: String, default: "", comment: "详细地址" },
|
||||
longitude: { type: Number, default: 0, comment: "经度" },
|
||||
latitude: { type: Number, default: 0, comment: "纬度" },
|
||||
},
|
||||
|
||||
// 联系方式 - 医院的联系信息
|
||||
contact: {
|
||||
phone: { type: String, default: "", comment: "联系电话" },
|
||||
emergencyPhone: { type: String, default: "", comment: "急诊电话" },
|
||||
website: { type: String, default: "", comment: "官方网站" },
|
||||
email: { type: String, default: "", comment: "电子邮箱" },
|
||||
},
|
||||
|
||||
// 服务信息 - 医院提供的服务
|
||||
service: {
|
||||
features: [{ type: String, comment: "特色服务" }],
|
||||
isEnabled: { type: Boolean, default: true, comment: "是否启用" },
|
||||
sortOrder: { type: Number, default: 0, comment: "排序优先级" },
|
||||
},
|
||||
|
||||
// 科室信息 - 医院科室详细信息
|
||||
departments: [
|
||||
{
|
||||
name: { type: String, required: true, comment: "科室名称" },
|
||||
pinyin: { type: String, default: "", comment: "科室名称拼音" },
|
||||
pinyinFL: { type: String, default: "", comment: "科室名称拼音首字母" },
|
||||
location: { type: String, default: "", comment: "科室位置(几号楼,几层)" },
|
||||
phone: { type: String, default: "", comment: "科室联系电话" },
|
||||
description: { type: String, default: "", comment: "科室简介" },
|
||||
doctors: [
|
||||
{
|
||||
name: { type: String, required: true, comment: "医生姓名" },
|
||||
title: {
|
||||
type: String,
|
||||
enum: ["resident", "attending", "deputy_chief", "chief", "other"],
|
||||
default: "attending",
|
||||
comment: "医生职称:住院医师、主治医师、副主任医师、主任医师、其他",
|
||||
},
|
||||
specialty: { type: String, default: "", comment: "专业擅长" },
|
||||
avatar: { type: String, default: "", comment: "医生头像" },
|
||||
},
|
||||
],
|
||||
isEnabled: { type: Boolean, default: true, comment: "是否启用" },
|
||||
sortOrder: { type: Number, default: 0, comment: "排序优先级" },
|
||||
},
|
||||
],
|
||||
|
||||
// 元数据 - 系统管理信息
|
||||
meta: {
|
||||
createtime: { type: Date, default: Date.now, comment: "创建时间" },
|
||||
updatetime: { type: Date, default: Date.now, comment: "更新时间" },
|
||||
},
|
||||
},
|
||||
{
|
||||
minimize: false,
|
||||
strict: false,
|
||||
collection: "hospital",
|
||||
timestamps: false,
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据名称查找医院
|
||||
*
|
||||
* @param {String} name - 医院名称(支持模糊搜索)
|
||||
* @param {Object} options - 查询选项 { page, pageSize }
|
||||
* @param {Function} cb - 可选的回调函数
|
||||
* @returns {Promise<Array>} 医院列表
|
||||
*/
|
||||
HospitalSchema.statics.findByName = async function (name, options = {}, cb) {
|
||||
const { page = 1, pageSize = 20 } = options;
|
||||
const filter = {
|
||||
$or: [
|
||||
{ "basic.name": new RegExp(name, "i") },
|
||||
{ "basic.shortName": new RegExp(name, "i") },
|
||||
{ "basic.pinyin": new RegExp(name.toLowerCase(), "i") },
|
||||
{ "basic.pinyinFL": new RegExp(name.toUpperCase(), "i") },
|
||||
],
|
||||
"service.isEnabled": true,
|
||||
};
|
||||
const skip = (page - 1) * pageSize;
|
||||
return await this.find(filter)
|
||||
.sort({ "service.sortOrder": 1, "basic.name": 1 })
|
||||
.skip(skip)
|
||||
.limit(pageSize)
|
||||
.exec(cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据城市查找医院
|
||||
*
|
||||
* @param {String} city - 城市名称
|
||||
* @param {Object} options - 查询选项 { page, pageSize, level, type }
|
||||
* @param {Function} cb - 可选的回调函数
|
||||
* @returns {Promise<Array>} 医院列表
|
||||
*/
|
||||
HospitalSchema.statics.findByCity = async function (city, options = {}, cb) {
|
||||
const { page = 1, pageSize = 20, level, type } = options;
|
||||
const filter = {
|
||||
"location.city": city,
|
||||
"service.isEnabled": true,
|
||||
};
|
||||
if (level) {
|
||||
filter["basic.level"] = level;
|
||||
}
|
||||
if (type) {
|
||||
filter["basic.type"] = type;
|
||||
}
|
||||
const skip = (page - 1) * pageSize;
|
||||
return await this.find(filter)
|
||||
.sort({ "service.sortOrder": 1, "basic.name": 1 })
|
||||
.skip(skip)
|
||||
.limit(pageSize)
|
||||
.exec(cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取所有启用的医院列表(用于选择器)
|
||||
*
|
||||
* @param {Object} options - 查询选项 { city, level, type }
|
||||
* @param {Function} cb - 可选的回调函数
|
||||
* @returns {Promise<Array>} 医院列表(仅包含名称和ID)
|
||||
*/
|
||||
HospitalSchema.statics.getHospitalSelector = async function (options = {}, cb) {
|
||||
const { city, level, type } = options;
|
||||
const filter = { "service.isEnabled": true };
|
||||
if (city) {
|
||||
filter["location.city"] = city;
|
||||
}
|
||||
if (level) {
|
||||
filter["basic.level"] = level;
|
||||
}
|
||||
if (type) {
|
||||
filter["basic.type"] = type;
|
||||
}
|
||||
return await this.find(filter, { "basic.name": 1 })
|
||||
.sort({ "service.sortOrder": 1, "basic.name": 1 })
|
||||
.exec(cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建医院
|
||||
*
|
||||
* @param {Object} hospital - 医院对象
|
||||
* @param {Function} cb - 可选的回调函数
|
||||
* @returns {Promise<Object>} 创建的医院
|
||||
*/
|
||||
HospitalSchema.statics.createHospital = async function (hospital, cb) {
|
||||
hospital.meta = {
|
||||
createtime: Date.now(),
|
||||
updatetime: Date.now(),
|
||||
};
|
||||
const newHospital = new this(hospital);
|
||||
return await newHospital.save(cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新医院信息
|
||||
*
|
||||
* @param {ObjectId} id - 医院ID
|
||||
* @param {Object} update - 要更新的字段
|
||||
* @param {Function} cb - 可选的回调函数
|
||||
* @returns {Promise<Object|null>} 更新后的医院
|
||||
*/
|
||||
HospitalSchema.statics.updateHospital = async function (id, update, cb) {
|
||||
try {
|
||||
update["meta.updatetime"] = Date.now();
|
||||
return await this.findByIdAndUpdate(id, { $set: update }, { new: true }, cb);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 启用/禁用医院
|
||||
*
|
||||
* @param {ObjectId} id - 医院ID
|
||||
* @param {Boolean} isEnabled - 是否启用
|
||||
* @param {Function} cb - 可选的回调函数
|
||||
* @returns {Promise<Object|null>} 更新后的医院
|
||||
*/
|
||||
HospitalSchema.statics.setHospitalStatus = async function (id, isEnabled, cb) {
|
||||
try {
|
||||
return await this.findByIdAndUpdate(
|
||||
id,
|
||||
{
|
||||
"service.isEnabled": isEnabled,
|
||||
"meta.updatetime": Date.now(),
|
||||
},
|
||||
{ new: true },
|
||||
cb
|
||||
);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// 医院名称索引
|
||||
HospitalSchema.index({ "basic.name": 1 });
|
||||
|
||||
// 城市和等级索引
|
||||
HospitalSchema.index({ "location.city": 1, "basic.level": 1 });
|
||||
|
||||
// 启用状态索引
|
||||
HospitalSchema.index({ "service.isEnabled": 1 });
|
||||
|
||||
export { HospitalSchema };
|
||||
Reference in New Issue
Block a user