index.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
  2. import { setCurrentPatientType } from '../../patientTypeSlice';
  3. import { BodyPart } from '@/API/bodyPart';
  4. import { PatientType } from '@/API/patientType';
  5. import {
  6. SelectionState,
  7. setSelected,
  8. } from '@/states/patient/register/SelectionTypeSlice';
  9. import { setCurrentBodyPart } from '../../bodyPartSlice';
  10. import { fetchProcedures, Procedure } from '@/API/patient/procedureActions';
  11. import { fetchViews } from '@/API/patient/viewActions';
  12. export type { Procedure };
  13. // 体位类型
  14. export interface View {
  15. internal_id: string;
  16. view_id: string;
  17. view_name: string;
  18. view_name_local: string;
  19. view_other_name: string;
  20. view_description: string;
  21. view_position: string;
  22. application: string;
  23. anatomic_region: string;
  24. patient_type: string;
  25. body_part_id: string;
  26. view_icon_name: string;
  27. view_big_icon_name: string;
  28. view_coach_name: string;
  29. modality: string;
  30. // config_object: any;
  31. tech_template: string;
  32. img_proc_template: string;
  33. sort: number;
  34. is_enabled: boolean;
  35. product: string;
  36. is_pre_install: boolean;
  37. }
  38. // 协议类型
  39. // export interface Procedure {
  40. // ProcedureID: string;
  41. // ProcedureCode: string;
  42. // ProcedureName: string;
  43. // ProcedureOtherName: string;
  44. // ProcedureDescription: string;
  45. // PatientType: string;
  46. // ProcedureGroupID: string;
  47. // ProcedureType: string;
  48. // FastSearch: boolean;
  49. // Enable: boolean;
  50. // Order: number;
  51. // UserGroupID: string;
  52. // ProcedureCategory: string;
  53. // Modality: string;
  54. // IsImplanted: boolean;
  55. // MagFactor: number;
  56. // // ProcedureViews: View[];
  57. // // ProcedureViewRelations: any[];
  58. // ClinicProtocol: boolean;
  59. // IsFactoryDefault: boolean;
  60. // MinBMI: number;
  61. // MaxBMI: number;
  62. // AutoDecompression: boolean;
  63. // ConfigObjectValue: string;
  64. // }
  65. interface ViewSelectionState {
  66. selectedViews: View[]; // 已选择体位列表
  67. availableViews: View[]; // 待选择体位列表
  68. protocols: Procedure[]; // 协议列表(只会出现在待选择列表)
  69. currentBodyPart: BodyPart | null;
  70. currentPatientType: PatientType | null;
  71. currentSelectionType: SelectionState;
  72. }
  73. const initialState: ViewSelectionState = {
  74. selectedViews: [],
  75. availableViews: [
  76. {
  77. internal_id: '1',
  78. view_id: 'AP',
  79. view_name: 'Anteroposterior',
  80. view_name_local: '前后位',
  81. view_other_name: 'AP View',
  82. view_description: '前后体位描述',
  83. view_position: 'Standing',
  84. application: 'General',
  85. anatomic_region: 'Chest',
  86. patient_type: 'Adult',
  87. body_part_id: 'CHEST',
  88. view_icon_name: 'ap_icon.png',
  89. view_big_icon_name: 'ap_big_icon.png',
  90. view_coach_name: 'ap_coach.png',
  91. modality: 'X-Ray',
  92. tech_template: 'default',
  93. img_proc_template: 'default',
  94. sort: 1,
  95. is_enabled: true,
  96. product: 'Standard',
  97. is_pre_install: true,
  98. },
  99. {
  100. internal_id: '2',
  101. view_id: 'LAT',
  102. view_name: 'Lateral',
  103. view_name_local: '侧位',
  104. view_other_name: 'LAT View',
  105. view_description: '侧体位描述',
  106. view_position: 'Standing',
  107. application: 'General',
  108. anatomic_region: 'Chest',
  109. patient_type: 'Adult',
  110. body_part_id: 'CHEST',
  111. view_icon_name: 'lat_icon.png',
  112. view_big_icon_name: 'lat_big_icon.png',
  113. view_coach_name: 'lat_coach.png',
  114. modality: 'X-Ray',
  115. tech_template: 'default',
  116. img_proc_template: 'default',
  117. sort: 2,
  118. is_enabled: true,
  119. product: 'Standard',
  120. is_pre_install: true,
  121. },
  122. ],
  123. protocols: [],
  124. currentBodyPart: null,
  125. currentPatientType: null,
  126. currentSelectionType: { selected: 'protocol' },
  127. };
  128. export interface FilterCondition {
  129. selection: string;
  130. patientType: string | null;
  131. bodyPart: string | null;
  132. }
  133. export const fetchViewsOrProtocols = createAsyncThunk(
  134. 'data/fetchData',
  135. async (filter: FilterCondition, { rejectWithValue }) => {
  136. try {
  137. console.log(`触发查询,查询条件是:${JSON.stringify(filter)}`);
  138. if (filter.selection === 'protocol') {
  139. const response = await fetchProcedures(
  140. filter.patientType,
  141. filter.bodyPart,
  142. true
  143. );
  144. return response.data.procedure_list;
  145. }
  146. if (filter.selection === 'view') {
  147. const response = await fetchViews(
  148. filter.patientType,
  149. filter.bodyPart,
  150. true,
  151. null
  152. );
  153. return response.data.view_list;
  154. }
  155. } catch (error) {
  156. return rejectWithValue(error.message);
  157. }
  158. }
  159. );
  160. const viewSelectionSlice = createSlice({
  161. name: 'viewSelection',
  162. initialState,
  163. reducers: {
  164. // 添加体位到已选择体位列表
  165. addSelectedView(state, action: PayloadAction<View>) {
  166. state.selectedViews.push(action.payload);
  167. },
  168. // 添加协议中的所有体位到已选择体位列表
  169. // eslint-disable-next-line
  170. addProtocolViews(state, action: PayloadAction<Procedure>) {
  171. // 假设协议中包含 ProcedureViews 属性,存储体位数组
  172. // todo 这里涉及到基于协议查询其名下的体位,然后再添加
  173. // if (Array.isArray(action.payload.ProcedureViews)) {
  174. // state.selectedViews.push(...action.payload.ProcedureViews);
  175. // }
  176. },
  177. // 可根据需要添加其它 reducer,例如设置 availableViews、Procedures 等
  178. setAvailableViews(state, action: PayloadAction<View[]>) {
  179. state.availableViews = action.payload;
  180. },
  181. setProtocols(state, action: PayloadAction<Procedure[]>) {
  182. state.protocols = action.payload;
  183. },
  184. },
  185. extraReducers: (builder) => {
  186. builder
  187. .addCase(setCurrentPatientType, (state, action) => {
  188. const currentPatientType = action.payload;
  189. if (currentPatientType) {
  190. // console.log(`在view section中感知到 current patient type 变化: ${currentPatientType.patient_type_name}`);
  191. // 基于过滤条件查询协议或者体位
  192. state.currentPatientType = currentPatientType;
  193. }
  194. })
  195. .addCase(setCurrentBodyPart, (state, action) => {
  196. const currentBodyPart = action.payload;
  197. if (currentBodyPart) {
  198. state.currentBodyPart = currentBodyPart;
  199. // console.log(`在view section中感知到 currentBodyPart 变化: ${JSON.stringify(currentBodyPart, null, 2)}`);
  200. }
  201. })
  202. .addCase(setSelected, (state, action) => {
  203. console
  204. .log
  205. // `在view section中感知到 currentSelectionType : ${action.payload}`
  206. ();
  207. state.currentSelectionType.selected = action.payload;
  208. })
  209. // eslint-disable-next-line
  210. .addCase(fetchViewsOrProtocols.pending, (state, action) => {
  211. console.log(`查询view或者protocals:pending`);
  212. })
  213. .addCase(fetchViewsOrProtocols.fulfilled, (state, action) => {
  214. // console.log(`查询view或者protocals: fulfilled ${JSON.stringify(action.payload)}`);
  215. if (action.meta.arg.selection === 'view') {
  216. state.availableViews = action.payload as unknown as View[];
  217. console.log(
  218. `查询 Views : fulfilled ${JSON.stringify(state.availableViews)}`
  219. );
  220. } else {
  221. state.protocols = action.payload as unknown as Procedure[];
  222. console.log(
  223. `查询protocals: fulfilled ${JSON.stringify(state.protocols)}`
  224. );
  225. }
  226. })
  227. // eslint-disable-next-line
  228. .addCase(fetchViewsOrProtocols.rejected, (state, action) => {
  229. console.log(`查询view或者protocals: rejected`);
  230. });
  231. },
  232. });
  233. export const {
  234. addSelectedView,
  235. addProtocolViews,
  236. setAvailableViews,
  237. setProtocols,
  238. } = viewSelectionSlice.actions;
  239. export default viewSelectionSlice.reducer;