system.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. import type { RouteMeta } from 'vue-router';
  2. import type { TransformData, TransformList, TransformRecord } from '#/api';
  3. import { http } from '#/api';
  4. import {
  5. fromEnterprise,
  6. fromOrganization,
  7. fromProject,
  8. fromRole,
  9. fromTisane,
  10. fromUser,
  11. toEnterprise,
  12. toOrganization,
  13. toProject,
  14. toRole,
  15. toTisane,
  16. toUser,
  17. } from '#/api/model';
  18. import {
  19. fromMenus,
  20. normalizeMenuTreeSelect,
  21. type TreeSelectMenuNode,
  22. } from '#/api/model/menu';
  23. export interface RoleMenuTreeselect {
  24. menus: TreeSelectMenuNode[];
  25. checkedKeys: string[];
  26. }
  27. export namespace SystemModel {
  28. export interface Project extends TransformRecord {
  29. id: string;
  30. institutionName?: string;
  31. createDate?: string;
  32. updateDate?: string;
  33. institutionCode?: string;
  34. institutionId?: string;
  35. itemName: string;
  36. itemCode?: string;
  37. sourceCode?: string;
  38. sourceName?: string;
  39. }
  40. export interface Role extends TransformRecord {
  41. [key: string]: any;
  42. id: string;
  43. name: string;
  44. code?: string;
  45. permissions: string[];
  46. deptIds?: Array<number | string>;
  47. roleSort?: number;
  48. remark?: string;
  49. status: 0 | 1;
  50. }
  51. export interface User extends TransformRecord {
  52. id: string;
  53. access: string;
  54. name: string;
  55. worker?: string;
  56. mobile?: string;
  57. phone?: string;
  58. roles?: Array<Role | string>;
  59. sititutionId?: string;
  60. pid?: string;
  61. password?: string;
  62. remark?: string;
  63. stateSel?: 0 | 1;
  64. status?: 0 | 1;
  65. roleNames?: string;
  66. /** 用户类型:01 点评专家 */
  67. userType?: string;
  68. createUser?: string;
  69. hospitalName?: string;
  70. }
  71. export interface Organization extends TransformRecord {
  72. id: string;
  73. name: string;
  74. code?: string;
  75. superior?: string;
  76. createTime?: string;
  77. createUser?: string;
  78. parentInstitutionId?: string;
  79. parentinstitutionSelsourceName?: string;
  80. /** 机构类型:1院区 2管理部门 3医疗机构 */
  81. deptType?: number;
  82. type?: string;
  83. creditCode?: string;
  84. medicineCenter?: string;
  85. remark?: string;
  86. }
  87. /** 企业 */
  88. export interface Enterprise extends TransformRecord {
  89. id: string;
  90. name: string;
  91. code?: string;
  92. /** 类型展示文案 */
  93. type?: string;
  94. enterpriseType?: number;
  95. remark?: string;
  96. }
  97. /** 煎药中心 */
  98. export interface Tisane extends TransformRecord {
  99. id: string;
  100. name: string;
  101. code?: string;
  102. /** 类型展示文案 */
  103. type?: string;
  104. enterpriseType?: number;
  105. institutionId?: string;
  106. relatedOrganizations?: string;
  107. enterpriseId?: string;
  108. relatedEnterprise?: string;
  109. hospitalCode?: string;
  110. hospitalName?: string;
  111. yardCode?: string;
  112. yardName?: string;
  113. medCenterId?: string;
  114. medCenterName?: string;
  115. remark?: string;
  116. }
  117. export interface Menu {
  118. type: 'button' | 'catalog' | 'menu';
  119. id: string;
  120. pid?: string;
  121. name: string;
  122. path: string;
  123. component?: string;
  124. meta: Partial<RouteMeta>;
  125. children?: Menu[];
  126. }
  127. }
  128. function normalizeDeptList(data: unknown): TransformData[] {
  129. if (Array.isArray(data)) return data;
  130. if (data && typeof data === 'object') {
  131. const record = data as TransformData;
  132. if (Array.isArray(record.rows)) return record.rows;
  133. if (Array.isArray(record.list)) return record.list;
  134. if (Array.isArray(record.items)) return record.items;
  135. }
  136. return [];
  137. }
  138. /** 获取医疗机构列表(deptType=3,用于处方筛选等) */
  139. export function listMedicalInstitutionsMethod() {
  140. return http.get<SystemModel.Organization[], TransformData[]>(
  141. `/manager/tcmp-pc/dept/allList`,
  142. {
  143. params: { deptType: 3 },
  144. cacheFor: 60_000,
  145. transform(data) {
  146. return normalizeDeptList(data).map((item) => fromOrganization(item));
  147. },
  148. },
  149. );
  150. }
  151. /** 根据医疗机构 deptId 获取院区列表(deptType=1) */
  152. export function listCampusByParentMethod(parentId?: string | number) {
  153. if (parentId === undefined || parentId === null || parentId === '') {
  154. return Promise.resolve([] as SystemModel.Organization[]);
  155. }
  156. return http.get<SystemModel.Organization[], TransformData[]>(
  157. `/manager/tcmp-pc/dept/allList`,
  158. {
  159. params: { parentId, deptType: 1 },
  160. cacheFor: 0,
  161. transform(data) {
  162. return normalizeDeptList(data).map((item) => fromOrganization(item));
  163. },
  164. },
  165. );
  166. }
  167. function normalizeParentIds(
  168. parentIds?: Array<string | number> | string | number,
  169. ): string[] {
  170. if (parentIds === undefined || parentIds === null || parentIds === '') {
  171. return [];
  172. }
  173. const list = Array.isArray(parentIds) ? parentIds : [parentIds];
  174. return list
  175. .filter((id) => id !== undefined && id !== null && id !== '')
  176. .map(String);
  177. }
  178. /** ApiSelect 用:按医疗机构 deptId(可多选)加载院区 */
  179. export async function listCampusByParentApiMethod(params?: {
  180. parentId?: string | number;
  181. parentIds?: Array<string | number>;
  182. /** 逗号分隔的 deptId,用于多选医疗机构时稳定传参 */
  183. parentKey?: string;
  184. }) {
  185. const ids = params?.parentKey
  186. ? params.parentKey.split(',').filter(Boolean)
  187. : normalizeParentIds(params?.parentIds ?? params?.parentId);
  188. if (!ids.length) {
  189. return [] as SystemModel.Organization[];
  190. }
  191. const results = await Promise.allSettled(
  192. ids.map((parentId) => listCampusByParentMethod(parentId)),
  193. );
  194. const map = new Map<string, SystemModel.Organization>();
  195. for (const result of results) {
  196. if (result.status !== 'fulfilled') continue;
  197. for (const item of result.value) {
  198. const optionKey = item.code || item.id;
  199. if (optionKey) {
  200. map.set(optionKey, item);
  201. }
  202. }
  203. }
  204. return Array.from(map.values());
  205. }
  206. // 获取机构(部门)列表
  207. export function listOrganizationsMethod(
  208. page = 1,
  209. size = 20,
  210. query?: Partial<SystemModel.Organization>,
  211. ) {
  212. return http.get<TransformList<SystemModel.Organization>, TransformList>(
  213. `/manager/tcmp-pc/dept/list`,
  214. {
  215. params: { pageNum: page, pageSize: size, ...toOrganization(query) },
  216. cacheFor: 0,
  217. transform({ items, ...data }) {
  218. const rows = items ?? [];
  219. return {
  220. ...data,
  221. items: rows.map((item) => fromOrganization(item)),
  222. };
  223. },
  224. },
  225. );
  226. }
  227. // 获取项目管理列表
  228. export function listProjectsMethod(page = 1, size = 20, query?: TransformData) {
  229. return http.post<TransformList<SystemModel.Project>, TransformList>(
  230. `/basis/institution/listPage`,
  231. toProject(query),
  232. {
  233. params: { page, limit: size },
  234. transform({ items, ...data }) {
  235. return { ...data, items: items.map((item) => fromProject(item)) };
  236. },
  237. },
  238. );
  239. }
  240. export function listRolesMethod(
  241. page = 1,
  242. size = 20,
  243. query?: Partial<SystemModel.Role>,
  244. ) {
  245. return http.get<TransformList<SystemModel.Role>, TransformList>(
  246. `/manager/system/role/list`,
  247. {
  248. params: { pageNum: page, pageSize: size, ...toRole(query) },
  249. cacheFor: 0,
  250. transform({ items, ...data }) {
  251. const rows = items ?? [];
  252. return {
  253. ...data,
  254. items: rows.map((item) => fromRole(item)),
  255. };
  256. },
  257. },
  258. );
  259. }
  260. export function getRoleMethod(id: string) {
  261. return http.get<SystemModel.Role, TransformData>(
  262. `/manager/system/role/${id}`,
  263. {
  264. cacheFor: 0,
  265. transform(data) {
  266. return fromRole(data);
  267. },
  268. },
  269. );
  270. }
  271. export function optionsRoleMethod() {
  272. return http.get<SystemModel.Role[], TransformData[]>(
  273. `/manager/system/role/optionselect`,
  274. {
  275. transform(data) {
  276. return (Array.isArray(data) ? data : []).map((item) => fromRole(item));
  277. },
  278. },
  279. );
  280. }
  281. // 获取来源平台
  282. export function listSourcePlatformMethod() {
  283. return http.Post<SystemModel.Project[], TransformData[]>(
  284. `/basis/institution/sourceList`,
  285. {
  286. transform(data) {
  287. return data.map((item) => fromProject(item));
  288. },
  289. },
  290. );
  291. }
  292. // 获取全部机构(用于上级机构下拉)
  293. export async function listOrganizationsMethodAll() {
  294. const { items } = await listOrganizationsMethod(1, 9999);
  295. return items;
  296. }
  297. function fromDeptTreeSelect(nodes?: TransformData[]): TransformData[] {
  298. return (nodes ?? []).map((node) => ({
  299. id: String(node.id ?? ''),
  300. pid: String(node.id ?? ''),
  301. name: node.label,
  302. children: fromDeptTreeSelect(node.children),
  303. }));
  304. }
  305. // 获取部门树(用户表单所属机构)
  306. export function listUsersInstitutionMethodTree() {
  307. return http.get<TransformData[], TransformData[]>(
  308. `/manager/system/user/deptTree`,
  309. {
  310. transform(data) {
  311. return fromDeptTreeSelect(Array.isArray(data) ? data : []);
  312. },
  313. },
  314. );
  315. }
  316. // 编辑机构
  317. export function editOrganizationMethod(
  318. data: Partial<SystemModel.Organization>,
  319. ) {
  320. return http.post(
  321. data.id
  322. ? `/basis/medicalinstitutionsMgr/update`
  323. : `/basis/medicalinstitutionsMgr/Add`,
  324. toOrganization(data),
  325. );
  326. }
  327. export function editRoleMethod(data: Partial<SystemModel.Role>) {
  328. const isCreate = !data?.id;
  329. const body = toRole(data, isCreate ? { create: true } : { update: true });
  330. return isCreate
  331. ? http.post(`/manager/system/role`, body)
  332. : http.put(`/manager/system/role`, body);
  333. }
  334. export function updateRoleStatusMethod(
  335. roleId: string,
  336. data: Pick<SystemModel.Role, 'name' | 'status'>,
  337. ) {
  338. const id = Number(roleId) || roleId;
  339. return http.put(`/manager/system/role/changeStatus`, {
  340. roleId: id,
  341. roleName: data.name,
  342. status: String(data.status),
  343. });
  344. }
  345. export function deleteRoleMethod(data: Pick<SystemModel.Role, 'id'>) {
  346. return deleteRolesMethod([data]);
  347. }
  348. export function deleteRolesMethod(params: Pick<SystemModel.Role, 'id'>[]) {
  349. const roleIds = params
  350. .map((item) => item.id)
  351. .filter(Boolean)
  352. .join(',');
  353. return http.delete(`/manager/system/role/${roleIds}`);
  354. }
  355. // 获取用户列表
  356. export function listUsersMethod(
  357. page = 1,
  358. size = 20,
  359. query?: Partial<SystemModel.User>,
  360. ) {
  361. return http.get<TransformList<SystemModel.User>, TransformList>(
  362. `/manager/system/user/list`,
  363. {
  364. params: { pageNum: page, pageSize: size, ...toUser(query) },
  365. cacheFor: 0, // 或 localCache: null,关闭该 GET 的内存缓存
  366. transform({ items, ...data }) {
  367. const rows = items ?? [];
  368. return {
  369. ...data,
  370. items: rows.map((item) => fromUser(item)),
  371. };
  372. },
  373. },
  374. );
  375. }
  376. // 编辑或新增用户
  377. // 编辑项目
  378. export function editProjectMethod(data: Partial<SystemModel.Project>) {
  379. return http.post(
  380. data.id ? `/basis/institution/update` : `/basis/institution/Add`,
  381. toProject(data),
  382. );
  383. }
  384. export function editUserMethod(data: Partial<SystemModel.User>) {
  385. const body = toUser(data);
  386. return data?.id || data?.pid
  387. ? http.put(`/manager/system/user`, body)
  388. : http.post(`/manager/system/user`, body);
  389. }
  390. // 用户状态更改
  391. export function updateUserStatusMethod(
  392. userId: string,
  393. { status }: { status: 0 | 1 },
  394. ) {
  395. return http.put(`/manager/system/user/changeStatus`, {
  396. userId,
  397. status: String(status),
  398. });
  399. }
  400. export function getUserMethod(id: string) {
  401. return http.get<SystemModel.User, TransformData>(
  402. `/manager/system/user/${id}`,
  403. {
  404. transform(data) {
  405. return fromUser(data);
  406. },
  407. },
  408. );
  409. }
  410. /** 重置用户登录密码 */
  411. export function resetUserPasswordMethod(data: {
  412. oldPassword: string;
  413. password: string;
  414. userId: string;
  415. }) {
  416. return http.put(`/manager/system/user/resetPwd`, {
  417. oldPassword: data.oldPassword,
  418. password: data.password,
  419. userId: data.userId,
  420. });
  421. }
  422. export function deleteUserMethod(data: Pick<SystemModel.User, 'id' | 'pid'>) {
  423. return deleteUsersMethod([data]);
  424. }
  425. export function deleteUsersMethod(
  426. params: Pick<SystemModel.User, 'id' | 'pid'>[],
  427. ) {
  428. const userIds = params
  429. .map((item) => item.pid ?? item.id)
  430. .filter(Boolean)
  431. .join(',');
  432. return http.delete(`/manager/system/user/${userIds}`);
  433. }
  434. // 删除机构
  435. export function deleteOrganizationMethod(
  436. data: Pick<SystemModel.Organization, 'id'>,
  437. ) {
  438. return deleteOrganizationsMethod([data]);
  439. }
  440. export function deleteOrganizationsMethod(
  441. params: Pick<SystemModel.Organization, 'id'>[],
  442. ) {
  443. return http.post(`/basis/medicalinstitutionsMgr/BatchDelete`, void 0, {
  444. params: { ids: params.map((item) => item.id).join(',') },
  445. });
  446. }
  447. function normalizeEnterpriseList(data: unknown): TransformData[] {
  448. if (Array.isArray(data)) return data;
  449. if (data && typeof data === 'object') {
  450. const record = data as TransformData;
  451. if (Array.isArray(record.rows)) return record.rows;
  452. if (Array.isArray(record.list)) return record.list;
  453. if (Array.isArray(record.items)) return record.items;
  454. }
  455. return [];
  456. }
  457. /** 获取煎药中心列表(enterprise/allList?enterpriseType=1,用于处方筛选等) */
  458. export function listDecoctionCentersAllMethod() {
  459. return http.get<SystemModel.Enterprise[], TransformData[]>(
  460. `/manager/tcmp-pc/enterprise/allList`,
  461. {
  462. params: { enterpriseType: 1 },
  463. cacheFor: 60_000,
  464. transform(data) {
  465. return normalizeEnterpriseList(data).map((item) =>
  466. fromEnterprise(item),
  467. );
  468. },
  469. },
  470. );
  471. }
  472. /** 获取企业分页列表 */
  473. export function listEnterprisesMethod(
  474. page = 1,
  475. size = 20,
  476. query?: Partial<SystemModel.Enterprise>,
  477. ) {
  478. return http.get<TransformList<SystemModel.Enterprise>, TransformList>(
  479. `/manager/tcmp-pc/enterprise/list`,
  480. {
  481. params: { pageNum: page, pageSize: size, ...toEnterprise(query) },
  482. cacheFor: 0,
  483. transform({ items, ...data }) {
  484. const rows = items ?? [];
  485. return {
  486. ...data,
  487. items: rows.map((item) => fromEnterprise(item)),
  488. };
  489. },
  490. },
  491. );
  492. }
  493. /** 获取机构煎药中心全量列表(用于岗位人员资质筛选等) */
  494. export function listMedicineCentersAllMethod(
  495. query?: Partial<SystemModel.Tisane>,
  496. ) {
  497. return http.get<SystemModel.Tisane[], TransformData[]>(
  498. `/manager/tcmp-pc/medicine/allList`,
  499. {
  500. params: toTisane(query),
  501. cacheFor: 60_000,
  502. transform(data) {
  503. return normalizeEnterpriseList(data).map((item) => fromTisane(item));
  504. },
  505. },
  506. );
  507. }
  508. /** 获取煎药中心分页列表 */
  509. export function listMedicineCentersMethod(
  510. page = 1,
  511. size = 20,
  512. query?: Partial<SystemModel.Tisane>,
  513. ) {
  514. return http.get<TransformList<SystemModel.Tisane>, TransformList>(
  515. `/manager/tcmp-pc/medicine/list`,
  516. {
  517. params: { pageNum: page, pageSize: size, ...toTisane(query) },
  518. cacheFor: 0,
  519. transform({ items, ...data }) {
  520. const rows = items ?? [];
  521. return {
  522. ...data,
  523. items: rows.map((item) => fromTisane(item)),
  524. };
  525. },
  526. },
  527. );
  528. }
  529. export function getMenusMethod() {
  530. return http.post<SystemModel.Menu[], TransformData[]>(
  531. `/admin/menu/allMenu`,
  532. void 0,
  533. {
  534. transform(data) {
  535. return fromMenus(data);
  536. },
  537. },
  538. );
  539. }
  540. /** 获取菜单下拉树列表 */
  541. export function getMenuTreeselectMethod() {
  542. return http.get<TreeSelectMenuNode[], TreeSelectMenuNode[]>(
  543. `/manager/system/menu/treeselect`,
  544. {
  545. transform(data) {
  546. return normalizeMenuTreeSelect(Array.isArray(data) ? data : []);
  547. },
  548. },
  549. );
  550. }
  551. /** 加载对应角色菜单列表树(含已勾选菜单) */
  552. export async function getRoleMenuTreeselectMethod(
  553. roleId: string,
  554. ): Promise<RoleMenuTreeselect> {
  555. const data = await http.get<TransformData, TransformData>(
  556. `/manager/system/menu/roleMenuTreeselect/${roleId}`,
  557. { cacheFor: 0 },
  558. );
  559. const checkedKeys = (
  560. Array.isArray(data?.checkedKeys) ? data.checkedKeys : []
  561. ).map((key) => String(key));
  562. let menus = normalizeMenuTreeSelect(
  563. Array.isArray(data?.menus) ? data.menus : [],
  564. );
  565. if (menus.length === 0) {
  566. menus = await getMenuTreeselectMethod();
  567. }
  568. return { menus, checkedKeys };
  569. }