|
@@ -35,6 +35,163 @@ export namespace PrescriptionReviewModel {
|
|
|
/** 0 启用,1 禁用 */
|
|
/** 0 启用,1 禁用 */
|
|
|
status: 0 | 1;
|
|
status: 0 | 1;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /** 点评任务状态 */
|
|
|
|
|
+ export type ReviewTaskStatus =
|
|
|
|
|
+ | 'archived'
|
|
|
|
|
+ | 'completed'
|
|
|
|
|
+ | 'in_progress'
|
|
|
|
|
+ | 'pending';
|
|
|
|
|
+
|
|
|
|
|
+ /** 处方点评任务(抽样批次) */
|
|
|
|
|
+ export interface ReviewTask extends TransformRecord {
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ sampleTime: string;
|
|
|
|
|
+ sampleCount: number;
|
|
|
|
|
+ prescriptionDateStart: string;
|
|
|
|
|
+ prescriptionDateEnd: string;
|
|
|
|
|
+ status: ReviewTaskStatus;
|
|
|
|
|
+ reviewedCount: number;
|
|
|
|
|
+ archiveTime?: string;
|
|
|
|
|
+ passRate: number;
|
|
|
|
|
+ /** 抽样规则快照 */
|
|
|
|
|
+ samplingRule?: ReviewSamplingRule;
|
|
|
|
|
+ expertIds?: string[];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 抽样规则 */
|
|
|
|
|
+ export interface ReviewSamplingRule {
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ institutions?: string[];
|
|
|
|
|
+ prescriptionDateStart?: string;
|
|
|
|
|
+ prescriptionDateEnd?: string;
|
|
|
|
|
+ herbCountMin?: number;
|
|
|
|
|
+ herbCountMax?: number;
|
|
|
|
|
+ amountMin?: number;
|
|
|
|
|
+ amountMax?: number;
|
|
|
|
|
+ sampleCount?: number;
|
|
|
|
|
+ sampleRatio?: number;
|
|
|
|
|
+ excludeReviewed?: boolean;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 抽样机构树节点(医疗机构 / 科室 / 医生) */
|
|
|
|
|
+ export interface ReviewInstitutionTreeNode {
|
|
|
|
|
+ id: string;
|
|
|
|
|
+ pid: string;
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ children?: ReviewInstitutionTreeNode[];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 点评任务中的处方记录 */
|
|
|
|
|
+ export interface ReviewPrescriptionRecord extends TransformRecord {
|
|
|
|
|
+ taskId: string;
|
|
|
|
|
+ prescriptionNo: string;
|
|
|
|
|
+ institutionName: string;
|
|
|
|
|
+ departmentName: string;
|
|
|
|
|
+ doctorName: string;
|
|
|
|
|
+ status: 'pending' | 'qualified' | 'unqualified';
|
|
|
|
|
+ reviewExpert?: string;
|
|
|
|
|
+ /** 点评详情 */
|
|
|
|
|
+ reviewResult?: ReviewPrescriptionResult;
|
|
|
|
|
+ /** 智能辅助点评结果 */
|
|
|
|
|
+ auxiliaryReviewResult?: ReviewPrescriptionResult;
|
|
|
|
|
+ /** 处方详情 */
|
|
|
|
|
+ patientName?: string;
|
|
|
|
|
+ patientGender?: string;
|
|
|
|
|
+ patientAge?: number;
|
|
|
|
|
+ pregnancy?: boolean;
|
|
|
|
|
+ lactation?: boolean;
|
|
|
|
|
+ tcmDisease?: string;
|
|
|
|
|
+ tcmSyndrome?: string;
|
|
|
|
|
+ treatmentPrinciple?: string;
|
|
|
|
|
+ administrationMethod?: string;
|
|
|
|
|
+ herbCount?: number;
|
|
|
|
|
+ doseCount?: number;
|
|
|
|
|
+ totalAmount?: number;
|
|
|
|
|
+ unitDoseAmount?: number;
|
|
|
|
|
+ herbs?: string[];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ export interface ReviewPrescriptionResult {
|
|
|
|
|
+ qualified: boolean;
|
|
|
|
|
+ indicatorIds?: string[];
|
|
|
|
|
+ herbIndicatorMap?: Record<string, string[]>;
|
|
|
|
|
+ comment?: string;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 统计分析 - 处方点评表行 */
|
|
|
|
|
+ export interface ReviewStatisticsPrescriptionRow extends TransformRecord {
|
|
|
|
|
+ prescriptionNo: string;
|
|
|
|
|
+ institutionName: string;
|
|
|
|
|
+ doctorName: string;
|
|
|
|
|
+ pharmacistName?: string;
|
|
|
|
|
+ result: 'qualified' | 'unqualified';
|
|
|
|
|
+ unqualifiedDetail?: string;
|
|
|
|
|
+ comment?: string;
|
|
|
|
|
+ unitDoseAmount: number;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 统计分析 - 处方点评详情 */
|
|
|
|
|
+ export interface ReviewStatisticsPrescriptionDetail
|
|
|
|
|
+ extends ReviewStatisticsPrescriptionRow {
|
|
|
|
|
+ departmentName: string;
|
|
|
|
|
+ patientName: string;
|
|
|
|
|
+ patientGender: string;
|
|
|
|
|
+ patientAge: number;
|
|
|
|
|
+ pregnancy: boolean;
|
|
|
|
|
+ lactation: boolean;
|
|
|
|
|
+ tcmDisease: string;
|
|
|
|
|
+ tcmSyndrome: string;
|
|
|
|
|
+ treatmentPrinciple: string;
|
|
|
|
|
+ administrationMethod: string;
|
|
|
|
|
+ herbCount: number;
|
|
|
|
|
+ doseCount: number;
|
|
|
|
|
+ totalAmount: number;
|
|
|
|
|
+ herbs: string[];
|
|
|
|
|
+ reviewExpert?: string;
|
|
|
|
|
+ reviewTime?: string;
|
|
|
|
|
+ reviewResult?: ReviewPrescriptionResult;
|
|
|
|
|
+ /** 问题饮片旁标注文案,如 { 秦艽: '唐熙' } */
|
|
|
|
|
+ herbIssueLabels?: Record<string, string>;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 统计分析 - 均剂费用汇报层级 */
|
|
|
|
|
+ export type ReviewStatisticsCostLevel =
|
|
|
|
|
+ | 'department'
|
|
|
|
|
+ | 'doctor'
|
|
|
|
|
+ | 'institution'
|
|
|
|
|
+ | 'prescription';
|
|
|
|
|
+
|
|
|
|
|
+ /** 统计分析 - 均剂费用汇报行(树形:机构 → 科室 → 医生 → 处方号) */
|
|
|
|
|
+ export interface ReviewStatisticsCostRow extends TransformRecord {
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ level: ReviewStatisticsCostLevel;
|
|
|
|
|
+ prescriptionCount: number;
|
|
|
|
|
+ totalDoseCount: number;
|
|
|
|
|
+ totalAmount: number;
|
|
|
|
|
+ avgDoseCost: number;
|
|
|
|
|
+ exceedLimit?: boolean;
|
|
|
|
|
+ children?: ReviewStatisticsCostRow[];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 统计分析 - 点评结果汇报 */
|
|
|
|
|
+ export interface ReviewStatisticsSummary {
|
|
|
|
|
+ sampledPrescriptionCount: number;
|
|
|
|
|
+ sampledInstitutionCount: number;
|
|
|
|
|
+ qualifiedCount: number;
|
|
|
|
|
+ qualifiedRate: number;
|
|
|
|
|
+ avgDoseCost: number;
|
|
|
|
|
+ exceedLimitInstitutionCount: number;
|
|
|
|
|
+ sampleRatio: number;
|
|
|
|
|
+ sampledDoctorCount: number;
|
|
|
|
|
+ unqualifiedCount: number;
|
|
|
|
|
+ unqualifiedRate: number;
|
|
|
|
|
+ exceedLimitDoseCount: number;
|
|
|
|
|
+ exceedLimitDoseRate: number;
|
|
|
|
|
+ exceedLimitDoctorCount: number;
|
|
|
|
|
+ topUnqualifiedReasons: string[];
|
|
|
|
|
+ topExcessDosageHerbs: string[];
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const MOCK_EXPERTS: PrescriptionReviewModel.ReviewExpert[] = [
|
|
const MOCK_EXPERTS: PrescriptionReviewModel.ReviewExpert[] = [
|
|
@@ -195,8 +352,9 @@ const MOCK_INDICATOR_CATEGORIES: PrescriptionReviewModel.ReviewIndicatorCategory
|
|
|
{ id: 'cat-1', name: '适应症', source: 'system' },
|
|
{ id: 'cat-1', name: '适应症', source: 'system' },
|
|
|
{ id: 'cat-2', name: '用法用量', source: 'system' },
|
|
{ id: 'cat-2', name: '用法用量', source: 'system' },
|
|
|
{ id: 'cat-3', name: '配伍禁忌', source: 'system' },
|
|
{ id: 'cat-3', name: '配伍禁忌', source: 'system' },
|
|
|
- { id: 'cat-4', name: '特殊人群禁忌', source: 'system' },
|
|
|
|
|
|
|
+ { id: 'cat-4', name: '特殊人群慎禁忌', source: 'system' },
|
|
|
{ id: 'cat-5', name: '其他禁忌', source: 'system' },
|
|
{ id: 'cat-5', name: '其他禁忌', source: 'system' },
|
|
|
|
|
+ { id: 'cat-6', name: '超均贴限价', source: 'system' },
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
const MOCK_INDICATORS: PrescriptionReviewModel.ReviewIndicator[] = [
|
|
const MOCK_INDICATORS: PrescriptionReviewModel.ReviewIndicator[] = [
|
|
@@ -236,24 +394,6 @@ const MOCK_INDICATORS: PrescriptionReviewModel.ReviewIndicator[] = [
|
|
|
associatedChineseMedicine: false,
|
|
associatedChineseMedicine: false,
|
|
|
status: 1,
|
|
status: 1,
|
|
|
},
|
|
},
|
|
|
- {
|
|
|
|
|
- id: 'ind-5',
|
|
|
|
|
- categoryId: 'cat-2',
|
|
|
|
|
- categoryName: '用法用量',
|
|
|
|
|
- name: '超剂量用药',
|
|
|
|
|
- source: 'system',
|
|
|
|
|
- associatedChineseMedicine: false,
|
|
|
|
|
- status: 1,
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- id: 'ind-6',
|
|
|
|
|
- categoryId: 'cat-3',
|
|
|
|
|
- categoryName: '配伍禁忌',
|
|
|
|
|
- name: '十八反十九畏',
|
|
|
|
|
- source: 'system',
|
|
|
|
|
- associatedChineseMedicine: true,
|
|
|
|
|
- status: 0,
|
|
|
|
|
- },
|
|
|
|
|
{
|
|
{
|
|
|
id: 'ind-7',
|
|
id: 'ind-7',
|
|
|
categoryId: 'cat-1',
|
|
categoryId: 'cat-1',
|
|
@@ -276,6 +416,159 @@ const MOCK_INDICATORS: PrescriptionReviewModel.ReviewIndicator[] = [
|
|
|
createTime: '2023-09-23 15:29:38',
|
|
createTime: '2023-09-23 15:29:38',
|
|
|
status: 0,
|
|
status: 0,
|
|
|
},
|
|
},
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-dose-exceed',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '剂量超标',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: true,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-dose-low',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '剂量过低',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-admin-wrong',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '用法不正确',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-herb-count',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '药味数超标',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-long-term',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '长期服用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-18fan',
|
|
|
|
|
+ categoryId: 'cat-3',
|
|
|
|
|
+ categoryName: '配伍禁忌',
|
|
|
|
|
+ name: '十八反',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-19wei',
|
|
|
|
|
+ categoryId: 'cat-3',
|
|
|
|
|
+ categoryName: '配伍禁忌',
|
|
|
|
|
+ name: '十九畏',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-incompatible',
|
|
|
|
|
+ categoryId: 'cat-3',
|
|
|
|
|
+ categoryName: '配伍禁忌',
|
|
|
|
|
+ name: '不宜同用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-child',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '儿童',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-elder',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '老年人',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-childbearing',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '育龄期妇女',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-pregnant-caution',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '孕妇慎用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-pregnant-forbidden',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '孕妇禁用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-pregnant-avoid',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '孕妇忌用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-lactation',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '哺乳期妇女禁忌',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-other',
|
|
|
|
|
+ categoryId: 'cat-5',
|
|
|
|
|
+ categoryName: '其他禁忌',
|
|
|
|
|
+ name: '其他禁忌',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-price-limit',
|
|
|
|
|
+ categoryId: 'cat-6',
|
|
|
|
|
+ categoryName: '超均贴限价',
|
|
|
|
|
+ name: '超均贴限价',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
function getCategoryIndicatorCount(categoryId: string) {
|
|
function getCategoryIndicatorCount(categoryId: string) {
|
|
@@ -430,14 +723,19 @@ export function deleteReviewIndicatorCategoryMethod(categoryId: string) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 按分类获取点评指标列表(当前为本地 mock) */
|
|
/** 按分类获取点评指标列表(当前为本地 mock) */
|
|
|
-export function listReviewIndicatorsByCategoryMethod(categoryId: string) {
|
|
|
|
|
|
|
+export function listReviewIndicatorsByCategoryMethod(
|
|
|
|
|
+ categoryId: string,
|
|
|
|
|
+ options?: { enabledOnly?: boolean },
|
|
|
|
|
+) {
|
|
|
const category = MOCK_INDICATOR_CATEGORIES.find((item) => item.id === categoryId);
|
|
const category = MOCK_INDICATOR_CATEGORIES.find((item) => item.id === categoryId);
|
|
|
if (!category) {
|
|
if (!category) {
|
|
|
return Promise.reject(new Error('分类不存在'));
|
|
return Promise.reject(new Error('分类不存在'));
|
|
|
}
|
|
}
|
|
|
- return Promise.resolve(
|
|
|
|
|
- MOCK_INDICATORS.filter((item) => item.categoryId === categoryId),
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ let items = MOCK_INDICATORS.filter((item) => item.categoryId === categoryId);
|
|
|
|
|
+ if (options?.enabledOnly) {
|
|
|
|
|
+ items = items.filter((item) => item.status === 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ return Promise.resolve(items);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 点评指标排序(当前为本地 mock,按分类内顺序) */
|
|
/** 点评指标排序(当前为本地 mock,按分类内顺序) */
|
|
@@ -569,3 +867,1138 @@ export function updateReviewIndicatorStatusMethod(
|
|
|
indicator.status = status;
|
|
indicator.status = status;
|
|
|
return Promise.resolve(true);
|
|
return Promise.resolve(true);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+const REVIEW_TASK_STATUS_LABEL: Record<
|
|
|
|
|
+ PrescriptionReviewModel.ReviewTaskStatus,
|
|
|
|
|
+ string
|
|
|
|
|
+> = {
|
|
|
|
|
+ pending: '待点评',
|
|
|
|
|
+ in_progress: '点评进行中',
|
|
|
|
|
+ completed: '点评完成',
|
|
|
|
|
+ archived: '已归档',
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+function buildReviewInstitutionTreeNode(
|
|
|
|
|
+ id: string,
|
|
|
|
|
+ name: string,
|
|
|
|
|
+ children?: PrescriptionReviewModel.ReviewInstitutionTreeNode[],
|
|
|
|
|
+): PrescriptionReviewModel.ReviewInstitutionTreeNode {
|
|
|
|
|
+ return {
|
|
|
|
|
+ id,
|
|
|
|
|
+ pid: id,
|
|
|
|
|
+ name,
|
|
|
|
|
+ ...(children?.length ? { children } : {}),
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 抽样弹窗 - 医疗机构/科室/医生树(当前为本地 mock) */
|
|
|
|
|
+const MOCK_REVIEW_SAMPLING_INSTITUTION_TREE: PrescriptionReviewModel.ReviewInstitutionTreeNode[] =
|
|
|
|
|
+ [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('hospital-1', '智慧药事医院', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-lab', '检验科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-lab-1', '张检验'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-lab-2', '李检验'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-lab-3', '王检验'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-emergency', '应急物资库'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-pharmacy', '药库', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-tcm', '中药库', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-tcm-room', '中药房'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-tcm-1', '陈药师'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-tcm-2', '林药师'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-wm', '西药库', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-wm-room', '西药房'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-wm-1', '赵药师'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-wm-2', '钱药师'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-vaccine', '疫苗库', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-vaccine-room', '疫苗仓储'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-rehab', '康复科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-rehab-1', '刘医生'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-rehab-2', '孙医生'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-checkup', '体检科室', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-checkup-1', '周体检'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-checkup-2', '吴体检'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-office', '办公室'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-station', '服务站', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('station-east', '城东服务站'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('station-west', '城西服务站'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('station-south', '城南服务站'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('station-north', '城北服务站'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-internal', '内科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-int-1', '张明'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-int-2', '李华'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-int-3', '王芳'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-int-4', '赵敏'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-surgery', '外科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-sur-1', '王强'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-sur-2', '赵磊'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-sur-3', '孙伟'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-tcm-clinic', '中医科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-tcm-clinic-1', '周中医'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-tcm-clinic-2', '吴中医'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-tcm-clinic-3', '郑中医'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-pediatric', '儿科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-ped-1', '杨儿科'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-ped-2', '何儿科'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-gynecology', '妇科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-gyn-1', '徐妇科'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-orthopedics', '骨科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-orth-1', '冯骨科'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-orth-2', '沈骨科'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-dermatology', '皮肤科'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-ophthalmology', '眼科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-eye-1', '韩眼科'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-ent', '耳鼻喉科'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-emergency-room', '急诊科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-er-1', '马急诊'),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-er-2', '朱急诊'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('hospital-2', '蒋村社区卫生服务中心', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-jc-tcm', '中医科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-jc-tcm-1', '唐熙'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-jc-internal', '全科', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-jc-int-1', '郭可新'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ buildReviewInstitutionTreeNode('hospital-3', '浙江省中医院', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('dept-zj-tcm', '中药房', [
|
|
|
|
|
+ buildReviewInstitutionTreeNode('doc-zj-1', '沈慧'),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ ]),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+/** 获取抽样机构树(当前为本地 mock,后期对接后端接口) */
|
|
|
|
|
+export function listReviewSamplingInstitutionTreeMethod() {
|
|
|
|
|
+ return Promise.resolve(
|
|
|
|
|
+ structuredClone(MOCK_REVIEW_SAMPLING_INSTITUTION_TREE),
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const MOCK_REVIEW_TASKS: PrescriptionReviewModel.ReviewTask[] = [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'task-1',
|
|
|
|
|
+ name: '2023年月度',
|
|
|
|
|
+ sampleTime: '2023-09-23 14:00:39',
|
|
|
|
|
+ sampleCount: 200,
|
|
|
|
|
+ prescriptionDateStart: '2023.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2023.01.30',
|
|
|
|
|
+ status: 'pending',
|
|
|
|
|
+ reviewedCount: 0,
|
|
|
|
|
+ passRate: 100,
|
|
|
|
|
+ samplingRule: {
|
|
|
|
|
+ name: '2023年月度',
|
|
|
|
|
+ institutions: ['蒋村社区卫生服务中心'],
|
|
|
|
|
+ prescriptionDateStart: '2023.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2023.01.30',
|
|
|
|
|
+ sampleCount: 200,
|
|
|
|
|
+ sampleRatio: 50,
|
|
|
|
|
+ excludeReviewed: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ expertIds: ['1', '2'],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'task-2',
|
|
|
|
|
+ name: '2022年度多药味处方点评',
|
|
|
|
|
+ sampleTime: '2023-09-23 14:00:39',
|
|
|
|
|
+ sampleCount: 56,
|
|
|
|
|
+ prescriptionDateStart: '2022.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2022.12.31',
|
|
|
|
|
+ status: 'in_progress',
|
|
|
|
|
+ reviewedCount: 20,
|
|
|
|
|
+ passRate: 10,
|
|
|
|
|
+ samplingRule: {
|
|
|
|
|
+ name: '2022年度多药味处方点评',
|
|
|
|
|
+ prescriptionDateStart: '2022.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2022.12.31',
|
|
|
|
|
+ herbCountMin: 15,
|
|
|
|
|
+ sampleCount: 56,
|
|
|
|
|
+ excludeReviewed: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ expertIds: ['1'],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'task-3',
|
|
|
|
|
+ name: '2022年度处方点评',
|
|
|
|
|
+ sampleTime: '2023-09-23 14:00:39',
|
|
|
|
|
+ sampleCount: 90,
|
|
|
|
|
+ prescriptionDateStart: '2022.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2022.12.31',
|
|
|
|
|
+ status: 'completed',
|
|
|
|
|
+ reviewedCount: 90,
|
|
|
|
|
+ passRate: 89,
|
|
|
|
|
+ samplingRule: {
|
|
|
|
|
+ name: '2022年度处方点评',
|
|
|
|
|
+ institutions: ['蒋村社区卫生服务中心', '同仁堂', '浙江省中医院'],
|
|
|
|
|
+ prescriptionDateStart: '2022.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2022.12.31',
|
|
|
|
|
+ sampleCount: 90,
|
|
|
|
|
+ excludeReviewed: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ expertIds: ['1', '2', '3'],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'task-4',
|
|
|
|
|
+ name: '2022年度处方点评归档',
|
|
|
|
|
+ sampleTime: '2023-09-23 14:00:39',
|
|
|
|
|
+ sampleCount: 167,
|
|
|
|
|
+ prescriptionDateStart: '2022.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2022.12.31',
|
|
|
|
|
+ status: 'archived',
|
|
|
|
|
+ reviewedCount: 167,
|
|
|
|
|
+ archiveTime: '2023-09-24 10:38:12',
|
|
|
|
|
+ passRate: 30,
|
|
|
|
|
+ samplingRule: {
|
|
|
|
|
+ name: '2022年度处方点评',
|
|
|
|
|
+ institutions: ['机构1', '机构2', '机构3'],
|
|
|
|
|
+ prescriptionDateStart: '2022.01.01',
|
|
|
|
|
+ prescriptionDateEnd: '2022.12.31',
|
|
|
|
|
+ amountMin: 300,
|
|
|
|
|
+ sampleCount: 167,
|
|
|
|
|
+ sampleRatio: 99,
|
|
|
|
|
+ excludeReviewed: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ expertIds: ['1', '2'],
|
|
|
|
|
+ },
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
|
|
+const MOCK_REVIEW_PRESCRIPTIONS: PrescriptionReviewModel.ReviewPrescriptionRecord[] =
|
|
|
|
|
+ [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'rp-1',
|
|
|
|
|
+ taskId: 'task-3',
|
|
|
|
|
+ prescriptionNo: '202309238475',
|
|
|
|
|
+ institutionName: '蒋村社区卫生服务中心',
|
|
|
|
|
+ departmentName: '中医科',
|
|
|
|
|
+ doctorName: '张医生',
|
|
|
|
|
+ status: 'unqualified',
|
|
|
|
|
+ reviewExpert: '专家1',
|
|
|
|
|
+ patientName: '唐熙',
|
|
|
|
|
+ patientGender: '女',
|
|
|
|
|
+ patientAge: 48,
|
|
|
|
|
+ pregnancy: false,
|
|
|
|
|
+ lactation: false,
|
|
|
|
|
+ tcmDisease: '腰痛',
|
|
|
|
|
+ tcmSyndrome: '肝肾亏虚证',
|
|
|
|
|
+ treatmentPrinciple: '补益肝肾',
|
|
|
|
|
+ administrationMethod: '内服',
|
|
|
|
|
+ herbCount: 18,
|
|
|
|
|
+ doseCount: 7,
|
|
|
|
|
+ totalAmount: 234.01,
|
|
|
|
|
+ unitDoseAmount: 33.43,
|
|
|
|
|
+ herbs: [
|
|
|
|
|
+ '熟地黄 15g',
|
|
|
|
|
+ '山茱萸 15g',
|
|
|
|
|
+ '山药 15g',
|
|
|
|
|
+ '茯苓 15g',
|
|
|
|
|
+ '泽泻 10g',
|
|
|
|
|
+ '牡丹皮 10g',
|
|
|
|
|
+ '秦艽 15g',
|
|
|
|
|
+ '杜仲 15g',
|
|
|
|
|
+ '续断 15g',
|
|
|
|
|
+ '牛膝 15g',
|
|
|
|
|
+ '当归 12g',
|
|
|
|
|
+ '白芍 12g',
|
|
|
|
|
+ '川芎 10g',
|
|
|
|
|
+ '甘草 6g',
|
|
|
|
|
+ '陈皮 10g',
|
|
|
|
|
+ '半夏 10g',
|
|
|
|
|
+ '生姜 3片',
|
|
|
|
|
+ '大枣 3枚',
|
|
|
|
|
+ ],
|
|
|
|
|
+ reviewResult: {
|
|
|
|
|
+ qualified: false,
|
|
|
|
|
+ indicatorIds: [
|
|
|
|
|
+ 'ind-1',
|
|
|
|
|
+ 'ind-dose-exceed',
|
|
|
|
|
+ 'ind-18fan',
|
|
|
|
|
+ 'ind-child',
|
|
|
|
|
+ 'ind-other',
|
|
|
|
|
+ ],
|
|
|
|
|
+ herbIndicatorMap: { 'ind-dose-exceed': ['秦艽'] },
|
|
|
|
|
+ },
|
|
|
|
|
+ auxiliaryReviewResult: {
|
|
|
|
|
+ qualified: false,
|
|
|
|
|
+ indicatorIds: ['ind-1', 'ind-2', 'ind-dose-exceed', 'ind-18fan'],
|
|
|
|
|
+ herbIndicatorMap: { 'ind-dose-exceed': ['秦艽'] },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'rp-2',
|
|
|
|
|
+ taskId: 'task-3',
|
|
|
|
|
+ prescriptionNo: '202309238476',
|
|
|
|
|
+ institutionName: '同仁堂',
|
|
|
|
|
+ departmentName: '内科',
|
|
|
|
|
+ doctorName: '李医生',
|
|
|
|
|
+ status: 'pending',
|
|
|
|
|
+ patientName: '王明',
|
|
|
|
|
+ patientGender: '男',
|
|
|
|
|
+ patientAge: 55,
|
|
|
|
|
+ herbCount: 12,
|
|
|
|
|
+ doseCount: 5,
|
|
|
|
|
+ totalAmount: 156.5,
|
|
|
|
|
+ unitDoseAmount: 31.3,
|
|
|
|
|
+ herbs: ['黄芪 30g', '党参 15g', '白术 15g', '茯苓 15g'],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'rp-3',
|
|
|
|
|
+ taskId: 'task-3',
|
|
|
|
|
+ prescriptionNo: '202309238477',
|
|
|
|
|
+ institutionName: '浙江省中医院',
|
|
|
|
|
+ departmentName: '针灸科',
|
|
|
|
|
+ doctorName: '王医生',
|
|
|
|
|
+ status: 'qualified',
|
|
|
|
|
+ reviewExpert: '专家2',
|
|
|
|
|
+ patientName: '赵丽',
|
|
|
|
|
+ patientGender: '女',
|
|
|
|
|
+ patientAge: 32,
|
|
|
|
|
+ herbCount: 10,
|
|
|
|
|
+ doseCount: 7,
|
|
|
|
|
+ totalAmount: 98.0,
|
|
|
|
|
+ unitDoseAmount: 14.0,
|
|
|
|
|
+ herbs: ['当归 10g', '川芎 10g', '白芍 10g'],
|
|
|
|
|
+ reviewResult: { qualified: true },
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+function filterReviewTasks(
|
|
|
|
|
+ items: PrescriptionReviewModel.ReviewTask[],
|
|
|
|
|
+ query?: {
|
|
|
|
|
+ name?: string;
|
|
|
|
|
+ sampleTimeEnd?: string;
|
|
|
|
|
+ sampleTimeStart?: string;
|
|
|
|
|
+ status?: PrescriptionReviewModel.ReviewTaskStatus;
|
|
|
|
|
+ },
|
|
|
|
|
+) {
|
|
|
|
|
+ let result = [...items];
|
|
|
|
|
+ if (query?.status) {
|
|
|
|
|
+ result = result.filter((item) => item.status === query.status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (query?.name?.trim()) {
|
|
|
|
|
+ const keyword = query.name.trim();
|
|
|
|
|
+ result = result.filter((item) => item.name.includes(keyword));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (query?.sampleTimeStart) {
|
|
|
|
|
+ result = result.filter(
|
|
|
|
|
+ (item) => item.sampleTime >= query.sampleTimeStart!,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ if (query?.sampleTimeEnd) {
|
|
|
|
|
+ result = result.filter((item) => item.sampleTime <= `${query.sampleTimeEnd} 23:59:59`);
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function getReviewTaskStatusLabel(
|
|
|
|
|
+ status: PrescriptionReviewModel.ReviewTaskStatus,
|
|
|
|
|
+) {
|
|
|
|
|
+ return REVIEW_TASK_STATUS_LABEL[status] ?? status;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 处方点评任务列表(当前为本地 mock) */
|
|
|
|
|
+export function listReviewTasksMethod(
|
|
|
|
|
+ page = 1,
|
|
|
|
|
+ size = 10,
|
|
|
|
|
+ query?: Parameters<typeof filterReviewTasks>[1],
|
|
|
|
|
+): Promise<TransformList<PrescriptionReviewModel.ReviewTask>> {
|
|
|
|
|
+ const filtered = filterReviewTasks(MOCK_REVIEW_TASKS, query);
|
|
|
|
|
+ const start = (page - 1) * size;
|
|
|
|
|
+ const items = filtered.slice(start, start + size);
|
|
|
|
|
+ return Promise.resolve({
|
|
|
|
|
+ items,
|
|
|
|
|
+ total: filtered.length,
|
|
|
|
|
+ data: { page, size, total: filtered.length },
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 获取点评任务详情(当前为本地 mock) */
|
|
|
|
|
+export function getReviewTaskMethod(taskId: string) {
|
|
|
|
|
+ const task = MOCK_REVIEW_TASKS.find((item) => item.id === taskId);
|
|
|
|
|
+ if (!task) return Promise.reject(new Error('点评任务不存在'));
|
|
|
|
|
+ return Promise.resolve(task);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 创建抽样任务(当前为本地 mock) */
|
|
|
|
|
+export function createReviewTaskMethod(
|
|
|
|
|
+ data: PrescriptionReviewModel.ReviewSamplingRule,
|
|
|
|
|
+) {
|
|
|
|
|
+ const task: PrescriptionReviewModel.ReviewTask = {
|
|
|
|
|
+ id: `task-${Date.now()}`,
|
|
|
|
|
+ name: data.name,
|
|
|
|
|
+ sampleTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
|
|
|
|
+ sampleCount: data.sampleCount ?? 0,
|
|
|
|
|
+ prescriptionDateStart: data.prescriptionDateStart ?? '',
|
|
|
|
|
+ prescriptionDateEnd: data.prescriptionDateEnd ?? '',
|
|
|
|
|
+ status: 'pending',
|
|
|
|
|
+ reviewedCount: 0,
|
|
|
|
|
+ passRate: 100,
|
|
|
|
|
+ samplingRule: data,
|
|
|
|
|
+ expertIds: [],
|
|
|
|
|
+ };
|
|
|
|
|
+ MOCK_REVIEW_TASKS.unshift(task);
|
|
|
|
|
+ return Promise.resolve(task);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 归档点评任务(当前为本地 mock) */
|
|
|
|
|
+export function archiveReviewTaskMethod(taskId: string) {
|
|
|
|
|
+ const task = MOCK_REVIEW_TASKS.find((item) => item.id === taskId);
|
|
|
|
|
+ if (!task) return Promise.reject(new Error('点评任务不存在'));
|
|
|
|
|
+ if (task.status !== 'completed') {
|
|
|
|
|
+ return Promise.reject(new Error('仅点评完成的任务可归档'));
|
|
|
|
|
+ }
|
|
|
|
|
+ task.status = 'archived';
|
|
|
|
|
+ task.archiveTime = new Date().toISOString().slice(0, 19).replace('T', ' ');
|
|
|
|
|
+ return Promise.resolve(task);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 删除点评任务(当前为本地 mock) */
|
|
|
|
|
+export function deleteReviewTaskMethod(taskId: string) {
|
|
|
|
|
+ const index = MOCK_REVIEW_TASKS.findIndex((item) => item.id === taskId);
|
|
|
|
|
+ if (index === -1) return Promise.reject(new Error('点评任务不存在'));
|
|
|
|
|
+ MOCK_REVIEW_TASKS.splice(index, 1);
|
|
|
|
|
+ MOCK_REVIEW_PRESCRIPTIONS.splice(
|
|
|
|
|
+ 0,
|
|
|
|
|
+ MOCK_REVIEW_PRESCRIPTIONS.length,
|
|
|
|
|
+ ...MOCK_REVIEW_PRESCRIPTIONS.filter((item) => item.taskId !== taskId),
|
|
|
|
|
+ );
|
|
|
|
|
+ return Promise.resolve(true);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 更新点评专家组(当前为本地 mock) */
|
|
|
|
|
+export function updateReviewTaskExpertsMethod(
|
|
|
|
|
+ taskId: string,
|
|
|
|
|
+ expertIds: string[],
|
|
|
|
|
+) {
|
|
|
|
|
+ const task = MOCK_REVIEW_TASKS.find((item) => item.id === taskId);
|
|
|
|
|
+ if (!task) return Promise.reject(new Error('点评任务不存在'));
|
|
|
|
|
+ task.expertIds = expertIds;
|
|
|
|
|
+ return Promise.resolve(task);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 启动智能辅助点评(当前为本地 mock) */
|
|
|
|
|
+export function startIntelligentReviewMethod(taskId: string) {
|
|
|
|
|
+ const task = MOCK_REVIEW_TASKS.find((item) => item.id === taskId);
|
|
|
|
|
+ if (!task) return Promise.reject(new Error('点评任务不存在'));
|
|
|
|
|
+ if (task.status === 'archived') {
|
|
|
|
|
+ return Promise.reject(new Error('已归档任务不可操作'));
|
|
|
|
|
+ }
|
|
|
|
|
+ task.status = 'in_progress';
|
|
|
|
|
+ return Promise.resolve(true);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 点评任务处方列表(当前为本地 mock) */
|
|
|
|
|
+export function listReviewPrescriptionsMethod(
|
|
|
|
|
+ taskId: string,
|
|
|
|
|
+ page = 1,
|
|
|
|
|
+ size = 10,
|
|
|
|
|
+ query?: {
|
|
|
|
|
+ departmentName?: string;
|
|
|
|
|
+ doctorName?: string;
|
|
|
|
|
+ institutionName?: string;
|
|
|
|
|
+ status?: string;
|
|
|
|
|
+ },
|
|
|
|
|
+) {
|
|
|
|
|
+ let items = MOCK_REVIEW_PRESCRIPTIONS.filter(
|
|
|
|
|
+ (item) => item.taskId === taskId,
|
|
|
|
|
+ );
|
|
|
|
|
+ if (query?.status) {
|
|
|
|
|
+ items = items.filter((item) => item.status === query.status);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (query?.institutionName) {
|
|
|
|
|
+ items = items.filter(
|
|
|
|
|
+ (item) => item.institutionName === query.institutionName,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ if (query?.departmentName) {
|
|
|
|
|
+ items = items.filter(
|
|
|
|
|
+ (item) => item.departmentName === query.departmentName,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ if (query?.doctorName) {
|
|
|
|
|
+ items = items.filter((item) => item.doctorName === query.doctorName);
|
|
|
|
|
+ }
|
|
|
|
|
+ const start = (page - 1) * size;
|
|
|
|
|
+ return Promise.resolve({
|
|
|
|
|
+ items: items.slice(start, start + size),
|
|
|
|
|
+ total: items.length,
|
|
|
|
|
+ data: { page, size, total: items.length },
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 获取处方点评详情(当前为本地 mock) */
|
|
|
|
|
+export function getReviewPrescriptionMethod(prescriptionId: string) {
|
|
|
|
|
+ const record = MOCK_REVIEW_PRESCRIPTIONS.find(
|
|
|
|
|
+ (item) => item.id === prescriptionId,
|
|
|
|
|
+ );
|
|
|
|
|
+ if (!record) return Promise.reject(new Error('处方不存在'));
|
|
|
|
|
+ return Promise.resolve(record);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 获取处方辅助点评结果(当前为本地 mock) */
|
|
|
|
|
+export function getAuxiliaryReviewResultMethod(prescriptionId: string) {
|
|
|
|
|
+ const record = MOCK_REVIEW_PRESCRIPTIONS.find(
|
|
|
|
|
+ (item) => item.id === prescriptionId,
|
|
|
|
|
+ );
|
|
|
|
|
+ if (!record) return Promise.reject(new Error('处方不存在'));
|
|
|
|
|
+ if (!record.auxiliaryReviewResult) {
|
|
|
|
|
+ return Promise.reject(new Error('暂无辅助点评结果'));
|
|
|
|
|
+ }
|
|
|
|
|
+ return Promise.resolve(record.auxiliaryReviewResult);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 保存处方点评结果(当前为本地 mock) */
|
|
|
|
|
+export function saveReviewPrescriptionResultMethod(
|
|
|
|
|
+ prescriptionId: string,
|
|
|
|
|
+ result: PrescriptionReviewModel.ReviewPrescriptionResult,
|
|
|
|
|
+) {
|
|
|
|
|
+ const record = MOCK_REVIEW_PRESCRIPTIONS.find(
|
|
|
|
|
+ (item) => item.id === prescriptionId,
|
|
|
|
|
+ );
|
|
|
|
|
+ if (!record) return Promise.reject(new Error('处方不存在'));
|
|
|
|
|
+ const task = MOCK_REVIEW_TASKS.find((item) => item.id === record.taskId);
|
|
|
|
|
+ if (task?.status === 'archived') {
|
|
|
|
|
+ return Promise.reject(new Error('已归档任务不可修改'));
|
|
|
|
|
+ }
|
|
|
|
|
+ const wasReviewed = record.status !== 'pending';
|
|
|
|
|
+ record.reviewResult = result;
|
|
|
|
|
+ record.status = result.qualified ? 'qualified' : 'unqualified';
|
|
|
|
|
+ if (task && !wasReviewed) {
|
|
|
|
|
+ task.reviewedCount += 1;
|
|
|
|
|
+ if (task.reviewedCount >= task.sampleCount) {
|
|
|
|
|
+ task.status = 'completed';
|
|
|
|
|
+ } else if (task.status === 'pending') {
|
|
|
|
|
+ task.status = 'in_progress';
|
|
|
|
|
+ }
|
|
|
|
|
+ const taskRecords = MOCK_REVIEW_PRESCRIPTIONS.filter(
|
|
|
|
|
+ (item) => item.taskId === task.id && item.status !== 'pending',
|
|
|
|
|
+ );
|
|
|
|
|
+ const qualified = taskRecords.filter(
|
|
|
|
|
+ (item) => item.status === 'qualified',
|
|
|
|
|
+ ).length;
|
|
|
|
|
+ task.passRate =
|
|
|
|
|
+ taskRecords.length > 0
|
|
|
|
|
+ ? Math.round((qualified / taskRecords.length) * 100)
|
|
|
|
|
+ : 100;
|
|
|
|
|
+ }
|
|
|
|
|
+ return Promise.resolve(record);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const MOCK_STATISTICS_PRESCRIPTION_DETAILS: PrescriptionReviewModel.ReviewStatisticsPrescriptionDetail[] =
|
|
|
|
|
+ [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'stat-1',
|
|
|
|
|
+ prescriptionNo: '202309238475',
|
|
|
|
|
+ institutionName: '蒋村社区卫生服务中心',
|
|
|
|
|
+ departmentName: '全科医疗科',
|
|
|
|
|
+ doctorName: '唐熙',
|
|
|
|
|
+ pharmacistName: '崔红',
|
|
|
|
|
+ result: 'unqualified',
|
|
|
|
|
+ unqualifiedDetail: '剂量超标',
|
|
|
|
|
+ comment:
|
|
|
|
|
+ '处方整体用药基本合理,但秦艽用量超出常规范围,建议复核剂量。\n请结合患者实际情况调整用药方案。',
|
|
|
|
|
+ unitDoseAmount: 33.43,
|
|
|
|
|
+ patientName: '唐熙',
|
|
|
|
|
+ patientGender: '女',
|
|
|
|
|
+ patientAge: 48,
|
|
|
|
|
+ pregnancy: false,
|
|
|
|
|
+ lactation: false,
|
|
|
|
|
+ tcmDisease: '腰痛',
|
|
|
|
|
+ tcmSyndrome: '肝肾亏虚证',
|
|
|
|
|
+ treatmentPrinciple: '补益肝肾',
|
|
|
|
|
+ administrationMethod: '内服',
|
|
|
|
|
+ herbCount: 18,
|
|
|
|
|
+ doseCount: 7,
|
|
|
|
|
+ totalAmount: 234.01,
|
|
|
|
|
+ herbs: [
|
|
|
|
|
+ '熟地黄 15g',
|
|
|
|
|
+ '山茱萸 15g',
|
|
|
|
|
+ '山药 15g',
|
|
|
|
|
+ '茯苓 15g',
|
|
|
|
|
+ '泽泻 10g',
|
|
|
|
|
+ '牡丹皮 10g',
|
|
|
|
|
+ '秦艽 20g',
|
|
|
|
|
+ '杜仲 15g',
|
|
|
|
|
+ '续断 15g',
|
|
|
|
|
+ '牛膝 15g',
|
|
|
|
|
+ '当归 12g',
|
|
|
|
|
+ '白芍 12g',
|
|
|
|
|
+ '川芎 10g',
|
|
|
|
|
+ '甘草 6g',
|
|
|
|
|
+ '陈皮 10g',
|
|
|
|
|
+ '半夏 10g',
|
|
|
|
|
+ '生姜 3片',
|
|
|
|
|
+ '大枣 3枚',
|
|
|
|
|
+ ],
|
|
|
|
|
+ reviewExpert: '于沐',
|
|
|
|
|
+ reviewTime: '2023-09-23 14:00:39',
|
|
|
|
|
+ reviewResult: {
|
|
|
|
|
+ qualified: false,
|
|
|
|
|
+ indicatorIds: ['ind-dose-exceed'],
|
|
|
|
|
+ herbIndicatorMap: { 'ind-dose-exceed': ['秦艽'] },
|
|
|
|
|
+ comment:
|
|
|
|
|
+ '处方整体用药基本合理,但秦艽用量超出常规范围,建议复核剂量。\n请结合患者实际情况调整用药方案。',
|
|
|
|
|
+ },
|
|
|
|
|
+ herbIssueLabels: { 秦艽: '唐熙' },
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'stat-2',
|
|
|
|
|
+ prescriptionNo: '2023092323946',
|
|
|
|
|
+ institutionName: '同仁堂',
|
|
|
|
|
+ departmentName: '内科',
|
|
|
|
|
+ doctorName: '郭可新',
|
|
|
|
|
+ pharmacistName: '',
|
|
|
|
|
+ result: 'unqualified',
|
|
|
|
|
+ unqualifiedDetail: '病证禁忌',
|
|
|
|
|
+ comment: '',
|
|
|
|
|
+ unitDoseAmount: 14,
|
|
|
|
|
+ patientName: '王明',
|
|
|
|
|
+ patientGender: '男',
|
|
|
|
|
+ patientAge: 55,
|
|
|
|
|
+ pregnancy: false,
|
|
|
|
|
+ lactation: false,
|
|
|
|
|
+ tcmDisease: '感冒',
|
|
|
|
|
+ tcmSyndrome: '风寒束表证',
|
|
|
|
|
+ treatmentPrinciple: '辛温解表',
|
|
|
|
|
+ administrationMethod: '内服',
|
|
|
|
|
+ herbCount: 12,
|
|
|
|
|
+ doseCount: 5,
|
|
|
|
|
+ totalAmount: 70,
|
|
|
|
|
+ herbs: ['黄芪 30g', '党参 15g', '白术 15g', '茯苓 15g'],
|
|
|
|
|
+ reviewExpert: '于沐',
|
|
|
|
|
+ reviewTime: '2023-09-23 14:05:12',
|
|
|
|
|
+ reviewResult: {
|
|
|
|
|
+ qualified: false,
|
|
|
|
|
+ indicatorIds: ['ind-1'],
|
|
|
|
|
+ comment: '',
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'stat-3',
|
|
|
|
|
+ prescriptionNo: '2023092323947',
|
|
|
|
|
+ institutionName: '浙江省中医院',
|
|
|
|
|
+ departmentName: '针灸科',
|
|
|
|
|
+ doctorName: '沈慧',
|
|
|
|
|
+ pharmacistName: '李药师',
|
|
|
|
|
+ result: 'unqualified',
|
|
|
|
|
+ unqualifiedDetail: '超均贴限价',
|
|
|
|
|
+ comment: '单剂金额偏高,建议优化处方结构。',
|
|
|
|
|
+ unitDoseAmount: 45,
|
|
|
|
|
+ patientName: '赵丽',
|
|
|
|
|
+ patientGender: '女',
|
|
|
|
|
+ patientAge: 32,
|
|
|
|
|
+ pregnancy: false,
|
|
|
|
|
+ lactation: false,
|
|
|
|
|
+ tcmDisease: '头痛',
|
|
|
|
|
+ tcmSyndrome: '肝阳上亢证',
|
|
|
|
|
+ treatmentPrinciple: '平肝潜阳',
|
|
|
|
|
+ administrationMethod: '内服',
|
|
|
|
|
+ herbCount: 10,
|
|
|
|
|
+ doseCount: 7,
|
|
|
|
|
+ totalAmount: 315,
|
|
|
|
|
+ herbs: ['当归 10g', '川芎 10g', '白芍 10g', '天麻 10g'],
|
|
|
|
|
+ reviewExpert: '专家2',
|
|
|
|
|
+ reviewTime: '2023-09-23 15:20:00',
|
|
|
|
|
+ reviewResult: {
|
|
|
|
|
+ qualified: false,
|
|
|
|
|
+ indicatorIds: ['ind-price-limit'],
|
|
|
|
|
+ comment: '单剂金额偏高,建议优化处方结构。',
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+const MOCK_STATISTICS_PRESCRIPTIONS: PrescriptionReviewModel.ReviewStatisticsPrescriptionRow[] =
|
|
|
|
|
+ MOCK_STATISTICS_PRESCRIPTION_DETAILS.map(
|
|
|
|
|
+ ({
|
|
|
|
|
+ administrationMethod,
|
|
|
|
|
+ departmentName,
|
|
|
|
|
+ doseCount,
|
|
|
|
|
+ herbCount,
|
|
|
|
|
+ herbIssueLabels,
|
|
|
|
|
+ herbs,
|
|
|
|
|
+ lactation,
|
|
|
|
|
+ patientAge,
|
|
|
|
|
+ patientGender,
|
|
|
|
|
+ patientName,
|
|
|
|
|
+ pregnancy,
|
|
|
|
|
+ reviewExpert,
|
|
|
|
|
+ reviewResult,
|
|
|
|
|
+ reviewTime,
|
|
|
|
|
+ tcmDisease,
|
|
|
|
|
+ tcmSyndrome,
|
|
|
|
|
+ totalAmount,
|
|
|
|
|
+ treatmentPrinciple,
|
|
|
|
|
+ ...row
|
|
|
|
|
+ }) => row,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+const MOCK_STATISTICS_DETAIL_INDICATORS: PrescriptionReviewModel.ReviewIndicator[] =
|
|
|
|
|
+ [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-1',
|
|
|
|
|
+ categoryId: 'cat-1',
|
|
|
|
|
+ categoryName: '适应症',
|
|
|
|
|
+ name: '病证禁忌',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-2',
|
|
|
|
|
+ categoryId: 'cat-1',
|
|
|
|
|
+ categoryName: '适应症',
|
|
|
|
|
+ name: '慎用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-3',
|
|
|
|
|
+ categoryId: 'cat-1',
|
|
|
|
|
+ categoryName: '适应症',
|
|
|
|
|
+ name: '禁用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-4',
|
|
|
|
|
+ categoryId: 'cat-1',
|
|
|
|
|
+ categoryName: '适应症',
|
|
|
|
|
+ name: '忌用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-7',
|
|
|
|
|
+ categoryId: 'cat-1',
|
|
|
|
|
+ categoryName: '适应症',
|
|
|
|
|
+ name: '点评项1',
|
|
|
|
|
+ source: 'custom',
|
|
|
|
|
+ associatedChineseMedicine: true,
|
|
|
|
|
+ createUser: '陆长林',
|
|
|
|
|
+ createTime: '2023-09-23 15:29:38',
|
|
|
|
|
+ status: 0,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-8',
|
|
|
|
|
+ categoryId: 'cat-1',
|
|
|
|
|
+ categoryName: '适应症',
|
|
|
|
|
+ name: '点评项2',
|
|
|
|
|
+ source: 'custom',
|
|
|
|
|
+ associatedChineseMedicine: true,
|
|
|
|
|
+ createUser: '陆长林',
|
|
|
|
|
+ createTime: '2023-09-23 15:29:38',
|
|
|
|
|
+ status: 0,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-dose-low',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '剂量不足',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-dose-exceed',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '剂量超标',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: true,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-admin-wrong',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '服法错误',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-decoct',
|
|
|
|
|
+ categoryId: 'cat-2',
|
|
|
|
|
+ categoryName: '用法用量',
|
|
|
|
|
+ name: '特殊煎法',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-18fan',
|
|
|
|
|
+ categoryId: 'cat-3',
|
|
|
|
|
+ categoryName: '配伍禁忌',
|
|
|
|
|
+ name: '十八反',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-19wei',
|
|
|
|
|
+ categoryId: 'cat-3',
|
|
|
|
|
+ categoryName: '配伍禁忌',
|
|
|
|
|
+ name: '十九畏',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-incompatible',
|
|
|
|
|
+ categoryId: 'cat-3',
|
|
|
|
|
+ categoryName: '配伍禁忌',
|
|
|
|
|
+ name: '不宜同用',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-food',
|
|
|
|
|
+ categoryId: 'cat-3',
|
|
|
|
|
+ categoryName: '配伍禁忌',
|
|
|
|
|
+ name: '忌用慎用的食物',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-child',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '儿童',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-elder',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '老年人',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-pregnant',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '孕妇',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-lactation',
|
|
|
|
|
+ categoryId: 'cat-4',
|
|
|
|
|
+ categoryName: '特殊人群慎禁忌',
|
|
|
|
|
+ name: '哺乳期妇女',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-other',
|
|
|
|
|
+ categoryId: 'cat-5',
|
|
|
|
|
+ categoryName: '其他禁忌',
|
|
|
|
|
+ name: '其他禁忌',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'ind-price-limit',
|
|
|
|
|
+ categoryId: 'cat-6',
|
|
|
|
|
+ categoryName: '超均贴限价',
|
|
|
|
|
+ name: '超均贴限价',
|
|
|
|
|
+ source: 'system',
|
|
|
|
|
+ associatedChineseMedicine: false,
|
|
|
|
|
+ status: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+function buildReviewStatisticsCostTree(): PrescriptionReviewModel.ReviewStatisticsCostRow[] {
|
|
|
|
|
+ return [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-1',
|
|
|
|
|
+ name: '蒋村社区卫生服务中心',
|
|
|
|
|
+ level: 'institution',
|
|
|
|
|
+ prescriptionCount: 233,
|
|
|
|
|
+ totalDoseCount: 1398,
|
|
|
|
|
+ totalAmount: 47392.2,
|
|
|
|
|
+ avgDoseCost: 33.9,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-1-dept-1',
|
|
|
|
|
+ name: '中医科',
|
|
|
|
|
+ level: 'department',
|
|
|
|
|
+ prescriptionCount: 120,
|
|
|
|
|
+ totalDoseCount: 720,
|
|
|
|
|
+ totalAmount: 24336,
|
|
|
|
|
+ avgDoseCost: 33.8,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-1-dept-1-doc-1',
|
|
|
|
|
+ name: '康毛理',
|
|
|
|
|
+ level: 'doctor',
|
|
|
|
|
+ prescriptionCount: 68,
|
|
|
|
|
+ totalDoseCount: 408,
|
|
|
|
|
+ totalAmount: 13872,
|
|
|
|
|
+ avgDoseCost: 34,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-1-dept-1-doc-1-rx-1',
|
|
|
|
|
+ name: '2023092323945',
|
|
|
|
|
+ level: 'prescription',
|
|
|
|
|
+ prescriptionCount: 1,
|
|
|
|
|
+ totalDoseCount: 7,
|
|
|
|
|
+ totalAmount: 208.6,
|
|
|
|
|
+ avgDoseCost: 29.8,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-1-dept-1-doc-1-rx-2',
|
|
|
|
|
+ name: '2023092323948',
|
|
|
|
|
+ level: 'prescription',
|
|
|
|
|
+ prescriptionCount: 1,
|
|
|
|
|
+ totalDoseCount: 6,
|
|
|
|
|
+ totalAmount: 210,
|
|
|
|
|
+ avgDoseCost: 35,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-1-dept-1-doc-2',
|
|
|
|
|
+ name: '张医生',
|
|
|
|
|
+ level: 'doctor',
|
|
|
|
|
+ prescriptionCount: 52,
|
|
|
|
|
+ totalDoseCount: 312,
|
|
|
|
|
+ totalAmount: 10464,
|
|
|
|
|
+ avgDoseCost: 33.5,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-1-dept-2',
|
|
|
|
|
+ name: '全科',
|
|
|
|
|
+ level: 'department',
|
|
|
|
|
+ prescriptionCount: 113,
|
|
|
|
|
+ totalDoseCount: 678,
|
|
|
|
|
+ totalAmount: 23056.2,
|
|
|
|
|
+ avgDoseCost: 34,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-2',
|
|
|
|
|
+ name: '同仁堂',
|
|
|
|
|
+ level: 'institution',
|
|
|
|
|
+ prescriptionCount: 455,
|
|
|
|
|
+ totalDoseCount: 3185,
|
|
|
|
|
+ totalAmount: 103512.5,
|
|
|
|
|
+ avgDoseCost: 32.5,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-2-dept-1',
|
|
|
|
|
+ name: '内科',
|
|
|
|
|
+ level: 'department',
|
|
|
|
|
+ prescriptionCount: 255,
|
|
|
|
|
+ totalDoseCount: 1785,
|
|
|
|
|
+ totalAmount: 58012.5,
|
|
|
|
|
+ avgDoseCost: 32.5,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-2-dept-1-doc-1',
|
|
|
|
|
+ name: '郭可新',
|
|
|
|
|
+ level: 'doctor',
|
|
|
|
|
+ prescriptionCount: 130,
|
|
|
|
|
+ totalDoseCount: 910,
|
|
|
|
|
+ totalAmount: 29575,
|
|
|
|
|
+ avgDoseCost: 32.5,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-2-dept-1-doc-1-rx-1',
|
|
|
|
|
+ name: '2023092323946',
|
|
|
|
|
+ level: 'prescription',
|
|
|
|
|
+ prescriptionCount: 1,
|
|
|
|
|
+ totalDoseCount: 5,
|
|
|
|
|
+ totalAmount: 70,
|
|
|
|
|
+ avgDoseCost: 14,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-2-dept-2',
|
|
|
|
|
+ name: '中医科',
|
|
|
|
|
+ level: 'department',
|
|
|
|
|
+ prescriptionCount: 200,
|
|
|
|
|
+ totalDoseCount: 1400,
|
|
|
|
|
+ totalAmount: 45500,
|
|
|
|
|
+ avgDoseCost: 32.5,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-3',
|
|
|
|
|
+ name: '浙江省中医院',
|
|
|
|
|
+ level: 'institution',
|
|
|
|
|
+ prescriptionCount: 3454,
|
|
|
|
|
+ totalDoseCount: 22451,
|
|
|
|
|
+ totalAmount: 713941.8,
|
|
|
|
|
+ avgDoseCost: 31.8,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-3-dept-1',
|
|
|
|
|
+ name: '针灸科',
|
|
|
|
|
+ level: 'department',
|
|
|
|
|
+ prescriptionCount: 1680,
|
|
|
|
|
+ totalDoseCount: 10920,
|
|
|
|
|
+ totalAmount: 347256,
|
|
|
|
|
+ avgDoseCost: 31.8,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-3-dept-1-doc-1',
|
|
|
|
|
+ name: '沈慧',
|
|
|
|
|
+ level: 'doctor',
|
|
|
|
|
+ prescriptionCount: 820,
|
|
|
|
|
+ totalDoseCount: 5330,
|
|
|
|
|
+ totalAmount: 169494,
|
|
|
|
|
+ avgDoseCost: 31.8,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-3-dept-1-doc-1-rx-1',
|
|
|
|
|
+ name: '2023092323947',
|
|
|
|
|
+ level: 'prescription',
|
|
|
|
|
+ prescriptionCount: 1,
|
|
|
|
|
+ totalDoseCount: 7,
|
|
|
|
|
+ totalAmount: 315,
|
|
|
|
|
+ avgDoseCost: 45,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 'cost-3-dept-2',
|
|
|
|
|
+ name: '骨伤科',
|
|
|
|
|
+ level: 'department',
|
|
|
|
|
+ prescriptionCount: 1774,
|
|
|
|
|
+ totalDoseCount: 11531,
|
|
|
|
|
+ totalAmount: 366685.8,
|
|
|
|
|
+ avgDoseCost: 31.8,
|
|
|
|
|
+ exceedLimit: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 统计分析 - 处方点评表(当前为本地 mock) */
|
|
|
|
|
+export function listReviewStatisticsPrescriptionsMethod(taskId: string) {
|
|
|
|
|
+ void taskId;
|
|
|
|
|
+ return Promise.resolve([...MOCK_STATISTICS_PRESCRIPTIONS]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 统计分析 - 处方点评详情(当前为本地 mock) */
|
|
|
|
|
+export function getReviewStatisticsPrescriptionDetailMethod(
|
|
|
|
|
+ taskId: string,
|
|
|
|
|
+ prescriptionId: string,
|
|
|
|
|
+) {
|
|
|
|
|
+ void taskId;
|
|
|
|
|
+ const detail = MOCK_STATISTICS_PRESCRIPTION_DETAILS.find(
|
|
|
|
|
+ (item) => item.id === prescriptionId,
|
|
|
|
|
+ );
|
|
|
|
|
+ if (!detail) {
|
|
|
|
|
+ return Promise.reject(new Error('处方不存在'));
|
|
|
|
|
+ }
|
|
|
|
|
+ return Promise.resolve(detail);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 统计分析 - 点评详情指标分类(当前为本地 mock) */
|
|
|
|
|
+export function listReviewStatisticsDetailIndicatorCategoriesMethod() {
|
|
|
|
|
+ const categoryIds = [
|
|
|
|
|
+ ...new Set(MOCK_STATISTICS_DETAIL_INDICATORS.map((item) => item.categoryId)),
|
|
|
|
|
+ ];
|
|
|
|
|
+ return Promise.resolve(
|
|
|
|
|
+ MOCK_INDICATOR_CATEGORIES.filter((item) => categoryIds.includes(item.id)),
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 统计分析 - 点评详情指标列表(当前为本地 mock) */
|
|
|
|
|
+export function listReviewStatisticsDetailIndicatorsByCategoryMethod(
|
|
|
|
|
+ categoryId: string,
|
|
|
|
|
+) {
|
|
|
|
|
+ return Promise.resolve(
|
|
|
|
|
+ MOCK_STATISTICS_DETAIL_INDICATORS.filter(
|
|
|
|
|
+ (item) => item.categoryId === categoryId,
|
|
|
|
|
+ ),
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 统计分析 - 均剂费用汇报(当前为本地 mock,树形:机构 → 科室 → 医生 → 处方号) */
|
|
|
|
|
+export function listReviewStatisticsCostMethod(taskId: string) {
|
|
|
|
|
+ void taskId;
|
|
|
|
|
+ return Promise.resolve(buildReviewStatisticsCostTree());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 统计分析 - 点评结果汇报(当前为本地 mock) */
|
|
|
|
|
+export function getReviewStatisticsSummaryMethod(
|
|
|
|
|
+ taskId: string,
|
|
|
|
|
+): Promise<PrescriptionReviewModel.ReviewStatisticsSummary> {
|
|
|
|
|
+ void taskId;
|
|
|
|
|
+ return Promise.resolve({
|
|
|
|
|
+ sampledPrescriptionCount: 234,
|
|
|
|
|
+ sampledInstitutionCount: 5,
|
|
|
|
|
+ qualifiedCount: 204,
|
|
|
|
|
+ qualifiedRate: 87.18,
|
|
|
|
|
+ avgDoseCost: 19.28,
|
|
|
|
|
+ exceedLimitInstitutionCount: 2,
|
|
|
|
|
+ sampleRatio: 26,
|
|
|
|
|
+ sampledDoctorCount: 25,
|
|
|
|
|
+ unqualifiedCount: 30,
|
|
|
|
|
+ unqualifiedRate: 12.82,
|
|
|
|
|
+ exceedLimitDoseCount: 35,
|
|
|
|
|
+ exceedLimitDoseRate: 5.18,
|
|
|
|
|
+ exceedLimitDoctorCount: 2,
|
|
|
|
|
+ topUnqualifiedReasons: [
|
|
|
|
|
+ '病证禁忌',
|
|
|
|
|
+ '剂量超标',
|
|
|
|
|
+ '药味数超标',
|
|
|
|
|
+ '不宜同用',
|
|
|
|
|
+ '超均贴限价',
|
|
|
|
|
+ ],
|
|
|
|
|
+ topExcessDosageHerbs: ['秦艽', '知柏', '甘草', '黄芩', '当归'],
|
|
|
|
|
+ });
|
|
|
|
|
+}
|