api.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. import axios from 'axios';
  2. import type { MinioUploadPolicy, OSSUploadPolicy } from '@d8d-appcontainer/types';
  3. import 'dayjs/locale/zh-cn';
  4. import type {
  5. User, FileLibrary, FileCategory, ThemeSettings,
  6. SystemSetting, SystemSettingGroupData,
  7. LoginLocation, LoginLocationDetail,
  8. Message, MessageType, MessageStatus
  9. } from '../share/types.ts';
  10. // 定义API基础URL
  11. const API_BASE_URL = '/api';
  12. // 获取OSS完整URL
  13. export const getOssUrl = (path: string): string => {
  14. // 获取全局配置中的OSS_HOST,如果不存在使用默认值
  15. const ossHost = (window.CONFIG?.OSS_BASE_URL) || '';
  16. // 确保path不以/开头
  17. const ossPath = path.startsWith('/') ? path.substring(1) : path;
  18. return `${ossHost}/${ossPath}`;
  19. };
  20. // ===================
  21. // Auth API 定义部分
  22. // ===================
  23. // 定义API返回数据类型
  24. interface AuthLoginResponse {
  25. message: string;
  26. token: string;
  27. refreshToken?: string;
  28. user: User;
  29. }
  30. interface AuthResponse {
  31. message: string;
  32. [key: string]: any;
  33. }
  34. // 定义Auth API接口类型
  35. interface AuthAPIType {
  36. login: (username: string, password: string, latitude?: number, longitude?: number) => Promise<AuthLoginResponse>;
  37. register: (username: string, email: string, password: string) => Promise<AuthResponse>;
  38. logout: () => Promise<AuthResponse>;
  39. getCurrentUser: () => Promise<User>;
  40. updateUser: (userId: number, userData: Partial<User>) => Promise<User>;
  41. changePassword: (oldPassword: string, newPassword: string) => Promise<AuthResponse>;
  42. requestPasswordReset: (email: string) => Promise<AuthResponse>;
  43. resetPassword: (token: string, newPassword: string) => Promise<AuthResponse>;
  44. }
  45. // Auth相关API
  46. export const AuthAPI: AuthAPIType = {
  47. // 登录API
  48. login: async (username: string, password: string, latitude?: number, longitude?: number) => {
  49. try {
  50. const response = await axios.post(`${API_BASE_URL}/auth/login`, {
  51. username,
  52. password,
  53. latitude,
  54. longitude
  55. });
  56. return response.data;
  57. } catch (error) {
  58. throw error;
  59. }
  60. },
  61. // 注册API
  62. register: async (username: string, email: string, password: string) => {
  63. try {
  64. const response = await axios.post(`${API_BASE_URL}/auth/register`, { username, email, password });
  65. return response.data;
  66. } catch (error) {
  67. throw error;
  68. }
  69. },
  70. // 登出API
  71. logout: async () => {
  72. try {
  73. const response = await axios.post(`${API_BASE_URL}/auth/logout`);
  74. return response.data;
  75. } catch (error) {
  76. throw error;
  77. }
  78. },
  79. // 获取当前用户信息
  80. getCurrentUser: async () => {
  81. try {
  82. const response = await axios.get(`${API_BASE_URL}/auth/me`);
  83. return response.data;
  84. } catch (error) {
  85. throw error;
  86. }
  87. },
  88. // 更新用户信息
  89. updateUser: async (userId: number, userData: Partial<User>) => {
  90. try {
  91. const response = await axios.put(`${API_BASE_URL}/auth/users/${userId}`, userData);
  92. return response.data;
  93. } catch (error) {
  94. throw error;
  95. }
  96. },
  97. // 修改密码
  98. changePassword: async (oldPassword: string, newPassword: string) => {
  99. try {
  100. const response = await axios.post(`${API_BASE_URL}/auth/change-password`, { oldPassword, newPassword });
  101. return response.data;
  102. } catch (error) {
  103. throw error;
  104. }
  105. },
  106. // 请求重置密码
  107. requestPasswordReset: async (email: string) => {
  108. try {
  109. const response = await axios.post(`${API_BASE_URL}/auth/request-password-reset`, { email });
  110. return response.data;
  111. } catch (error) {
  112. throw error;
  113. }
  114. },
  115. // 重置密码
  116. resetPassword: async (token: string, newPassword: string) => {
  117. try {
  118. const response = await axios.post(`${API_BASE_URL}/auth/reset-password`, { token, newPassword });
  119. return response.data;
  120. } catch (error) {
  121. throw error;
  122. }
  123. }
  124. };
  125. // 为UserAPI添加的接口响应类型
  126. interface UsersResponse {
  127. data: User[];
  128. pagination: {
  129. total: number;
  130. current: number;
  131. pageSize: number;
  132. totalPages: number;
  133. };
  134. }
  135. interface UserResponse {
  136. data: User;
  137. message?: string;
  138. }
  139. interface UserCreateResponse {
  140. message: string;
  141. data: User;
  142. }
  143. interface UserUpdateResponse {
  144. message: string;
  145. data: User;
  146. }
  147. interface UserDeleteResponse {
  148. message: string;
  149. id: number;
  150. }
  151. // 用户管理API
  152. export const UserAPI = {
  153. // 获取用户列表
  154. getUsers: async (params?: { page?: number, limit?: number, search?: string }): Promise<UsersResponse> => {
  155. try {
  156. const response = await axios.get(`${API_BASE_URL}/users`, { params });
  157. return response.data;
  158. } catch (error) {
  159. throw error;
  160. }
  161. },
  162. // 获取单个用户详情
  163. getUser: async (userId: number): Promise<UserResponse> => {
  164. try {
  165. const response = await axios.get(`${API_BASE_URL}/users/${userId}`);
  166. return response.data;
  167. } catch (error) {
  168. throw error;
  169. }
  170. },
  171. // 创建用户
  172. createUser: async (userData: Partial<User>): Promise<UserCreateResponse> => {
  173. try {
  174. const response = await axios.post(`${API_BASE_URL}/users`, userData);
  175. return response.data;
  176. } catch (error) {
  177. throw error;
  178. }
  179. },
  180. // 更新用户信息
  181. updateUser: async (userId: number, userData: Partial<User>): Promise<UserUpdateResponse> => {
  182. try {
  183. const response = await axios.put(`${API_BASE_URL}/users/${userId}`, userData);
  184. return response.data;
  185. } catch (error) {
  186. throw error;
  187. }
  188. },
  189. // 删除用户
  190. deleteUser: async (userId: number): Promise<UserDeleteResponse> => {
  191. try {
  192. const response = await axios.delete(`${API_BASE_URL}/users/${userId}`);
  193. return response.data;
  194. } catch (error) {
  195. throw error;
  196. }
  197. }
  198. };
  199. // 定义文件相关接口类型
  200. interface FileUploadPolicyResponse {
  201. message: string;
  202. data: MinioUploadPolicy | OSSUploadPolicy;
  203. }
  204. interface FileListResponse {
  205. message: string;
  206. data: {
  207. list: FileLibrary[];
  208. pagination: {
  209. current: number;
  210. pageSize: number;
  211. total: number;
  212. };
  213. };
  214. }
  215. interface FileSaveResponse {
  216. message: string;
  217. data: FileLibrary;
  218. }
  219. interface FileInfoResponse {
  220. message: string;
  221. data: FileLibrary;
  222. }
  223. interface FileDeleteResponse {
  224. message: string;
  225. }
  226. interface FileCategoryListResponse {
  227. data: FileCategory[];
  228. total: number;
  229. page: number;
  230. pageSize: number;
  231. }
  232. interface FileCategoryCreateResponse {
  233. message: string;
  234. data: FileCategory;
  235. }
  236. interface FileCategoryUpdateResponse {
  237. message: string;
  238. data: FileCategory;
  239. }
  240. interface FileCategoryDeleteResponse {
  241. message: string;
  242. }
  243. // 文件API接口定义
  244. export const FileAPI = {
  245. // 获取文件上传策略
  246. getUploadPolicy: async (filename: string, prefix: string = 'uploads/', maxSize: number = 10 * 1024 * 1024): Promise<FileUploadPolicyResponse> => {
  247. try {
  248. const response = await axios.get(`${API_BASE_URL}/upload/policy`, {
  249. params: { filename, prefix, maxSize }
  250. });
  251. return response.data;
  252. } catch (error) {
  253. throw error;
  254. }
  255. },
  256. // 保存文件信息
  257. saveFileInfo: async (fileData: Partial<FileLibrary>): Promise<FileSaveResponse> => {
  258. try {
  259. const response = await axios.post(`${API_BASE_URL}/upload/save`, fileData);
  260. return response.data;
  261. } catch (error) {
  262. throw error;
  263. }
  264. },
  265. // 获取文件列表
  266. getFileList: async (params?: {
  267. page?: number,
  268. pageSize?: number,
  269. category_id?: number,
  270. fileType?: string,
  271. keyword?: string
  272. }): Promise<FileListResponse> => {
  273. try {
  274. const response = await axios.get(`${API_BASE_URL}/upload/list`, { params });
  275. return response.data;
  276. } catch (error) {
  277. throw error;
  278. }
  279. },
  280. // 获取单个文件信息
  281. getFileInfo: async (id: number): Promise<FileInfoResponse> => {
  282. try {
  283. const response = await axios.get(`${API_BASE_URL}/upload/${id}`);
  284. return response.data;
  285. } catch (error) {
  286. throw error;
  287. }
  288. },
  289. // 更新文件下载计数
  290. updateDownloadCount: async (id: number): Promise<FileDeleteResponse> => {
  291. try {
  292. const response = await axios.post(`${API_BASE_URL}/upload/${id}/download`);
  293. return response.data;
  294. } catch (error) {
  295. throw error;
  296. }
  297. },
  298. // 删除文件
  299. deleteFile: async (id: number): Promise<FileDeleteResponse> => {
  300. try {
  301. const response = await axios.delete(`${API_BASE_URL}/upload/${id}`);
  302. return response.data;
  303. } catch (error) {
  304. throw error;
  305. }
  306. },
  307. // 获取文件分类列表
  308. getCategories: async (params?: {
  309. page?: number,
  310. pageSize?: number,
  311. search?: string
  312. }): Promise<FileCategoryListResponse> => {
  313. try {
  314. const response = await axios.get(`${API_BASE_URL}/file-categories`, { params });
  315. return response.data;
  316. } catch (error) {
  317. throw error;
  318. }
  319. },
  320. // 创建文件分类
  321. createCategory: async (data: Partial<FileCategory>): Promise<FileCategoryCreateResponse> => {
  322. try {
  323. const response = await axios.post(`${API_BASE_URL}/file-categories`, data);
  324. return response.data;
  325. } catch (error) {
  326. throw error;
  327. }
  328. },
  329. // 更新文件分类
  330. updateCategory: async (id: number, data: Partial<FileCategory>): Promise<FileCategoryUpdateResponse> => {
  331. try {
  332. const response = await axios.put(`${API_BASE_URL}/file-categories/${id}`, data);
  333. return response.data;
  334. } catch (error) {
  335. throw error;
  336. }
  337. },
  338. // 删除文件分类
  339. deleteCategory: async (id: number): Promise<FileCategoryDeleteResponse> => {
  340. try {
  341. const response = await axios.delete(`${API_BASE_URL}/file-categories/${id}`);
  342. return response.data;
  343. } catch (error) {
  344. throw error;
  345. }
  346. }
  347. };
  348. // Theme API 定义
  349. export const ThemeAPI = {
  350. // 获取主题设置
  351. getThemeSettings: async (): Promise<ThemeSettings> => {
  352. try {
  353. const response = await axios.get(`${API_BASE_URL}/theme`);
  354. return response.data.data;
  355. } catch (error) {
  356. throw error;
  357. }
  358. },
  359. // 更新主题设置
  360. updateThemeSettings: async (themeData: Partial<ThemeSettings>): Promise<ThemeSettings> => {
  361. try {
  362. const response = await axios.put(`${API_BASE_URL}/theme`, themeData);
  363. return response.data.data;
  364. } catch (error) {
  365. throw error;
  366. }
  367. },
  368. // 重置主题设置
  369. resetThemeSettings: async (): Promise<ThemeSettings> => {
  370. try {
  371. const response = await axios.post(`${API_BASE_URL}/theme/reset`);
  372. return response.data.data;
  373. } catch (error) {
  374. throw error;
  375. }
  376. }
  377. };
  378. // 图表数据API接口类型
  379. interface ChartDataResponse<T> {
  380. message: string;
  381. data: T;
  382. }
  383. interface UserActivityData {
  384. date: string;
  385. count: number;
  386. }
  387. interface FileUploadsData {
  388. month: string;
  389. count: number;
  390. }
  391. interface FileTypesData {
  392. type: string;
  393. value: number;
  394. }
  395. interface DashboardOverviewData {
  396. userCount: number;
  397. fileCount: number;
  398. articleCount: number;
  399. todayLoginCount: number;
  400. }
  401. // 图表数据API
  402. export const ChartAPI = {
  403. // 获取用户活跃度数据
  404. getUserActivity: async (): Promise<ChartDataResponse<UserActivityData[]>> => {
  405. try {
  406. const response = await axios.get(`${API_BASE_URL}/charts/user-activity`);
  407. return response.data;
  408. } catch (error) {
  409. throw error;
  410. }
  411. },
  412. // 获取文件上传统计数据
  413. getFileUploads: async (): Promise<ChartDataResponse<FileUploadsData[]>> => {
  414. try {
  415. const response = await axios.get(`${API_BASE_URL}/charts/file-uploads`);
  416. return response.data;
  417. } catch (error) {
  418. throw error;
  419. }
  420. },
  421. // 获取文件类型分布数据
  422. getFileTypes: async (): Promise<ChartDataResponse<FileTypesData[]>> => {
  423. try {
  424. const response = await axios.get(`${API_BASE_URL}/charts/file-types`);
  425. return response.data;
  426. } catch (error) {
  427. throw error;
  428. }
  429. },
  430. // 获取仪表盘概览数据
  431. getDashboardOverview: async (): Promise<ChartDataResponse<DashboardOverviewData>> => {
  432. try {
  433. const response = await axios.get(`${API_BASE_URL}/charts/dashboard-overview`);
  434. return response.data;
  435. } catch (error) {
  436. throw error;
  437. }
  438. }
  439. };
  440. // 地图相关API的接口类型定义
  441. export interface LoginLocationResponse {
  442. message: string;
  443. data: LoginLocation[];
  444. }
  445. export interface LoginLocationDetailResponse {
  446. message: string;
  447. data: LoginLocationDetail;
  448. }
  449. export interface LoginLocationUpdateResponse {
  450. message: string;
  451. data: LoginLocationDetail;
  452. }
  453. // 地图相关API
  454. export const MapAPI = {
  455. // 获取地图标记点数据
  456. getMarkers: async (params?: {
  457. startTime?: string;
  458. endTime?: string;
  459. userId?: number
  460. }): Promise<LoginLocationResponse> => {
  461. try {
  462. const response = await axios.get(`${API_BASE_URL}/map/markers`, { params });
  463. return response.data;
  464. } catch (error) {
  465. throw error;
  466. }
  467. },
  468. // 获取登录位置详情
  469. getLocationDetail: async (locationId: number): Promise<LoginLocationDetailResponse> => {
  470. try {
  471. const response = await axios.get(`${API_BASE_URL}/map/location/${locationId}`);
  472. return response.data;
  473. } catch (error) {
  474. throw error;
  475. }
  476. },
  477. // 更新登录位置信息
  478. updateLocation: async (locationId: number, data: {
  479. longitude: number;
  480. latitude: number;
  481. location_name?: string;
  482. }): Promise<LoginLocationUpdateResponse> => {
  483. try {
  484. const response = await axios.put(`${API_BASE_URL}/map/location/${locationId}`, data);
  485. return response.data;
  486. } catch (error) {
  487. throw error;
  488. }
  489. }
  490. };
  491. // 系统设置API
  492. export const SystemAPI = {
  493. // 获取所有系统设置
  494. getSettings: async (): Promise<SystemSettingGroupData[]> => {
  495. try {
  496. const response = await axios.get(`${API_BASE_URL}/settings`);
  497. return response.data.data;
  498. } catch (error) {
  499. throw error;
  500. }
  501. },
  502. // 获取指定分组的系统设置
  503. getSettingsByGroup: async (group: string): Promise<SystemSetting[]> => {
  504. try {
  505. const response = await axios.get(`${API_BASE_URL}/settings/group/${group}`);
  506. return response.data.data;
  507. } catch (error) {
  508. throw error;
  509. }
  510. },
  511. // 更新系统设置
  512. updateSettings: async (settings: Partial<SystemSetting>[]): Promise<SystemSetting[]> => {
  513. try {
  514. const response = await axios.put(`${API_BASE_URL}/settings`, settings);
  515. return response.data.data;
  516. } catch (error) {
  517. throw error;
  518. }
  519. },
  520. // 重置系统设置
  521. resetSettings: async (): Promise<SystemSetting[]> => {
  522. try {
  523. const response = await axios.post(`${API_BASE_URL}/settings/reset`);
  524. return response.data.data;
  525. } catch (error) {
  526. throw error;
  527. }
  528. }
  529. };
  530. // 消息API响应类型
  531. export interface MessageResponse {
  532. message: string;
  533. data?: any;
  534. }
  535. export interface MessagesResponse {
  536. data: Message[];
  537. pagination: {
  538. total: number;
  539. current: number;
  540. pageSize: number;
  541. totalPages: number;
  542. };
  543. }
  544. export interface UnreadCountResponse {
  545. count: number;
  546. }
  547. // 消息API
  548. export const MessageAPI = {
  549. // 获取消息列表
  550. getMessages: async (params?: {
  551. page?: number,
  552. pageSize?: number,
  553. type?: MessageType,
  554. status?: MessageStatus
  555. }): Promise<MessagesResponse> => {
  556. try {
  557. const response = await axios.get(`${API_BASE_URL}/messages`, { params });
  558. return response.data;
  559. } catch (error) {
  560. throw error;
  561. }
  562. },
  563. // 获取消息详情
  564. getMessage: async (id: number): Promise<MessageResponse> => {
  565. try {
  566. const response = await axios.get(`${API_BASE_URL}/messages/${id}`);
  567. return response.data;
  568. } catch (error) {
  569. throw error;
  570. }
  571. },
  572. // 发送消息
  573. sendMessage: async (data: {
  574. title: string,
  575. content: string,
  576. type: MessageType,
  577. receiver_ids: number[]
  578. }): Promise<MessageResponse> => {
  579. try {
  580. const response = await axios.post(`${API_BASE_URL}/messages`, data);
  581. return response.data;
  582. } catch (error) {
  583. throw error;
  584. }
  585. },
  586. // 删除消息(软删除)
  587. deleteMessage: async (id: number): Promise<MessageResponse> => {
  588. try {
  589. const response = await axios.delete(`${API_BASE_URL}/messages/${id}`);
  590. return response.data;
  591. } catch (error) {
  592. throw error;
  593. }
  594. },
  595. // 获取未读消息数量
  596. getUnreadCount: async (): Promise<UnreadCountResponse> => {
  597. try {
  598. const response = await axios.get(`${API_BASE_URL}/messages/unread-count`);
  599. return response.data;
  600. } catch (error) {
  601. throw error;
  602. }
  603. },
  604. // 标记消息为已读
  605. markAsRead: async (id: number): Promise<MessageResponse> => {
  606. try {
  607. const response = await axios.post(`${API_BASE_URL}/messages/${id}/read`);
  608. return response.data;
  609. } catch (error) {
  610. throw error;
  611. }
  612. }
  613. };