api.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  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, UserMessage
  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 interface ThemeSettingsResponse {
  350. message: string;
  351. data: ThemeSettings;
  352. }
  353. // Theme API 定义
  354. export const ThemeAPI = {
  355. // 获取主题设置
  356. getThemeSettings: async (): Promise<ThemeSettings> => {
  357. try {
  358. const response = await axios.get(`${API_BASE_URL}/theme`);
  359. return response.data.data;
  360. } catch (error) {
  361. throw error;
  362. }
  363. },
  364. // 更新主题设置
  365. updateThemeSettings: async (themeData: Partial<ThemeSettings>): Promise<ThemeSettings> => {
  366. try {
  367. const response = await axios.put(`${API_BASE_URL}/theme`, themeData);
  368. return response.data.data;
  369. } catch (error) {
  370. throw error;
  371. }
  372. },
  373. // 重置主题设置
  374. resetThemeSettings: async (): Promise<ThemeSettings> => {
  375. try {
  376. const response = await axios.post(`${API_BASE_URL}/theme/reset`);
  377. return response.data.data;
  378. } catch (error) {
  379. throw error;
  380. }
  381. }
  382. };
  383. // 图表数据API接口类型
  384. interface ChartDataResponse<T> {
  385. message: string;
  386. data: T;
  387. }
  388. interface UserActivityData {
  389. date: string;
  390. count: number;
  391. }
  392. interface FileUploadsData {
  393. month: string;
  394. count: number;
  395. }
  396. interface FileTypesData {
  397. type: string;
  398. value: number;
  399. }
  400. interface DashboardOverviewData {
  401. userCount: number;
  402. fileCount: number;
  403. articleCount: number;
  404. todayLoginCount: number;
  405. }
  406. // 图表数据API
  407. export const ChartAPI = {
  408. // 获取用户活跃度数据
  409. getUserActivity: async (): Promise<ChartDataResponse<UserActivityData[]>> => {
  410. try {
  411. const response = await axios.get(`${API_BASE_URL}/charts/user-activity`);
  412. return response.data;
  413. } catch (error) {
  414. throw error;
  415. }
  416. },
  417. // 获取文件上传统计数据
  418. getFileUploads: async (): Promise<ChartDataResponse<FileUploadsData[]>> => {
  419. try {
  420. const response = await axios.get(`${API_BASE_URL}/charts/file-uploads`);
  421. return response.data;
  422. } catch (error) {
  423. throw error;
  424. }
  425. },
  426. // 获取文件类型分布数据
  427. getFileTypes: async (): Promise<ChartDataResponse<FileTypesData[]>> => {
  428. try {
  429. const response = await axios.get(`${API_BASE_URL}/charts/file-types`);
  430. return response.data;
  431. } catch (error) {
  432. throw error;
  433. }
  434. },
  435. // 获取仪表盘概览数据
  436. getDashboardOverview: async (): Promise<ChartDataResponse<DashboardOverviewData>> => {
  437. try {
  438. const response = await axios.get(`${API_BASE_URL}/charts/dashboard-overview`);
  439. return response.data;
  440. } catch (error) {
  441. throw error;
  442. }
  443. }
  444. };
  445. // 消息API接口类型
  446. interface MessagesResponse {
  447. data: UserMessage[];
  448. pagination: {
  449. total: number;
  450. current: number;
  451. pageSize: number;
  452. totalPages: number;
  453. };
  454. }
  455. interface MessageResponse {
  456. data: Message;
  457. message?: string;
  458. }
  459. interface MessageCountResponse {
  460. count: number;
  461. }
  462. // 消息API
  463. export const MessageAPI = {
  464. // 获取消息列表
  465. getMessages: async (params?: {
  466. page?: number,
  467. pageSize?: number,
  468. type?: string,
  469. status?: string,
  470. search?: string
  471. }): Promise<MessagesResponse> => {
  472. try {
  473. const response = await axios.get(`${API_BASE_URL}/messages`, { params });
  474. return response.data;
  475. } catch (error) {
  476. throw error;
  477. }
  478. },
  479. // 发送消息
  480. sendMessage: async (data: {
  481. title: string,
  482. content: string,
  483. type: string,
  484. receiver_ids: number[]
  485. }): Promise<MessageResponse> => {
  486. try {
  487. const response = await axios.post(`${API_BASE_URL}/messages`, data);
  488. return response.data;
  489. } catch (error) {
  490. throw error;
  491. }
  492. },
  493. // 获取未读消息数
  494. getUnreadCount: async (): Promise<MessageCountResponse> => {
  495. try {
  496. const response = await axios.get(`${API_BASE_URL}/messages/count/unread`);
  497. return response.data;
  498. } catch (error) {
  499. throw error;
  500. }
  501. },
  502. // 标记消息为已读
  503. markAsRead: async (id: number): Promise<MessageResponse> => {
  504. try {
  505. const response = await axios.post(`${API_BASE_URL}/messages/${id}/read`);
  506. return response.data;
  507. } catch (error) {
  508. throw error;
  509. }
  510. },
  511. // 删除消息
  512. deleteMessage: async (id: number): Promise<MessageResponse> => {
  513. try {
  514. const response = await axios.delete(`${API_BASE_URL}/messages/${id}`);
  515. return response.data;
  516. } catch (error) {
  517. throw error;
  518. }
  519. }
  520. };
  521. // 地图相关API的接口类型定义
  522. export interface LoginLocationResponse {
  523. message: string;
  524. data: LoginLocation[];
  525. }
  526. export interface LoginLocationDetailResponse {
  527. message: string;
  528. data: LoginLocationDetail;
  529. }
  530. export interface LoginLocationUpdateResponse {
  531. message: string;
  532. data: LoginLocationDetail;
  533. }
  534. // 地图相关API
  535. export const MapAPI = {
  536. // 获取地图标记点数据
  537. getMarkers: async (params?: {
  538. startTime?: string;
  539. endTime?: string;
  540. userId?: number
  541. }): Promise<LoginLocationResponse> => {
  542. try {
  543. const response = await axios.get(`${API_BASE_URL}/map/markers`, { params });
  544. return response.data;
  545. } catch (error) {
  546. throw error;
  547. }
  548. },
  549. // 获取登录位置详情
  550. getLocationDetail: async (locationId: number): Promise<LoginLocationDetailResponse> => {
  551. try {
  552. const response = await axios.get(`${API_BASE_URL}/map/location/${locationId}`);
  553. return response.data;
  554. } catch (error) {
  555. throw error;
  556. }
  557. },
  558. // 更新登录位置信息
  559. updateLocation: async (locationId: number, data: {
  560. longitude: number;
  561. latitude: number;
  562. location_name?: string;
  563. }): Promise<LoginLocationUpdateResponse> => {
  564. try {
  565. const response = await axios.put(`${API_BASE_URL}/map/location/${locationId}`, data);
  566. return response.data;
  567. } catch (error) {
  568. throw error;
  569. }
  570. }
  571. };
  572. // 系统设置API
  573. export const SystemAPI = {
  574. // 获取所有系统设置
  575. getSettings: async (): Promise<SystemSettingGroupData[]> => {
  576. try {
  577. const response = await axios.get(`${API_BASE_URL}/settings`);
  578. return response.data.data;
  579. } catch (error) {
  580. throw error;
  581. }
  582. },
  583. // 获取指定分组的系统设置
  584. getSettingsByGroup: async (group: string): Promise<SystemSetting[]> => {
  585. try {
  586. const response = await axios.get(`${API_BASE_URL}/settings/group/${group}`);
  587. return response.data.data;
  588. } catch (error) {
  589. throw error;
  590. }
  591. },
  592. // 更新系统设置
  593. updateSettings: async (settings: Partial<SystemSetting>[]): Promise<SystemSetting[]> => {
  594. try {
  595. const response = await axios.put(`${API_BASE_URL}/settings`, settings);
  596. return response.data.data;
  597. } catch (error) {
  598. throw error;
  599. }
  600. },
  601. // 重置系统设置
  602. resetSettings: async (): Promise<SystemSetting[]> => {
  603. try {
  604. const response = await axios.post(`${API_BASE_URL}/settings/reset`);
  605. return response.data.data;
  606. } catch (error) {
  607. throw error;
  608. }
  609. }
  610. };