work_orders.ts 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import axios from 'axios';
  2. import { WorkOrder, WorkOrderSettings, WorkOrderStatus, WorkOrderPriority } from '../../share/monitorTypes.ts'
  3. // 分类数据缓存
  4. let categoriesCache: string[] | null = null;
  5. let cacheExpireTime = 0;
  6. const CACHE_EXPIRE_DURATION = 5 * 60 * 1000; // 5分钟缓存
  7. interface WorkOrderListParams {
  8. page?: number;
  9. pageSize?: number;
  10. status?: WorkOrderStatus;
  11. priority?: WorkOrderPriority;
  12. device_id?: number;
  13. creator_id?: number;
  14. }
  15. interface WorkOrderListResponse {
  16. data: WorkOrder[];
  17. pagination: {
  18. total: number;
  19. current: number;
  20. pageSize: number;
  21. totalPages: number;
  22. };
  23. }
  24. interface WorkOrderDetailResponse {
  25. data: WorkOrder;
  26. message?: string;
  27. }
  28. interface WorkOrderCreateResponse {
  29. message: string;
  30. data: WorkOrder;
  31. }
  32. interface WorkOrderUpdateResponse {
  33. message: string;
  34. data: WorkOrder;
  35. }
  36. interface WorkOrderStatusChangeResponse {
  37. message: string;
  38. status: string;
  39. history_id?: string;
  40. }
  41. interface WorkOrderDeadlineResponse {
  42. data: {
  43. deadline: string;
  44. remaining_hours: number;
  45. is_overdue: boolean;
  46. };
  47. }
  48. interface WorkOrderHistoryItem {
  49. id: string;
  50. status_from: string;
  51. status_to: string;
  52. operator: string;
  53. comment?: string;
  54. created_at: string;
  55. }
  56. interface WorkOrderHistoryResponse {
  57. data: WorkOrderHistoryItem[];
  58. pagination: {
  59. total: number;
  60. current: number;
  61. pageSize: number;
  62. };
  63. }
  64. interface WorkOrderAssignResponse {
  65. message: string;
  66. assignee: string;
  67. }
  68. interface WorkOrderSettingsResponse {
  69. data: WorkOrderSettings;
  70. message?: string;
  71. }
  72. interface WorkOrderCategoryResponse {
  73. data: string[];
  74. message?: string;
  75. }
  76. interface WorkOrderAttachmentResponse {
  77. message: string;
  78. data: {
  79. id: string;
  80. url: string;
  81. name: string;
  82. };
  83. }
  84. interface WorkOrderCommentResponse {
  85. message: string;
  86. data: {
  87. id: string;
  88. content: string;
  89. created_at: string;
  90. author: string;
  91. }[];
  92. }
  93. export const WorkOrderAPI = {
  94. getList: async (params?: WorkOrderListParams): Promise<WorkOrderListResponse> => {
  95. try {
  96. const response = await axios.get('/work-orders', { params });
  97. return response.data;
  98. } catch (error) {
  99. if (axios.isAxiosError(error)) {
  100. const errorMessage = error.response?.data?.message || error.message;
  101. throw new Error(`获取工单列表失败: ${errorMessage}`);
  102. }
  103. throw new Error('获取工单列表失败: 未知错误');
  104. }
  105. },
  106. create: async (data: {
  107. title: string;
  108. device_id?: number;
  109. problem_desc: string;
  110. problem_type: string;
  111. priority: WorkOrderPriority;
  112. deadline?: Date;
  113. attachments?: Array<{
  114. id: string;
  115. url: string;
  116. name: string;
  117. }>;
  118. }): Promise<WorkOrderCreateResponse> => {
  119. try {
  120. const response = await axios.post('/work-orders', data);
  121. return response.data;
  122. } catch (error) {
  123. throw error;
  124. }
  125. },
  126. getDetail: async (id: string): Promise<WorkOrderDetailResponse> => {
  127. try {
  128. const response = await axios.get(`/work-orders/${id}`);
  129. return response.data;
  130. } catch (error) {
  131. throw error;
  132. }
  133. },
  134. update: async (id: string, data: {
  135. status?: WorkOrderStatus;
  136. priority?: WorkOrderPriority;
  137. feedback?: string;
  138. assignee_id?: number;
  139. deadline?: Date;
  140. }): Promise<WorkOrderUpdateResponse> => {
  141. try {
  142. const response = await axios.put(`/work-orders/${id}`, data);
  143. return response.data;
  144. } catch (error) {
  145. throw error;
  146. }
  147. },
  148. changeStatus: async (id: string, status: string, operator: string, comment?: string): Promise<WorkOrderStatusChangeResponse> => {
  149. try {
  150. const response = await axios.post(`/work-orders/${id}/status`, {
  151. status,
  152. operator,
  153. comment
  154. });
  155. return response.data;
  156. } catch (error) {
  157. throw error;
  158. }
  159. },
  160. getDeadline: async (id: string): Promise<WorkOrderDeadlineResponse> => {
  161. try {
  162. const response = await axios.get(`/work-orders/${id}/deadline`);
  163. return response.data;
  164. } catch (error) {
  165. throw error;
  166. }
  167. },
  168. getHistory: async (id: string, page = 1, pageSize = 10): Promise<WorkOrderHistoryResponse> => {
  169. try {
  170. const response = await axios.get(`/work-orders/${id}/history`, {
  171. params: { page, pageSize }
  172. });
  173. return response.data;
  174. } catch (error) {
  175. throw error;
  176. }
  177. },
  178. getStatusHistory: async (id: string): Promise<WorkOrderHistoryResponse> => {
  179. try {
  180. const response = await axios.get(`/work-orders/${id}/status-history`);
  181. return response.data;
  182. } catch (error) {
  183. throw error;
  184. }
  185. },
  186. assign: async (id: string, assignee: string): Promise<WorkOrderAssignResponse> => {
  187. try {
  188. const response = await axios.post(`/work-orders/${id}/assign`, { assignee });
  189. return response.data;
  190. } catch (error) {
  191. throw error;
  192. }
  193. },
  194. getSettings: async (): Promise<WorkOrderSettingsResponse> => {
  195. try {
  196. const response = await axios.get('/work-orders/settings');
  197. return response.data;
  198. } catch (error) {
  199. throw error;
  200. }
  201. },
  202. updateSettings: async (data: WorkOrderSettings): Promise<WorkOrderSettingsResponse> => {
  203. try {
  204. const response = await axios.post('/work-orders/settings', data);
  205. return response.data;
  206. } catch (error) {
  207. throw error;
  208. }
  209. },
  210. // 新增分类相关API
  211. getCategories: async (): Promise<WorkOrderCategoryResponse> => {
  212. // 检查缓存是否有效
  213. if (categoriesCache && Date.now() < cacheExpireTime) {
  214. return { data: categoriesCache };
  215. }
  216. try {
  217. const response = await axios.get('/work-orders/categories');
  218. categoriesCache = response.data.data;
  219. cacheExpireTime = Date.now() + CACHE_EXPIRE_DURATION;
  220. return response.data;
  221. } catch (error) {
  222. if (axios.isAxiosError(error)) {
  223. const errorMessage = error.response?.data?.message || error.message;
  224. throw new Error(`获取分类失败: ${errorMessage}`);
  225. }
  226. throw new Error('获取分类失败: 未知错误');
  227. }
  228. },
  229. // 新增附件相关API
  230. uploadAttachment: async (id: string, file: File): Promise<WorkOrderAttachmentResponse> => {
  231. try {
  232. const formData = new FormData();
  233. formData.append('file', file);
  234. const response = await axios.post(`/work-orders/${id}/attachments`, formData, {
  235. headers: {
  236. 'Content-Type': 'multipart/form-data'
  237. }
  238. });
  239. return response.data;
  240. } catch (error) {
  241. throw error;
  242. }
  243. },
  244. // 新增评论相关API
  245. getComments: async (id: string): Promise<WorkOrderCommentResponse> => {
  246. try {
  247. const response = await axios.get(`/work-orders/${id}/comments`);
  248. return response.data;
  249. } catch (error) {
  250. throw error;
  251. }
  252. },
  253. addComment: async (id: string, content: string): Promise<WorkOrderCommentResponse> => {
  254. try {
  255. const response = await axios.post(`/work-orders/${id}/comments`, { content });
  256. return response.data;
  257. } catch (error) {
  258. throw error;
  259. }
  260. },
  261. exportList: async (params?: WorkOrderListParams): Promise<Blob> => {
  262. try {
  263. const response = await axios.get('/work-orders/export', {
  264. params,
  265. responseType: 'blob'
  266. });
  267. return response.data;
  268. } catch (error) {
  269. if (axios.isAxiosError(error)) {
  270. const errorMessage = error.response?.data?.message || error.message;
  271. throw new Error(`导出工单失败: ${errorMessage}`);
  272. }
  273. throw new Error('导出工单失败: 未知错误');
  274. }
  275. },
  276. };