api.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. import { Request, Response } from 'express';
  2. const now = Math.floor(Date.now() / 1000);
  3. const deptTree = [
  4. {
  5. id: 1,
  6. parentId: 0,
  7. name: '研发部',
  8. path: '/1',
  9. sort: 1,
  10. deptType: 'DEV',
  11. remark: '',
  12. status: 1,
  13. createTime: now - 86400 * 30,
  14. children: [
  15. {
  16. id: 4,
  17. parentId: 1,
  18. name: '前端组',
  19. path: '/1/4',
  20. sort: 1,
  21. deptType: 'DEV',
  22. remark: '',
  23. status: 1,
  24. createTime: now - 86400 * 28,
  25. },
  26. {
  27. id: 5,
  28. parentId: 1,
  29. name: '后端组',
  30. path: '/1/5',
  31. sort: 2,
  32. deptType: 'DEV',
  33. remark: '',
  34. status: 1,
  35. createTime: now - 86400 * 28,
  36. },
  37. ],
  38. },
  39. {
  40. id: 2,
  41. parentId: 0,
  42. name: '市场部',
  43. path: '/2',
  44. sort: 2,
  45. deptType: 'NORMAL',
  46. remark: '',
  47. status: 1,
  48. createTime: now - 86400 * 30,
  49. },
  50. {
  51. id: 3,
  52. parentId: 0,
  53. name: '运营部',
  54. path: '/3',
  55. sort: 3,
  56. deptType: 'NORMAL',
  57. remark: '',
  58. status: 1,
  59. createTime: now - 86400 * 30,
  60. },
  61. ];
  62. const products = [
  63. {
  64. id: 1,
  65. code: 'crm',
  66. name: 'CRM 系统',
  67. appKey: 'ak_crm_001',
  68. remark: '客户关系管理',
  69. status: 1,
  70. createTime: now - 86400 * 20,
  71. },
  72. {
  73. id: 2,
  74. code: 'oa',
  75. name: 'OA 系统',
  76. appKey: 'ak_oa_002',
  77. remark: '办公自动化',
  78. status: 1,
  79. createTime: now - 86400 * 15,
  80. },
  81. {
  82. id: 3,
  83. code: 'mall',
  84. name: '电商后台',
  85. appKey: 'ak_mall_003',
  86. remark: '',
  87. status: 2,
  88. createTime: now - 86400 * 10,
  89. },
  90. ];
  91. const users = [
  92. {
  93. id: 1,
  94. username: 'superadmin',
  95. nickname: '超级管理员',
  96. avatar: '',
  97. email: '[email protected]',
  98. phone: '13800000001',
  99. remark: '',
  100. deptId: 0,
  101. status: 1,
  102. createTime: now - 86400 * 60,
  103. },
  104. {
  105. id: 2,
  106. username: 'zhangsan',
  107. nickname: '张三',
  108. avatar: '',
  109. email: '[email protected]',
  110. phone: '13800000002',
  111. remark: '前端开发',
  112. deptId: 4,
  113. status: 1,
  114. createTime: now - 86400 * 25,
  115. },
  116. {
  117. id: 3,
  118. username: 'lisi',
  119. nickname: '李四',
  120. avatar: '',
  121. email: '[email protected]',
  122. phone: '13800000003',
  123. remark: '销售',
  124. deptId: 2,
  125. status: 1,
  126. createTime: now - 86400 * 20,
  127. },
  128. {
  129. id: 4,
  130. username: 'wangwu',
  131. nickname: '王五',
  132. avatar: '',
  133. email: '[email protected]',
  134. phone: '13800000004',
  135. remark: '运营',
  136. deptId: 3,
  137. status: 2,
  138. createTime: now - 86400 * 18,
  139. },
  140. ];
  141. const roles = [
  142. {
  143. id: 1,
  144. productCode: 'crm',
  145. name: '销售经理',
  146. remark: '管理销售团队',
  147. status: 1,
  148. permsLevel: 10,
  149. createTime: now - 86400 * 15,
  150. },
  151. {
  152. id: 2,
  153. productCode: 'crm',
  154. name: '普通销售',
  155. remark: '',
  156. status: 1,
  157. permsLevel: 20,
  158. createTime: now - 86400 * 15,
  159. },
  160. {
  161. id: 3,
  162. productCode: 'crm',
  163. name: '客服',
  164. remark: '只读权限',
  165. status: 1,
  166. permsLevel: 30,
  167. createTime: now - 86400 * 15,
  168. },
  169. {
  170. id: 4,
  171. productCode: 'oa',
  172. name: '审批管理员',
  173. remark: '',
  174. status: 1,
  175. permsLevel: 10,
  176. createTime: now - 86400 * 10,
  177. },
  178. ];
  179. const perms = [
  180. {
  181. id: 1,
  182. productCode: 'crm',
  183. name: '查看客户列表',
  184. code: 'customer:list',
  185. remark: '',
  186. status: 1,
  187. createTime: now - 86400 * 14,
  188. },
  189. {
  190. id: 2,
  191. productCode: 'crm',
  192. name: '创建客户',
  193. code: 'customer:create',
  194. remark: '',
  195. status: 1,
  196. createTime: now - 86400 * 14,
  197. },
  198. {
  199. id: 3,
  200. productCode: 'crm',
  201. name: '编辑客户',
  202. code: 'customer:update',
  203. remark: '',
  204. status: 1,
  205. createTime: now - 86400 * 14,
  206. },
  207. {
  208. id: 4,
  209. productCode: 'crm',
  210. name: '删除客户',
  211. code: 'customer:delete',
  212. remark: '',
  213. status: 1,
  214. createTime: now - 86400 * 14,
  215. },
  216. {
  217. id: 5,
  218. productCode: 'crm',
  219. name: '查看订单',
  220. code: 'order:list',
  221. remark: '',
  222. status: 1,
  223. createTime: now - 86400 * 14,
  224. },
  225. {
  226. id: 6,
  227. productCode: 'crm',
  228. name: '创建订单',
  229. code: 'order:create',
  230. remark: '',
  231. status: 1,
  232. createTime: now - 86400 * 14,
  233. },
  234. {
  235. id: 7,
  236. productCode: 'crm',
  237. name: '导出报表',
  238. code: 'report:export',
  239. remark: '',
  240. status: 1,
  241. createTime: now - 86400 * 14,
  242. },
  243. ];
  244. const members = [
  245. {
  246. id: 1,
  247. productCode: 'crm',
  248. userId: 2,
  249. username: 'zhangsan',
  250. nickname: '张三',
  251. memberType: 'MEMBER',
  252. status: 1,
  253. createTime: now - 86400 * 12,
  254. },
  255. {
  256. id: 2,
  257. productCode: 'crm',
  258. userId: 3,
  259. username: 'lisi',
  260. nickname: '李四',
  261. memberType: 'MEMBER',
  262. status: 1,
  263. createTime: now - 86400 * 10,
  264. },
  265. {
  266. id: 3,
  267. productCode: 'oa',
  268. userId: 2,
  269. username: 'zhangsan',
  270. nickname: '张三',
  271. memberType: 'DEVELOPER',
  272. status: 1,
  273. createTime: now - 86400 * 8,
  274. },
  275. ];
  276. function ok(data: any) {
  277. return { success: true, errorCode: 0, errorMessage: 'ok', showType: 0, data };
  278. }
  279. function okList(list: any[], total?: number) {
  280. return {
  281. success: true,
  282. errorCode: 0,
  283. errorMessage: 'ok',
  284. showType: 0,
  285. data: { list, total: total ?? list.length },
  286. };
  287. }
  288. function fail(code: number, msg: string) {
  289. return { success: false, errorCode: code, errorMessage: msg, showType: 2 };
  290. }
  291. export default {
  292. 'POST /api/dept/tree': (_req: Request, res: Response) => {
  293. res.json(ok(deptTree));
  294. },
  295. 'POST /api/dept/create': (req: Request, res: Response) => {
  296. res.json(ok({ id: Math.floor(Math.random() * 1000) + 100 }));
  297. },
  298. 'POST /api/dept/update': (_req: Request, res: Response) => {
  299. res.json(ok(null));
  300. },
  301. 'POST /api/dept/delete': (req: Request, res: Response) => {
  302. const { id } = req.body;
  303. const dept = deptTree.find((d) => d.id === id);
  304. if (dept && dept.children && dept.children.length > 0) {
  305. res.json(fail(400, '该部门下存在子部门,无法删除'));
  306. return;
  307. }
  308. res.json(ok(null));
  309. },
  310. 'POST /api/product/list': (req: Request, res: Response) => {
  311. const { page = 1, pageSize = 20 } = req.body;
  312. const start = (page - 1) * pageSize;
  313. res.json(okList(products.slice(start, start + pageSize), products.length));
  314. },
  315. 'POST /api/product/detail': (req: Request, res: Response) => {
  316. const { id } = req.body;
  317. const item = products.find((p) => p.id === id);
  318. if (!item) {
  319. res.json(fail(404, '产品不存在'));
  320. return;
  321. }
  322. res.json(ok(item));
  323. },
  324. 'POST /api/product/create': (_req: Request, res: Response) => {
  325. res.json(
  326. ok({
  327. id: 100,
  328. code: 'new_product',
  329. appKey: 'ak_new_product_100',
  330. adminUser: 'admin_new_product',
  331. credentialsTicket: 'ticket_mock_abc123',
  332. credentialsExpiresAt: now + 300,
  333. }),
  334. );
  335. },
  336. 'POST /api/product/update': (_req: Request, res: Response) => {
  337. res.json(ok(null));
  338. },
  339. 'POST /api/product/fetchInitialCredentials': (_req: Request, res: Response) => {
  340. res.json(
  341. ok({
  342. appKey: 'ak_new_product_100',
  343. appSecret: 'sk_mock_secret_xyz789',
  344. adminUser: 'admin_new_product',
  345. adminPassword: 'P@ssw0rd123',
  346. }),
  347. );
  348. },
  349. 'POST /api/user/list': (req: Request, res: Response) => {
  350. const { page = 1, pageSize = 20, productCode } = req.body;
  351. const list = users.map((u) => ({
  352. ...u,
  353. memberType: productCode
  354. ? (members.find((m) => m.userId === u.id && m.productCode === productCode)?.memberType ??
  355. '')
  356. : undefined,
  357. }));
  358. const start = (page - 1) * pageSize;
  359. res.json(okList(list.slice(start, start + pageSize), list.length));
  360. },
  361. 'POST /api/user/detail': (req: Request, res: Response) => {
  362. const { id } = req.body;
  363. const item = users.find((u) => u.id === id);
  364. if (!item) {
  365. res.json(fail(404, '用户不存在'));
  366. return;
  367. }
  368. res.json(ok({ ...item, roleIds: id === 3 ? [2] : [] }));
  369. },
  370. 'POST /api/user/create': (_req: Request, res: Response) => {
  371. res.json(ok({ id: Math.floor(Math.random() * 1000) + 100 }));
  372. },
  373. 'POST /api/user/update': (_req: Request, res: Response) => {
  374. res.json(ok(null));
  375. },
  376. 'POST /api/user/updateStatus': (_req: Request, res: Response) => {
  377. res.json(ok(null));
  378. },
  379. 'POST /api/user/bindRoles': (_req: Request, res: Response) => {
  380. res.json(ok(null));
  381. },
  382. 'POST /api/user/setPerms': (_req: Request, res: Response) => {
  383. res.json(ok(null));
  384. },
  385. 'POST /api/user/userPerms': (req: Request, res: Response) => {
  386. const { userId } = req.body;
  387. const mockPerms =
  388. userId === 3
  389. ? [
  390. { permId: 7, effect: 'ALLOW' },
  391. { permId: 6, effect: 'DENY' },
  392. ]
  393. : [];
  394. res.json(ok({ perms: mockPerms }));
  395. },
  396. 'POST /api/role/list': (req: Request, res: Response) => {
  397. const { productCode, page = 1, pageSize = 20 } = req.body;
  398. const filtered = roles.filter((r) => r.productCode === productCode);
  399. const start = (page - 1) * pageSize;
  400. res.json(okList(filtered.slice(start, start + pageSize), filtered.length));
  401. },
  402. 'POST /api/role/detail': (req: Request, res: Response) => {
  403. const { id } = req.body;
  404. const item = roles.find((r) => r.id === id);
  405. if (!item) {
  406. res.json(fail(404, '角色不存在'));
  407. return;
  408. }
  409. const permIds = id === 1 ? [1, 2, 3, 4, 5, 6, 7] : id === 2 ? [1, 2, 5, 6] : [1, 5];
  410. res.json(ok({ ...item, permIds }));
  411. },
  412. 'POST /api/role/create': (_req: Request, res: Response) => {
  413. res.json(ok({ id: Math.floor(Math.random() * 1000) + 100 }));
  414. },
  415. 'POST /api/role/update': (_req: Request, res: Response) => {
  416. res.json(ok(null));
  417. },
  418. 'POST /api/role/delete': (_req: Request, res: Response) => {
  419. res.json(ok(null));
  420. },
  421. 'POST /api/role/bindPerms': (_req: Request, res: Response) => {
  422. res.json(ok(null));
  423. },
  424. 'POST /api/perm/list': (req: Request, res: Response) => {
  425. const { productCode, page = 1, pageSize = 20 } = req.body;
  426. const filtered = perms.filter((p) => p.productCode === productCode);
  427. const start = (page - 1) * pageSize;
  428. res.json(okList(filtered.slice(start, start + pageSize), filtered.length));
  429. },
  430. 'POST /api/member/list': (req: Request, res: Response) => {
  431. const { productCode, page = 1, pageSize = 20 } = req.body;
  432. const filtered = members.filter((m) => m.productCode === productCode);
  433. const start = (page - 1) * pageSize;
  434. res.json(okList(filtered.slice(start, start + pageSize), filtered.length));
  435. },
  436. 'POST /api/member/add': (_req: Request, res: Response) => {
  437. res.json(ok({ id: Math.floor(Math.random() * 1000) + 100 }));
  438. },
  439. 'POST /api/member/update': (_req: Request, res: Response) => {
  440. res.json(ok(null));
  441. },
  442. 'POST /api/member/remove': (_req: Request, res: Response) => {
  443. res.json(ok(null));
  444. },
  445. 'POST /api/captcha/get': (_req: Request, res: Response) => {
  446. res.json(
  447. ok({
  448. id: 'captcha_mock_001',
  449. base64image:
  450. 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
  451. }),
  452. );
  453. },
  454. 'POST /api/capjs/endpoint': (_req: Request, res: Response) => {
  455. res.json(ok({ data: '' }));
  456. },
  457. 'POST /api/auth/adminLogin': (req: Request, res: Response) => {
  458. const { username, password, managementKey } = req.body;
  459. if (managementKey !== 'mock-key') {
  460. res.json(fail(401, 'managementKey 无效'));
  461. return;
  462. }
  463. if (username === 'superadmin' && password === '123456') {
  464. res.json(
  465. ok({
  466. accessToken: 'mock_access_token_superadmin',
  467. refreshToken: 'mock_refresh_token_superadmin',
  468. expires: now + 7200,
  469. userInfo: {
  470. userId: 1,
  471. username: 'superadmin',
  472. nickname: '超级管理员',
  473. avatar: '',
  474. email: '[email protected]',
  475. phone: '13800000001',
  476. isSuperAdmin: 1,
  477. mustChangePassword: 0,
  478. memberType: '',
  479. perms: [],
  480. },
  481. }),
  482. );
  483. return;
  484. }
  485. res.json(fail(401, '用户名或密码错误'));
  486. },
  487. 'POST /api/auth/adminLogin/cap': (req: Request, res: Response) => {
  488. const { username, password, managementKey } = req.body;
  489. if (managementKey !== 'mock-key') {
  490. res.json(fail(401, 'managementKey 无效'));
  491. return;
  492. }
  493. if (username === 'superadmin' && password === '123456') {
  494. res.json(
  495. ok({
  496. accessToken: 'mock_access_token_superadmin',
  497. refreshToken: 'mock_refresh_token_superadmin',
  498. expires: now + 7200,
  499. userInfo: {
  500. userId: 1,
  501. username: 'superadmin',
  502. nickname: '超级管理员',
  503. avatar: '',
  504. email: '[email protected]',
  505. phone: '13800000001',
  506. isSuperAdmin: 1,
  507. mustChangePassword: 0,
  508. memberType: '',
  509. perms: [],
  510. },
  511. }),
  512. );
  513. return;
  514. }
  515. res.json(fail(401, '用户名或密码错误'));
  516. },
  517. 'POST /api/auth/logout': (_req: Request, res: Response) => {
  518. res.json(ok(null));
  519. },
  520. 'POST /api/auth/refreshToken': (_req: Request, res: Response) => {
  521. res.json(
  522. ok({
  523. accessToken: 'mock_access_token_refreshed',
  524. refreshToken: 'mock_refresh_token_refreshed',
  525. expires: now + 7200,
  526. userInfo: {
  527. userId: 1,
  528. username: 'superadmin',
  529. nickname: '超级管理员',
  530. avatar: '',
  531. email: '[email protected]',
  532. phone: '13800000001',
  533. isSuperAdmin: 1,
  534. mustChangePassword: 0,
  535. memberType: '',
  536. perms: [],
  537. },
  538. }),
  539. );
  540. },
  541. 'POST /api/auth/updateInfo': (_req: Request, res: Response) => {
  542. res.json(ok(null));
  543. },
  544. 'POST /api/auth/changePassword': (req: Request, res: Response) => {
  545. const { oldPassword } = req.body;
  546. if (oldPassword !== '123456') {
  547. res.json(fail(400, '原密码错误'));
  548. return;
  549. }
  550. res.json(ok(null));
  551. },
  552. };