medical-talk.mock.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import type {
  2. MedicalTalkDTO,
  3. MedicalTalkSubmitVO,
  4. MedicalTalkVO,
  5. } from './medical-talk.schema';
  6. import type { PageQueryMethodArgs } from '#/request/schema';
  7. import type { PageVO } from '#/request/schema/record';
  8. import { pageQueryArgsTransform } from '#/request/schema';
  9. import {
  10. decodeMedicalTalk,
  11. encodeMedicalTalk,
  12. encodeMedicalTalkQuery,
  13. } from './medical-talk.schema';
  14. /** 后端接口就绪后改为 false */
  15. export const USE_MEDICAL_TALK_MOCK = false;
  16. type MethodLike<T> = PromiseLike<T> & {
  17. send?: (force?: boolean) => PromiseLike<T>;
  18. };
  19. const SEED_RECORDS: Omit<
  20. MedicalTalkDTO,
  21. 'createTime' | 'id' | 'personalStudioId' | 'updateTime'
  22. >[] = [
  23. {
  24. name: '浅谈《伤寒论》六经辨证在现代临床中的应用',
  25. type: '1',
  26. author: '张教授',
  27. content:
  28. '《伤寒论》六经辨证是中医辨证论治的重要基石。在现代临床中,结合现代医学检查结果,灵活运用六经辨证,可显著提高诊疗效果。',
  29. browseCount: 328,
  30. praiseCount: 45,
  31. commentCount: 12,
  32. createBy: '张教授',
  33. fileUrl: '',
  34. },
  35. {
  36. name: '春季养生与肝脾调理',
  37. type: '2',
  38. author: '李医师',
  39. content:
  40. '春季属木,与肝相应。养生重在疏肝理气、健脾和胃,饮食宜清淡,起居有常,情志舒畅。',
  41. browseCount: 256,
  42. praiseCount: 38,
  43. commentCount: 8,
  44. createBy: '李医师',
  45. fileUrl: '',
  46. },
  47. {
  48. name: '疑难病案:顽固性失眠的辨证思路',
  49. type: '3',
  50. author: '王主任',
  51. content:
  52. '患者失眠三年,多方求治无效。经四诊合参,辨为心肾不交,以交泰丸加减治疗,两周后睡眠明显改善。',
  53. browseCount: 189,
  54. praiseCount: 52,
  55. commentCount: 15,
  56. createBy: '王主任',
  57. fileUrl: '',
  58. },
  59. {
  60. name: '经方学术讨论:小柴胡汤的临床应用',
  61. type: '0',
  62. author: '赵教授',
  63. content:
  64. '小柴胡汤为和解少阳之主方,临床适用范围广泛。本文结合经典原文与现代研究,探讨其辨证要点与加减变化。',
  65. browseCount: 412,
  66. praiseCount: 67,
  67. commentCount: 23,
  68. createBy: '赵教授',
  69. fileUrl: '',
  70. },
  71. ];
  72. function createInitialStore(): MedicalTalkDTO[] {
  73. const records: MedicalTalkDTO[] = [];
  74. for (let index = 0; index < 67; index += 1) {
  75. const seed = SEED_RECORDS[index % SEED_RECORDS.length] ?? SEED_RECORDS[0];
  76. if (!seed) continue;
  77. const day = String((index % 28) + 1).padStart(2, '0');
  78. const month = String((index % 12) + 1).padStart(2, '0');
  79. records.push({
  80. ...seed,
  81. id: String(index + 1),
  82. personalStudioId: '327477138296832',
  83. browseCount: (seed.browseCount ?? 0) + (index % 20),
  84. praiseCount: (seed.praiseCount ?? 0) + (index % 10),
  85. commentCount: (seed.commentCount ?? 0) + (index % 5),
  86. createTime: `2026-${month}-${day}T10:00:00`,
  87. updateTime: `2026-05-${day}T10:00:00`,
  88. });
  89. }
  90. return records;
  91. }
  92. let nextId = 100;
  93. let store = createInitialStore();
  94. function delay<T>(runner: () => Promise<T> | T, ms = 120): MethodLike<T> {
  95. const run = async () => {
  96. await new Promise((resolve) => setTimeout(resolve, ms));
  97. return runner();
  98. };
  99. const promise = run();
  100. return Object.assign(promise, { send: run });
  101. }
  102. function matchKeyword(record: MedicalTalkDTO, keyword?: string) {
  103. if (!keyword) return true;
  104. const text = [record.name, record.author, record.content, record.createBy]
  105. .filter(Boolean)
  106. .join(' ');
  107. return text.includes(keyword);
  108. }
  109. function matchWorkroom(record: MedicalTalkDTO, workroomId?: string) {
  110. if (!workroomId) return true;
  111. return String(record.personalStudioId ?? '') === String(workroomId);
  112. }
  113. function matchCategory(record: MedicalTalkDTO, type?: string) {
  114. if (!type) return true;
  115. return String(record.type ?? '') === String(type);
  116. }
  117. function sortRecords(records: MedicalTalkDTO[]) {
  118. return records.toSorted((a, b) => {
  119. const timeA = a.createTime ? Date.parse(a.createTime) : 0;
  120. const timeB = b.createTime ? Date.parse(b.createTime) : 0;
  121. return timeB - timeA;
  122. });
  123. }
  124. function toVo(dto: MedicalTalkDTO): MedicalTalkVO {
  125. return decodeMedicalTalk(dto);
  126. }
  127. export function mockListMedicalTalkMethod(...args: PageQueryMethodArgs) {
  128. const { params, data } = pageQueryArgsTransform(args, encodeMedicalTalkQuery);
  129. const pageNum = Number(params.pageNum ?? 1);
  130. const pageSize = Number(params.pageSize ?? 20);
  131. const keyword = data.mixture;
  132. const workroomId = data.personalStudioId?.toString();
  133. const type = data.type?.toString();
  134. const filtered = sortRecords(
  135. store.filter(
  136. (record) =>
  137. matchKeyword(record, keyword) &&
  138. matchWorkroom(record, workroomId) &&
  139. matchCategory(record, type),
  140. ),
  141. );
  142. const start = (pageNum - 1) * pageSize;
  143. const items = filtered
  144. .slice(start, start + pageSize)
  145. .map((record) => toVo(record));
  146. const result: PageVO<MedicalTalkVO> = {
  147. total: filtered.length,
  148. items,
  149. };
  150. return delay(() => result);
  151. }
  152. export function mockGetMedicalTalkMethod(vo: Partial<MedicalTalkVO>) {
  153. return delay(() => {
  154. const record = store.find((item) => String(item.id) === String(vo.id));
  155. if (!record) {
  156. throw new Error('医话不存在');
  157. }
  158. return toVo(record);
  159. });
  160. }
  161. export function mockEditMedicalTalkMethod(vo: MedicalTalkSubmitVO) {
  162. return delay(() => {
  163. const dto = encodeMedicalTalk(vo);
  164. const now = new Date().toISOString();
  165. if (vo.id) {
  166. const index = store.findIndex(
  167. (item) => String(item.id) === String(vo.id),
  168. );
  169. if (index === -1) {
  170. throw new Error('医话不存在');
  171. }
  172. store[index] = {
  173. ...store[index],
  174. ...dto,
  175. updateTime: now,
  176. };
  177. return String(vo.id);
  178. }
  179. const id = String(nextId++);
  180. store.unshift({
  181. ...dto,
  182. id,
  183. browseCount: 0,
  184. praiseCount: 0,
  185. commentCount: 0,
  186. createBy: dto.author ?? '当前用户',
  187. createTime: now,
  188. updateTime: now,
  189. });
  190. return id;
  191. });
  192. }
  193. export function mockDeleteMedicalTalkMethod(vo: Pick<MedicalTalkVO, 'id'>) {
  194. return delay(() => {
  195. const before = store.length;
  196. store = store.filter((item) => String(item.id) !== String(vo.id));
  197. if (store.length === before) {
  198. throw new Error('医话不存在');
  199. }
  200. return null;
  201. });
  202. }
  203. /** 仅用于本地调试,重置 mock 数据 */
  204. export function resetMedicalTalkMockStore() {
  205. nextId = 100;
  206. store = createInitialStore();
  207. }