|
|
@@ -0,0 +1,258 @@
|
|
|
+import type {
|
|
|
+ DosageForm,
|
|
|
+ HospitalPreparationDTO,
|
|
|
+ HospitalPreparationSubmitVO,
|
|
|
+ HospitalPreparationVO,
|
|
|
+} from './hospital-preparation.schema';
|
|
|
+
|
|
|
+import type { PageQueryMethodArgs } from '#/request/schema';
|
|
|
+import type { PageVO } from '#/request/schema/record';
|
|
|
+
|
|
|
+import { pageQueryArgsTransform } from '#/request/schema';
|
|
|
+
|
|
|
+import {
|
|
|
+ decodeHospitalPreparation,
|
|
|
+ encodeHospitalPreparation,
|
|
|
+ encodeHospitalPreparationQuery,
|
|
|
+} from './hospital-preparation.schema';
|
|
|
+
|
|
|
+/** 后端接口就绪后改为 false */
|
|
|
+export const USE_HOSPITAL_PREPARATION_MOCK = true;
|
|
|
+
|
|
|
+type MethodLike<T> = PromiseLike<T> & {
|
|
|
+ send?: (force?: boolean) => PromiseLike<T>;
|
|
|
+};
|
|
|
+
|
|
|
+const MOCK_PDF_URL =
|
|
|
+ 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';
|
|
|
+
|
|
|
+const SEED_RECORDS: Omit<
|
|
|
+ HospitalPreparationDTO,
|
|
|
+ 'createTime' | 'id' | 'personalStudioId' | 'updateTime'
|
|
|
+>[] = [
|
|
|
+ {
|
|
|
+ preparationNumber: 'YN2023001',
|
|
|
+ name: '健脾和胃颗粒',
|
|
|
+ dosageForm: 'granules',
|
|
|
+ mainIngredients: '党参、白术、茯苓、甘草等',
|
|
|
+ indications: '用于脾胃虚弱,食少便溏',
|
|
|
+ approvalDate: '2023-06-15',
|
|
|
+ status: true,
|
|
|
+ fileUrl: MOCK_PDF_URL,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ preparationNumber: 'YN2024002',
|
|
|
+ name: '清肝明目丸',
|
|
|
+ dosageForm: 'pills',
|
|
|
+ mainIngredients: '菊花、决明子、枸杞子、熟地黄等',
|
|
|
+ indications: '用于肝火上炎,目赤肿痛',
|
|
|
+ approvalDate: '2024-03-20',
|
|
|
+ status: true,
|
|
|
+ fileUrl: MOCK_PDF_URL,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ preparationNumber: 'YN2022003',
|
|
|
+ name: '止咳化痰口服液',
|
|
|
+ dosageForm: 'oral_liquid',
|
|
|
+ mainIngredients: '川贝、枇杷叶、桔梗、甘草等',
|
|
|
+ indications: '用于咳嗽痰多,胸闷气促',
|
|
|
+ approvalDate: '2022-11-10',
|
|
|
+ status: false,
|
|
|
+ fileUrl: MOCK_PDF_URL,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ preparationNumber: 'YN2023004',
|
|
|
+ name: '温阳散寒汤',
|
|
|
+ dosageForm: 'decoction',
|
|
|
+ mainIngredients: '附子、干姜、肉桂、甘草等',
|
|
|
+ indications: '用于阳虚寒凝,四肢不温',
|
|
|
+ approvalDate: '2023-09-08',
|
|
|
+ status: true,
|
|
|
+ fileUrl: MOCK_PDF_URL,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ preparationNumber: 'YN2024005',
|
|
|
+ name: '润肤止痒膏',
|
|
|
+ dosageForm: 'cream',
|
|
|
+ mainIngredients: '苦参、白鲜皮、地肤子、冰片等',
|
|
|
+ indications: '用于湿疹瘙痒,皮肤干燥',
|
|
|
+ approvalDate: '2024-01-12',
|
|
|
+ status: true,
|
|
|
+ fileUrl: MOCK_PDF_URL,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ preparationNumber: 'YN2023006',
|
|
|
+ name: '益气复脉颗粒',
|
|
|
+ dosageForm: 'granules',
|
|
|
+ mainIngredients: '黄芪、党参、麦冬、五味子',
|
|
|
+ indications: '用于气阴两虚,心悸气短',
|
|
|
+ approvalDate: '2023-04-22',
|
|
|
+ status: false,
|
|
|
+ fileUrl: MOCK_PDF_URL,
|
|
|
+ },
|
|
|
+];
|
|
|
+
|
|
|
+function createInitialStore(): HospitalPreparationDTO[] {
|
|
|
+ const records: HospitalPreparationDTO[] = [];
|
|
|
+ for (let index = 0; index < 18; index += 1) {
|
|
|
+ const seed = SEED_RECORDS[index % SEED_RECORDS.length] ?? SEED_RECORDS[0];
|
|
|
+ if (!seed) continue;
|
|
|
+ const year = 2022 + (index % 3);
|
|
|
+ const month = String((index % 12) + 1).padStart(2, '0');
|
|
|
+ const day = String((index % 28) + 1).padStart(2, '0');
|
|
|
+ records.push({
|
|
|
+ ...seed,
|
|
|
+ id: String(index + 1),
|
|
|
+ personalStudioId: '327477138296832',
|
|
|
+ preparationNumber: `YN${year}${String(index + 1).padStart(3, '0')}`,
|
|
|
+ approvalDate: `${year}-${month}-${day}`,
|
|
|
+ createTime: `2026-${month}-${day}T10:00:00`,
|
|
|
+ updateTime: `2026-05-${day}T10:00:00`,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return records;
|
|
|
+}
|
|
|
+
|
|
|
+let nextId = 100;
|
|
|
+let store = createInitialStore();
|
|
|
+
|
|
|
+function delay<T>(runner: () => Promise<T> | T, ms = 120): MethodLike<T> {
|
|
|
+ const run = async () => {
|
|
|
+ await new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
+ return runner();
|
|
|
+ };
|
|
|
+ const promise = run();
|
|
|
+ return Object.assign(promise, { send: run });
|
|
|
+}
|
|
|
+
|
|
|
+function matchKeyword(record: HospitalPreparationDTO, keyword?: string) {
|
|
|
+ if (!keyword) return true;
|
|
|
+ const text = [
|
|
|
+ record.name,
|
|
|
+ record.preparationNumber,
|
|
|
+ record.mainIngredients,
|
|
|
+ record.indications,
|
|
|
+ ]
|
|
|
+ .filter(Boolean)
|
|
|
+ .join(' ');
|
|
|
+ return text.includes(keyword);
|
|
|
+}
|
|
|
+
|
|
|
+function matchWorkroom(record: HospitalPreparationDTO, workroomId?: string) {
|
|
|
+ if (!workroomId) return true;
|
|
|
+ return String(record.personalStudioId ?? '') === String(workroomId);
|
|
|
+}
|
|
|
+
|
|
|
+function matchDosageForm(
|
|
|
+ record: HospitalPreparationDTO,
|
|
|
+ dosageForm?: DosageForm,
|
|
|
+) {
|
|
|
+ if (!dosageForm) return true;
|
|
|
+ return record.dosageForm === dosageForm;
|
|
|
+}
|
|
|
+
|
|
|
+function matchStatus(record: HospitalPreparationDTO, status?: boolean) {
|
|
|
+ if (status === undefined) return true;
|
|
|
+ return record.status === status;
|
|
|
+}
|
|
|
+
|
|
|
+function toVo(dto: HospitalPreparationDTO): HospitalPreparationVO {
|
|
|
+ return decodeHospitalPreparation(dto);
|
|
|
+}
|
|
|
+
|
|
|
+export function mockListHospitalPreparationMethod(
|
|
|
+ ...args: PageQueryMethodArgs
|
|
|
+) {
|
|
|
+ const { params, data } = pageQueryArgsTransform(
|
|
|
+ args,
|
|
|
+ encodeHospitalPreparationQuery,
|
|
|
+ );
|
|
|
+ const pageNum = Number(params.pageNum ?? 1);
|
|
|
+ const pageSize = Number(params.pageSize ?? 10);
|
|
|
+ const keyword = data.mixture;
|
|
|
+ const workroomId = data.personalStudioId?.toString();
|
|
|
+ const dosageForm = data.dosageForm;
|
|
|
+ const status = data.status;
|
|
|
+
|
|
|
+ const filtered = store.filter(
|
|
|
+ (record) =>
|
|
|
+ matchKeyword(record, keyword) &&
|
|
|
+ matchWorkroom(record, workroomId) &&
|
|
|
+ matchDosageForm(record, dosageForm) &&
|
|
|
+ matchStatus(record, status),
|
|
|
+ );
|
|
|
+ const start = (pageNum - 1) * pageSize;
|
|
|
+ const items = filtered
|
|
|
+ .slice(start, start + pageSize)
|
|
|
+ .map((record) => toVo(record));
|
|
|
+
|
|
|
+ const result: PageVO<HospitalPreparationVO> = {
|
|
|
+ total: filtered.length,
|
|
|
+ items,
|
|
|
+ };
|
|
|
+ return delay(() => result);
|
|
|
+}
|
|
|
+
|
|
|
+export function mockGetHospitalPreparationMethod(
|
|
|
+ vo: Partial<HospitalPreparationVO>,
|
|
|
+) {
|
|
|
+ return delay(() => {
|
|
|
+ const record = store.find((item) => String(item.id) === String(vo.id));
|
|
|
+ if (!record) {
|
|
|
+ throw new Error('院内制剂不存在');
|
|
|
+ }
|
|
|
+ return toVo(record);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+export function mockEditHospitalPreparationMethod(
|
|
|
+ vo: HospitalPreparationSubmitVO,
|
|
|
+) {
|
|
|
+ return delay(() => {
|
|
|
+ const dto = encodeHospitalPreparation(vo);
|
|
|
+ const now = new Date().toISOString();
|
|
|
+
|
|
|
+ if (vo.id) {
|
|
|
+ const index = store.findIndex(
|
|
|
+ (item) => String(item.id) === String(vo.id),
|
|
|
+ );
|
|
|
+ if (index === -1) {
|
|
|
+ throw new Error('院内制剂不存在');
|
|
|
+ }
|
|
|
+ store[index] = {
|
|
|
+ ...store[index],
|
|
|
+ ...dto,
|
|
|
+ updateTime: now,
|
|
|
+ };
|
|
|
+ return String(vo.id);
|
|
|
+ }
|
|
|
+
|
|
|
+ const id = String(nextId++);
|
|
|
+ store.unshift({
|
|
|
+ ...dto,
|
|
|
+ id,
|
|
|
+ createTime: now,
|
|
|
+ updateTime: now,
|
|
|
+ });
|
|
|
+ return id;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+export function mockDeleteHospitalPreparationMethod(
|
|
|
+ vo: Pick<HospitalPreparationVO, 'id'>,
|
|
|
+) {
|
|
|
+ return delay(() => {
|
|
|
+ const before = store.length;
|
|
|
+ store = store.filter((item) => String(item.id) !== String(vo.id));
|
|
|
+ if (store.length === before) {
|
|
|
+ throw new Error('院内制剂不存在');
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/** 仅用于本地调试,重置 mock 数据 */
|
|
|
+export function resetHospitalPreparationMockStore() {
|
|
|
+ nextId = 100;
|
|
|
+ store = createInitialStore();
|
|
|
+}
|