Compare commits
	
		
			15 Commits
		
	
	
		
			ee2f3e12d2
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b4662a2b10 | |||
| 840fb98988 | |||
| fcd1b1c140 | |||
| 22f633e20b | |||
| e704249d75 | |||
| 0ff82657ab | |||
| fff309f56b | |||
| d3700c8835 | |||
| ea44c9caea | |||
| ab8ea6977f | |||
| d5f91b9b12 | |||
| a8d9b033f3 | |||
| e1fb3055bb | |||
| 6d452394aa | |||
| 62801326cb | 
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,5 +1,12 @@ | |||||||
| import http from '../utils/http'; | import http from '../utils/http'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} AreaControllerResponse |  * @typedef {object} AreaControllerResponse | ||||||
|  * @property {number} id |  * @property {number} id | ||||||
| @@ -67,8 +74,16 @@ export const updateAreaController = (id, areaControllerData) => { | |||||||
| /** | /** | ||||||
|  * 根据ID删除一个区域主控(软删除) |  * 根据ID删除一个区域主控(软删除) | ||||||
|  * @param {string} id - 区域主控ID |  * @param {string} id - 区域主控ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const deleteAreaController = (id) => { | export const deleteAreaController = (id) => { | ||||||
|   return http.delete(`/api/v1/area-controllers/${id}`); |   return http.delete(`/api/v1/area-controllers/${id}`); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const AreaControllerApi = { | ||||||
|  |   list: getAreaControllers, | ||||||
|  |   create: createAreaController, | ||||||
|  |   getById: getAreaControllerById, | ||||||
|  |   update: updateAreaController, | ||||||
|  |   delete: deleteAreaController, | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -2,6 +2,13 @@ import http from '../utils/http'; | |||||||
|  |  | ||||||
| // --- Typedefs --- | // --- Typedefs --- | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} DeviceResponse |  * @typedef {object} DeviceResponse | ||||||
|  * @property {number} id |  * @property {number} id | ||||||
| @@ -109,7 +116,7 @@ export const updateDevice = (id, deviceData) => { | |||||||
| /** | /** | ||||||
|  * 根据设备ID删除一个设备(软删除) |  * 根据设备ID删除一个设备(软删除) | ||||||
|  * @param {string} id - 设备ID |  * @param {string} id - 设备ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const deleteDevice = (id) => { | export const deleteDevice = (id) => { | ||||||
|   return http.delete(`/api/v1/devices/${id}`); |   return http.delete(`/api/v1/devices/${id}`); | ||||||
| @@ -119,7 +126,7 @@ export const deleteDevice = (id) => { | |||||||
|  * 根据设备ID和指定的动作(开启或关闭)来手动控制设备 |  * 根据设备ID和指定的动作(开启或关闭)来手动控制设备 | ||||||
|  * @param {string} id - 设备ID |  * @param {string} id - 设备ID | ||||||
|  * @param {ManualControlDeviceRequest} manualControlData - 手动控制指令 |  * @param {ManualControlDeviceRequest} manualControlData - 手动控制指令 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const manualControlDevice = (id, manualControlData) => { | export const manualControlDevice = (id, manualControlData) => { | ||||||
|   return http.post(`/api/v1/devices/manual-control/${id}`, manualControlData); |   return http.post(`/api/v1/devices/manual-control/${id}`, manualControlData); | ||||||
| @@ -167,7 +174,7 @@ export const updateAreaController = (id, areaControllerData) => { | |||||||
| /** | /** | ||||||
|  * 根据ID删除一个区域主控 |  * 根据ID删除一个区域主控 | ||||||
|  * @param {string} id - 区域主控ID |  * @param {string} id - 区域主控ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const deleteAreaController = (id) => { | export const deleteAreaController = (id) => { | ||||||
|   return http.delete(`/api/v1/area-controllers/${id}`); |   return http.delete(`/api/v1/area-controllers/${id}`); | ||||||
|   | |||||||
| @@ -1,5 +1,12 @@ | |||||||
| import http from '../utils/http'; | import http from '../utils/http'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {('执行器'|'传感器')} DeviceCategory |  * @typedef {('执行器'|'传感器')} DeviceCategory | ||||||
|  */ |  */ | ||||||
| @@ -68,7 +75,7 @@ const createDeviceTemplate = (deviceTemplateData) => { | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 根据设备模板ID获取单个设备模板的详细信息 |  * 根据设备模板ID获取单个设备模板的详细信息 | ||||||
|  * @param {string} id - 设备模板ID |  * @param {number} id - 设备模板ID | ||||||
|  * @returns {Promise<DeviceTemplateResponse>} |  * @returns {Promise<DeviceTemplateResponse>} | ||||||
|  */ |  */ | ||||||
| const getDeviceTemplateById = (id) => { | const getDeviceTemplateById = (id) => { | ||||||
| @@ -77,7 +84,7 @@ const getDeviceTemplateById = (id) => { | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 根据设备模板ID更新一个已存在的设备模板信息 |  * 根据设备模板ID更新一个已存在的设备模板信息 | ||||||
|  * @param {string} id - 设备模板ID |  * @param {number} id - 设备模板ID | ||||||
|  * @param {UpdateDeviceTemplateRequest} deviceTemplateData - 要更新的设备模板信息 |  * @param {UpdateDeviceTemplateRequest} deviceTemplateData - 要更新的设备模板信息 | ||||||
|  * @returns {Promise<DeviceTemplateResponse>} |  * @returns {Promise<DeviceTemplateResponse>} | ||||||
|  */ |  */ | ||||||
| @@ -87,8 +94,8 @@ const updateDeviceTemplate = (id, deviceTemplateData) => { | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 根据设备模板ID删除一个设备模板(软删除) |  * 根据设备模板ID删除一个设备模板(软删除) | ||||||
|  * @param {string} id - 设备模板ID |  * @param {number} id - 设备模板ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| const deleteDeviceTemplate = (id) => { | const deleteDeviceTemplate = (id) => { | ||||||
|   return http.delete(`/api/v1/device-templates/${id}`); |   return http.delete(`/api/v1/device-templates/${id}`); | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PaginationDTO |  * @typedef {object} PaginationDTO | ||||||
|  * @property {number} page |  * @property {number} page | ||||||
|  * @property {number} pageSize |  * @property {number} page_size | ||||||
|  * @property {number} total |  * @property {number} total | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @@ -27,7 +27,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} DeviceCommandLogsParams |  * @typedef {object} DeviceCommandLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [device_id] |  * @property {number} [device_id] | ||||||
|  * @property {string} [start_time] |  * @property {string} [start_time] | ||||||
| @@ -69,7 +69,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} FeedUsageRecordsParams |  * @typedef {object} FeedUsageRecordsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pen_id] |  * @property {number} [pen_id] | ||||||
|  * @property {number} [feed_formula_id] |  * @property {number} [feed_formula_id] | ||||||
| @@ -111,7 +111,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} MedicationLogsParams |  * @typedef {object} MedicationLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pig_batch_id] |  * @property {number} [pig_batch_id] | ||||||
|  * @property {number} [medication_id] |  * @property {number} [medication_id] | ||||||
| @@ -121,6 +121,49 @@ import http from '../utils/http'; | |||||||
|  * @property {number} [operator_id] |  * @property {number} [operator_id] | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {('邮件'|'企业微信'|'飞书'|'日志')} NotifierType | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {('发送成功'|'发送失败'|'已跳过')} NotificationStatus | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} NotificationDTO | ||||||
|  |  * @property {number} id | ||||||
|  |  * @property {number} user_id | ||||||
|  |  * @property {NotifierType} notifier_type | ||||||
|  |  * @property {string} to_address | ||||||
|  |  * @property {string} title | ||||||
|  |  * @property {string} message | ||||||
|  |  * @property {number} level - 日志级别, 见 ZapcoreLevel 枚举 | ||||||
|  |  * @property {string} alarm_timestamp | ||||||
|  |  * @property {NotificationStatus} status | ||||||
|  |  * @property {string} error_message | ||||||
|  |  * @property {string} created_at | ||||||
|  |  * @property {string} updated_at | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} ListNotificationResponse | ||||||
|  |  * @property {Array<NotificationDTO>} list | ||||||
|  |  * @property {PaginationDTO} pagination | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} NotificationsParams | ||||||
|  |  * @property {number} [page] | ||||||
|  |  * @property {number} [page_size] | ||||||
|  |  * @property {string} [order_by] | ||||||
|  |  * @property {string} [start_time] | ||||||
|  |  * @property {string} [end_time] | ||||||
|  |  * @property {number} [level] - 日志级别, 见 ZapcoreLevel 枚举 | ||||||
|  |  * @property {NotifierType} [notifier_type] | ||||||
|  |  * @property {NotificationStatus} [status] | ||||||
|  |  * @property {number} [user_id] | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {('等待中'|'已完成'|'已超时')} PendingCollectionStatus |  * @typedef {('等待中'|'已完成'|'已超时')} PendingCollectionStatus | ||||||
|  */ |  */ | ||||||
| @@ -144,7 +187,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PendingCollectionsParams |  * @typedef {object} PendingCollectionsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [device_id] |  * @property {number} [device_id] | ||||||
|  * @property {string} [status] |  * @property {string} [status] | ||||||
| @@ -180,7 +223,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PigBatchLogsParams |  * @typedef {object} PigBatchLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pig_batch_id] |  * @property {number} [pig_batch_id] | ||||||
|  * @property {string} [change_type] |  * @property {string} [change_type] | ||||||
| @@ -213,7 +256,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PigPurchasesParams |  * @typedef {object} PigPurchasesParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pig_batch_id] |  * @property {number} [pig_batch_id] | ||||||
|  * @property {string} [supplier] |  * @property {string} [supplier] | ||||||
| @@ -246,7 +289,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PigSalesParams |  * @typedef {object} PigSalesParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pig_batch_id] |  * @property {number} [pig_batch_id] | ||||||
|  * @property {string} [buyer] |  * @property {string} [buyer] | ||||||
| @@ -289,7 +332,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PigSickLogsParams |  * @typedef {object} PigSickLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pig_batch_id] |  * @property {number} [pig_batch_id] | ||||||
|  * @property {number} [pen_id] |  * @property {number} [pen_id] | ||||||
| @@ -328,7 +371,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PigTransferLogsParams |  * @typedef {object} PigTransferLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pig_batch_id] |  * @property {number} [pig_batch_id] | ||||||
|  * @property {number} [pen_id] |  * @property {number} [pen_id] | ||||||
| @@ -347,6 +390,7 @@ import http from '../utils/http'; | |||||||
|  * @typedef {object} PlanExecutionLogDTO |  * @typedef {object} PlanExecutionLogDTO | ||||||
|  * @property {number} id |  * @property {number} id | ||||||
|  * @property {number} plan_id |  * @property {number} plan_id | ||||||
|  |  * @property {string} plan_name | ||||||
|  * @property {ExecutionStatus} status |  * @property {ExecutionStatus} status | ||||||
|  * @property {string} started_at |  * @property {string} started_at | ||||||
|  * @property {string} ended_at |  * @property {string} ended_at | ||||||
| @@ -364,7 +408,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PlanExecutionLogsParams |  * @typedef {object} PlanExecutionLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [plan_id] |  * @property {number} [plan_id] | ||||||
|  * @property {string} [status] |  * @property {string} [status] | ||||||
| @@ -400,7 +444,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} RawMaterialPurchasesParams |  * @typedef {object} RawMaterialPurchasesParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [raw_material_id] |  * @property {number} [raw_material_id] | ||||||
|  * @property {string} [supplier] |  * @property {string} [supplier] | ||||||
| @@ -432,7 +476,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} RawMaterialStockLogsParams |  * @typedef {object} RawMaterialStockLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [raw_material_id] |  * @property {number} [raw_material_id] | ||||||
|  * @property {string} [source_type] |  * @property {string} [source_type] | ||||||
| @@ -463,7 +507,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} SensorDataParams |  * @typedef {object} SensorDataParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [device_id] |  * @property {number} [device_id] | ||||||
|  * @property {string} [sensor_type] |  * @property {string} [sensor_type] | ||||||
| @@ -501,7 +545,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} TaskExecutionLogsParams |  * @typedef {object} TaskExecutionLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [plan_execution_log_id] |  * @property {number} [plan_execution_log_id] | ||||||
|  * @property {number} [task_id] |  * @property {number} [task_id] | ||||||
| @@ -539,7 +583,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} UserActionLogsParams |  * @typedef {object} UserActionLogsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [user_id] |  * @property {number} [user_id] | ||||||
|  * @property {string} [username] |  * @property {string} [username] | ||||||
| @@ -568,7 +612,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} WeighingBatchesParams |  * @typedef {object} WeighingBatchesParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [pig_batch_id] |  * @property {number} [pig_batch_id] | ||||||
|  * @property {string} [start_time] |  * @property {string} [start_time] | ||||||
| @@ -597,7 +641,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} WeighingRecordsParams |  * @typedef {object} WeighingRecordsParams | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [weighing_batch_id] |  * @property {number} [weighing_batch_id] | ||||||
|  * @property {number} [pen_id] |  * @property {number} [pen_id] | ||||||
| @@ -606,6 +650,25 @@ import http from '../utils/http'; | |||||||
|  * @property {number} [operator_id] |  * @property {number} [operator_id] | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | // --- Enums --- | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 日志级别, 对应后端的 zapcore.Level | ||||||
|  |  * @enum {number} | ||||||
|  |  */ | ||||||
|  | export const ZapcoreLevel = { | ||||||
|  |   Debug: -1, | ||||||
|  |   Info: 0, | ||||||
|  |   Warn: 1, | ||||||
|  |   Error: 2, | ||||||
|  |   DPanic: 3, | ||||||
|  |   Panic: 4, | ||||||
|  |   Fatal: 5, | ||||||
|  |   _minLevel: -1, | ||||||
|  |   _maxLevel: 5, | ||||||
|  |   Invalid: 6, | ||||||
|  |   _numLevels: 7, | ||||||
|  | }; | ||||||
|  |  | ||||||
| // --- Functions --- | // --- Functions --- | ||||||
|  |  | ||||||
| @@ -623,7 +686,8 @@ const processResponse = (responseData) => { | |||||||
|  * @returns {Promise<{list: Array<DeviceCommandLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<DeviceCommandLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getDeviceCommandLogs = async (params) => { | export const getDeviceCommandLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/device-command-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/device-command-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -633,7 +697,8 @@ export const getDeviceCommandLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<FeedUsageRecordDTO>, total: number}>} |  * @returns {Promise<{list: Array<FeedUsageRecordDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getFeedUsageRecords = async (params) => { | export const getFeedUsageRecords = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/feed-usage-records', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/feed-usage-records', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -643,7 +708,19 @@ export const getFeedUsageRecords = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<MedicationLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<MedicationLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getMedicationLogs = async (params) => { | export const getMedicationLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/medication-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/medication-logs', { params: newParams }); | ||||||
|  |   return processResponse(responseData); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 批量查询通知 | ||||||
|  |  * @param {NotificationsParams} params - 查询参数 | ||||||
|  |  * @returns {Promise<{list: Array<NotificationDTO>, total: number}>} | ||||||
|  |  */ | ||||||
|  | export const getNotifications = async (params) => { | ||||||
|  |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/notifications', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -653,7 +730,8 @@ export const getMedicationLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<PendingCollectionDTO>, total: number}>} |  * @returns {Promise<{list: Array<PendingCollectionDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getPendingCollections = async (params) => { | export const getPendingCollections = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/pending-collections', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/pending-collections', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -663,7 +741,8 @@ export const getPendingCollections = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<PigBatchLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<PigBatchLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getPigBatchLogs = async (params) => { | export const getPigBatchLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/pig-batch-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/pig-batch-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -673,7 +752,8 @@ export const getPigBatchLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<PigPurchaseDTO>, total: number}>} |  * @returns {Promise<{list: Array<PigPurchaseDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getPigPurchases = async (params) => { | export const getPigPurchases = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/pig-purchases', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/pig-purchases', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -683,7 +763,8 @@ export const getPigPurchases = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<PigSaleDTO>, total: number}>} |  * @returns {Promise<{list: Array<PigSaleDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getPigSales = async (params) => { | export const getPigSales = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/pig-sales', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/pig-sales', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -693,7 +774,8 @@ export const getPigSales = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<PigSickLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<PigSickLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getPigSickLogs = async (params) => { | export const getPigSickLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/pig-sick-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/pig-sick-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -703,7 +785,8 @@ export const getPigSickLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<PigTransferLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<PigTransferLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getPigTransferLogs = async (params) => { | export const getPigTransferLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/pig-transfer-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/pig-transfer-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -713,7 +796,8 @@ export const getPigTransferLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<PlanExecutionLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<PlanExecutionLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getPlanExecutionLogs = async (params) => { | export const getPlanExecutionLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/plan-execution-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/plan-execution-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -723,7 +807,8 @@ export const getPlanExecutionLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<RawMaterialPurchaseDTO>, total: number}>} |  * @returns {Promise<{list: Array<RawMaterialPurchaseDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getRawMaterialPurchases = async (params) => { | export const getRawMaterialPurchases = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/raw-material-purchases', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/raw-material-purchases', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -733,7 +818,8 @@ export const getRawMaterialPurchases = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<RawMaterialStockLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<RawMaterialStockLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getRawMaterialStockLogs = async (params) => { | export const getRawMaterialStockLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/raw-material-stock-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/raw-material-stock-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -743,7 +829,8 @@ export const getRawMaterialStockLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<SensorDataDTO>, total: number}>} |  * @returns {Promise<{list: Array<SensorDataDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getSensorData = async (params) => { | export const getSensorData = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/sensor-data', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/sensor-data', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -753,7 +840,8 @@ export const getSensorData = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<TaskExecutionLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<TaskExecutionLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getTaskExecutionLogs = async (params) => { | export const getTaskExecutionLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/task-execution-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/task-execution-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -763,7 +851,8 @@ export const getTaskExecutionLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<UserActionLogDTO>, total: number}>} |  * @returns {Promise<{list: Array<UserActionLogDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getUserActionLogs = async (params) => { | export const getUserActionLogs = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/user-action-logs', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/user-action-logs', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -773,7 +862,8 @@ export const getUserActionLogs = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<WeighingBatchDTO>, total: number}>} |  * @returns {Promise<{list: Array<WeighingBatchDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getWeighingBatches = async (params) => { | export const getWeighingBatches = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/weighing-batches', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/weighing-batches', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -783,6 +873,28 @@ export const getWeighingBatches = async (params) => { | |||||||
|  * @returns {Promise<{list: Array<WeighingRecordDTO>, total: number}>} |  * @returns {Promise<{list: Array<WeighingRecordDTO>, total: number}>} | ||||||
|  */ |  */ | ||||||
| export const getWeighingRecords = async (params) => { | export const getWeighingRecords = async (params) => { | ||||||
|   const responseData = await http.get('/api/v1/monitor/weighing-records', { params }); |   const newParams = { ...params, page_size: params.page_size }; | ||||||
|  |   const responseData = await http.get('/api/v1/monitor/weighing-records', { params: newParams }); | ||||||
|   return processResponse(responseData); |   return processResponse(responseData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const MonitorApi = { | ||||||
|  |   getDeviceCommandLogs, | ||||||
|  |   getFeedUsageRecords, | ||||||
|  |   getMedicationLogs, | ||||||
|  |   getNotifications, | ||||||
|  |   getPendingCollections, | ||||||
|  |   getPigBatchLogs, | ||||||
|  |   getPigPurchases, | ||||||
|  |   getPigSales, | ||||||
|  |   getPigSickLogs, | ||||||
|  |   getPigTransferLogs, | ||||||
|  |   getPlanExecutionLogs, | ||||||
|  |   getRawMaterialPurchases, | ||||||
|  |   getRawMaterialStockLogs, | ||||||
|  |   getSensorData, | ||||||
|  |   getTaskExecutionLogs, | ||||||
|  |   getUserActionLogs, | ||||||
|  |   getWeighingBatches, | ||||||
|  |   getWeighingRecords, | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -1,5 +1,12 @@ | |||||||
| import http from '../utils/http'; | import http from '../utils/http'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} PenResponse |  * @typedef {object} PenResponse | ||||||
|  * @property {number} id |  * @property {number} id | ||||||
| @@ -70,7 +77,7 @@ export const updatePen = (id, penData) => { | |||||||
| /** | /** | ||||||
|  * 根据ID删除一个猪栏 |  * 根据ID删除一个猪栏 | ||||||
|  * @param {number} id - 猪栏ID |  * @param {number} id - 猪栏ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const deletePen = (id) => { | export const deletePen = (id) => { | ||||||
|   return http.delete(`/api/v1/pens/${id}`); |   return http.delete(`/api/v1/pens/${id}`); | ||||||
| @@ -85,3 +92,12 @@ export const deletePen = (id) => { | |||||||
| export const updatePenStatus = (id, statusData) => { | export const updatePenStatus = (id, statusData) => { | ||||||
|   return http.put(`/api/v1/pens/${id}/status`, statusData); |   return http.put(`/api/v1/pens/${id}/status`, statusData); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const PenApi = { | ||||||
|  |   getPens, | ||||||
|  |   createPen, | ||||||
|  |   getPenById, | ||||||
|  |   updatePen, | ||||||
|  |   deletePen, | ||||||
|  |   updatePenStatus, | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -2,6 +2,13 @@ import http from '../utils/http'; | |||||||
|  |  | ||||||
| // --- Typedefs --- | // --- Typedefs --- | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {('自繁'|'外购')} PigBatchOriginType |  * @typedef {('自繁'|'外购')} PigBatchOriginType | ||||||
|  */ |  */ | ||||||
| @@ -15,15 +22,15 @@ import http from '../utils/http'; | |||||||
|  * @property {number} id - 批次ID |  * @property {number} id - 批次ID | ||||||
|  * @property {string} batch_number - 批次编号 |  * @property {string} batch_number - 批次编号 | ||||||
|  * @property {PigBatchOriginType} origin_type - 批次来源 |  * @property {PigBatchOriginType} origin_type - 批次来源 | ||||||
|  * @property {string} start_date - 批次开始日期 |  * @property {string} [start_date] - 批次开始日期 | ||||||
|  * @property {string} [end_date] - 批次结束日期 |  * @property {string} [end_date] - 批次结束日期 | ||||||
|  * @property {number} initial_count - 初始数量 |  * @property {number} initial_count - 初始数量 | ||||||
|  * @property {PigBatchStatus} status - 批次状态 |  * @property {PigBatchStatus} status - 批次状态 | ||||||
|  * @property {boolean} is_active - 是否活跃 |  * @property {boolean} is_active - 是否活跃 | ||||||
|  * @property {string} create_time - 创建时间 |  * @property {string} create_time - 创建时间 | ||||||
|  * @property {string} update_time - 更新时间 |  * @property {string} update_time - 更新时间 | ||||||
|  * @property {number} currentTotalQuantity - 当前总数 |  * @property {number} current_total_quantity - 当前总数 | ||||||
|  * @property {number} currentTotalPigsInPens - 当前存栏总数 |  * @property {number} current_total_pigs_in_pens - 当前存栏总数 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -57,54 +64,54 @@ import http from '../utils/http'; | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} BuyPigsRequest |  * @typedef {object} BuyPigsRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 买入猪只数量 |  * @property {number} quantity - 买入猪只数量 | ||||||
|  * @property {number} unitPrice - 单价 |  * @property {number} unit_price - 单价 | ||||||
|  * @property {number} totalPrice - 总价 |  * @property {number} total_price - 总价 | ||||||
|  * @property {string} traderName - 交易方名称 |  * @property {string} trader_name - 交易方名称 | ||||||
|  * @property {string} tradeDate - 交易日期 |  * @property {string} trade_date - 交易日期 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} SellPigsRequest |  * @typedef {object} SellPigsRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 卖出猪只数量 |  * @property {number} quantity - 卖出猪只数量 | ||||||
|  * @property {number} unitPrice - 单价 |  * @property {number} unit_price - 单价 | ||||||
|  * @property {number} totalPrice - 总价 |  * @property {number} total_price - 总价 | ||||||
|  * @property {string} traderName - 交易方名称 |  * @property {string} trader_name - 交易方名称 | ||||||
|  * @property {string} tradeDate - 交易日期 |  * @property {string} trade_date - 交易日期 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} MovePigsIntoPenRequest |  * @typedef {object} MovePigsIntoPenRequest | ||||||
|  * @property {number} toPenID - 目标猪栏ID |  * @property {number} to_pen_id - 目标猪栏ID | ||||||
|  * @property {number} quantity - 移入猪只数量 |  * @property {number} quantity - 移入猪只数量 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} TransferPigsWithinBatchRequest |  * @typedef {object} TransferPigsWithinBatchRequest | ||||||
|  * @property {number} fromPenID - 源猪栏ID |  * @property {number} from_pen_id - 源猪栏ID | ||||||
|  * @property {number} toPenID - 目标猪栏ID |  * @property {number} to_pen_id - 目标猪栏ID | ||||||
|  * @property {number} quantity - 调栏猪只数量 |  * @property {number} quantity - 调栏猪只数量 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} TransferPigsAcrossBatchesRequest |  * @typedef {object} TransferPigsAcrossBatchesRequest | ||||||
|  * @property {number} fromPenID - 源猪栏ID |  * @property {number} dest_batch_id - 目标猪批次ID | ||||||
|  * @property {number} destBatchID - 目标猪批次ID |  * @property {number} from_pen_id - 源猪栏ID | ||||||
|  * @property {number} toPenID - 目标猪栏ID |  * @property {number} to_pen_id - 目标猪栏ID | ||||||
|  * @property {number} quantity - 调栏猪只数量 |  * @property {number} quantity - 调栏猪只数量 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} ReclassifyPenToNewBatchRequest |  * @typedef {object} ReclassifyPenToNewBatchRequest | ||||||
|  * @property {number} penID - 待划拨的猪栏ID |  * @property {number} pen_id - 待划拨的猪栏ID | ||||||
|  * @property {number} toBatchID - 目标猪批次ID |  * @property {number} to_batch_id - 目标猪批次ID | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @@ -114,53 +121,53 @@ import http from '../utils/http'; | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} RecordSickPigsRequest |  * @typedef {object} RecordSickPigsRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 病猪数量 |  * @property {number} quantity - 病猪数量 | ||||||
|  * @property {PigBatchSickPigTreatmentLocation} treatmentLocation - 治疗地点 |  * @property {PigBatchSickPigTreatmentLocation} treatment_location - 治疗地点 | ||||||
|  * @property {string} happenedAt - 发生时间 |  * @property {string} happened_at - 发生时间 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} RecordSickPigRecoveryRequest |  * @typedef {object} RecordSickPigRecoveryRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 康复猪数量 |  * @property {number} quantity - 康复猪数量 | ||||||
|  * @property {PigBatchSickPigTreatmentLocation} treatmentLocation - 治疗地点 |  * @property {PigBatchSickPigTreatmentLocation} treatment_location - 治疗地点 | ||||||
|  * @property {string} happenedAt - 发生时间 |  * @property {string} happened_at - 发生时间 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} RecordSickPigDeathRequest |  * @typedef {object} RecordSickPigDeathRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 死亡猪数量 |  * @property {number} quantity - 死亡猪数量 | ||||||
|  * @property {PigBatchSickPigTreatmentLocation} treatmentLocation - 治疗地点 |  * @property {PigBatchSickPigTreatmentLocation} treatment_location - 治疗地点 | ||||||
|  * @property {string} happenedAt - 发生时间 |  * @property {string} happened_at - 发生时间 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} RecordSickPigCullRequest |  * @typedef {object} RecordSickPigCullRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 淘汰猪数量 |  * @property {number} quantity - 淘汰猪数量 | ||||||
|  * @property {PigBatchSickPigTreatmentLocation} treatmentLocation - 治疗地点 |  * @property {PigBatchSickPigTreatmentLocation} treatment_location - 治疗地点 | ||||||
|  * @property {string} happenedAt - 发生时间 |  * @property {string} happened_at - 发生时间 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} RecordDeathRequest |  * @typedef {object} RecordDeathRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 死亡猪数量 |  * @property {number} quantity - 死亡猪数量 | ||||||
|  * @property {string} happenedAt - 发生时间 |  * @property {string} happened_at - 发生时间 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} RecordCullRequest |  * @typedef {object} RecordCullRequest | ||||||
|  * @property {number} penID - 猪栏ID |  * @property {number} pen_id - 猪栏ID | ||||||
|  * @property {number} quantity - 淘汰猪数量 |  * @property {number} quantity - 淘汰猪数量 | ||||||
|  * @property {string} happenedAt - 发生时间 |  * @property {string} happened_at - 发生时间 | ||||||
|  * @property {string} [remarks] - 备注 |  * @property {string} [remarks] - 备注 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @@ -190,7 +197,7 @@ import http from '../utils/http'; | |||||||
|  * @returns {Promise<Array<PigBatchResponseDTO>>} |  * @returns {Promise<Array<PigBatchResponseDTO>>} | ||||||
|  */ |  */ | ||||||
| export const getPigBatches = (params) => { | export const getPigBatches = (params) => { | ||||||
|   return http.get('/api/v1/pig-batches', { params }); |     return http.get('/api/v1/pig-batches', params); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -224,7 +231,7 @@ export const updatePigBatch = (id, batchData) => { | |||||||
| /** | /** | ||||||
|  * 根据ID删除一个猪批次 |  * 根据ID删除一个猪批次 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const deletePigBatch = (id) => { | export const deletePigBatch = (id) => { | ||||||
|     return http.delete(`/api/v1/pig-batches/${id}`); |     return http.delete(`/api/v1/pig-batches/${id}`); | ||||||
| @@ -236,7 +243,7 @@ export const deletePigBatch = (id) => { | |||||||
|  * 为猪批次分配空栏 |  * 为猪批次分配空栏 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {AssignEmptyPensToBatchRequest} pensData - 待分配的猪栏ID列表 |  * @param {AssignEmptyPensToBatchRequest} pensData - 待分配的猪栏ID列表 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const assignPensToBatch = (id, pensData) => { | export const assignPensToBatch = (id, pensData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/assign-pens/${id}`, pensData); |     return http.post(`/api/v1/pig-batches/assign-pens/${id}`, pensData); | ||||||
| @@ -246,7 +253,7 @@ export const assignPensToBatch = (id, pensData) => { | |||||||
|  * 从猪批次移除空栏 |  * 从猪批次移除空栏 | ||||||
|  * @param {number} penID - 待移除的猪栏ID |  * @param {number} penID - 待移除的猪栏ID | ||||||
|  * @param {number} batchID - 猪批次ID |  * @param {number} batchID - 猪批次ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const removePenFromBatch = (penID, batchID) => { | export const removePenFromBatch = (penID, batchID) => { | ||||||
|     return http.delete(`/api/v1/pig-batches/remove-pen/${penID}/${batchID}`); |     return http.delete(`/api/v1/pig-batches/remove-pen/${penID}/${batchID}`); | ||||||
| @@ -256,7 +263,7 @@ export const removePenFromBatch = (penID, batchID) => { | |||||||
|  * 处理买猪的业务逻辑 |  * 处理买猪的业务逻辑 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {BuyPigsRequest} buyData - 买猪请求信息 |  * @param {BuyPigsRequest} buyData - 买猪请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const buyPigsForBatch = (id, buyData) => { | export const buyPigsForBatch = (id, buyData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/buy-pigs/${id}`, buyData); |     return http.post(`/api/v1/pig-batches/buy-pigs/${id}`, buyData); | ||||||
| @@ -266,7 +273,7 @@ export const buyPigsForBatch = (id, buyData) => { | |||||||
|  * 处理卖猪的业务逻辑 |  * 处理卖猪的业务逻辑 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {SellPigsRequest} sellData - 卖猪请求信息 |  * @param {SellPigsRequest} sellData - 卖猪请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const sellPigsFromBatch = (id, sellData) => { | export const sellPigsFromBatch = (id, sellData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/sell-pigs/${id}`, sellData); |     return http.post(`/api/v1/pig-batches/sell-pigs/${id}`, sellData); | ||||||
| @@ -276,7 +283,7 @@ export const sellPigsFromBatch = (id, sellData) => { | |||||||
|  * 将猪只从“虚拟库存”移入指定猪栏 |  * 将猪只从“虚拟库存”移入指定猪栏 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {MovePigsIntoPenRequest} moveData - 移入猪只请求信息 |  * @param {MovePigsIntoPenRequest} moveData - 移入猪只请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const movePigsIntoPen = (id, moveData) => { | export const movePigsIntoPen = (id, moveData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/move-pigs-into-pen/${id}`, moveData); |     return http.post(`/api/v1/pig-batches/move-pigs-into-pen/${id}`, moveData); | ||||||
| @@ -286,7 +293,7 @@ export const movePigsIntoPen = (id, moveData) => { | |||||||
|  * 群内调栏 |  * 群内调栏 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {TransferPigsWithinBatchRequest} transferData - 群内调栏请求信息 |  * @param {TransferPigsWithinBatchRequest} transferData - 群内调栏请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const transferPigsWithinBatch = (id, transferData) => { | export const transferPigsWithinBatch = (id, transferData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/transfer-within-batch/${id}`, transferData); |     return http.post(`/api/v1/pig-batches/transfer-within-batch/${id}`, transferData); | ||||||
| @@ -296,7 +303,7 @@ export const transferPigsWithinBatch = (id, transferData) => { | |||||||
|  * 跨猪群调栏 |  * 跨猪群调栏 | ||||||
|  * @param {number} sourceBatchID - 源猪批次ID |  * @param {number} sourceBatchID - 源猪批次ID | ||||||
|  * @param {TransferPigsAcrossBatchesRequest} transferData - 跨群调栏请求信息 |  * @param {TransferPigsAcrossBatchesRequest} transferData - 跨群调栏请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const transferPigsAcrossBatches = (sourceBatchID, transferData) => { | export const transferPigsAcrossBatches = (sourceBatchID, transferData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/transfer-across-batches/${sourceBatchID}`, transferData); |     return http.post(`/api/v1/pig-batches/transfer-across-batches/${sourceBatchID}`, transferData); | ||||||
| @@ -306,7 +313,7 @@ export const transferPigsAcrossBatches = (sourceBatchID, transferData) => { | |||||||
|  * 将猪栏划拨到新批次 |  * 将猪栏划拨到新批次 | ||||||
|  * @param {number} fromBatchID - 源猪批次ID |  * @param {number} fromBatchID - 源猪批次ID | ||||||
|  * @param {ReclassifyPenToNewBatchRequest} reclassifyData - 划拨请求信息 |  * @param {ReclassifyPenToNewBatchRequest} reclassifyData - 划拨请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const reclassifyPenToNewBatch = (fromBatchID, reclassifyData) => { | export const reclassifyPenToNewBatch = (fromBatchID, reclassifyData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/reclassify-pen/${fromBatchID}`, reclassifyData); |     return http.post(`/api/v1/pig-batches/reclassify-pen/${fromBatchID}`, reclassifyData); | ||||||
| @@ -318,7 +325,7 @@ export const reclassifyPenToNewBatch = (fromBatchID, reclassifyData) => { | |||||||
|  * 记录新增病猪事件 |  * 记录新增病猪事件 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {RecordSickPigsRequest} sickData - 记录病猪请求信息 |  * @param {RecordSickPigsRequest} sickData - 记录病猪请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const recordSickPigsInBatch = (id, sickData) => { | export const recordSickPigsInBatch = (id, sickData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/record-sick-pigs/${id}`, sickData); |     return http.post(`/api/v1/pig-batches/record-sick-pigs/${id}`, sickData); | ||||||
| @@ -328,7 +335,7 @@ export const recordSickPigsInBatch = (id, sickData) => { | |||||||
|  * 记录病猪康复事件 |  * 记录病猪康复事件 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {RecordSickPigRecoveryRequest} recoveryData - 记录病猪康复请求信息 |  * @param {RecordSickPigRecoveryRequest} recoveryData - 记录病猪康复请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const recordSickPigRecoveryInBatch = (id, recoveryData) => { | export const recordSickPigRecoveryInBatch = (id, recoveryData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/record-sick-pig-recovery/${id}`, recoveryData); |     return http.post(`/api/v1/pig-batches/record-sick-pig-recovery/${id}`, recoveryData); | ||||||
| @@ -338,7 +345,7 @@ export const recordSickPigRecoveryInBatch = (id, recoveryData) => { | |||||||
|  * 记录病猪死亡事件 |  * 记录病猪死亡事件 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {RecordSickPigDeathRequest} deathData - 记录病猪死亡请求信息 |  * @param {RecordSickPigDeathRequest} deathData - 记录病猪死亡请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const recordSickPigDeathInBatch = (id, deathData) => { | export const recordSickPigDeathInBatch = (id, deathData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/record-sick-pig-death/${id}`, deathData); |     return http.post(`/api/v1/pig-batches/record-sick-pig-death/${id}`, deathData); | ||||||
| @@ -348,7 +355,7 @@ export const recordSickPigDeathInBatch = (id, deathData) => { | |||||||
|  * 记录病猪淘汰事件 |  * 记录病猪淘汰事件 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {RecordSickPigCullRequest} cullData - 记录病猪淘汰请求信息 |  * @param {RecordSickPigCullRequest} cullData - 记录病猪淘汰请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const recordSickPigCullInBatch = (id, cullData) => { | export const recordSickPigCullInBatch = (id, cullData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/record-sick-pig-cull/${id}`, cullData); |     return http.post(`/api/v1/pig-batches/record-sick-pig-cull/${id}`, cullData); | ||||||
| @@ -358,7 +365,7 @@ export const recordSickPigCullInBatch = (id, cullData) => { | |||||||
|  * 记录正常猪只死亡事件 |  * 记录正常猪只死亡事件 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {RecordDeathRequest} deathData - 记录正常猪只死亡请求信息 |  * @param {RecordDeathRequest} deathData - 记录正常猪只死亡请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const recordDeathInBatch = (id, deathData) => { | export const recordDeathInBatch = (id, deathData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/record-death/${id}`, deathData); |     return http.post(`/api/v1/pig-batches/record-death/${id}`, deathData); | ||||||
| @@ -368,7 +375,7 @@ export const recordDeathInBatch = (id, deathData) => { | |||||||
|  * 记录正常猪只淘汰事件 |  * 记录正常猪只淘汰事件 | ||||||
|  * @param {number} id - 猪批次ID |  * @param {number} id - 猪批次ID | ||||||
|  * @param {RecordCullRequest} cullData - 记录正常猪只淘汰请求信息 |  * @param {RecordCullRequest} cullData - 记录正常猪只淘汰请求信息 | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const recordCullInBatch = (id, cullData) => { | export const recordCullInBatch = (id, cullData) => { | ||||||
|     return http.post(`/api/v1/pig-batches/record-cull/${id}`, cullData); |     return http.post(`/api/v1/pig-batches/record-cull/${id}`, cullData); | ||||||
| @@ -391,3 +398,27 @@ export const getAllPens = () => { | |||||||
| export const getAllPigHouses = () => { | export const getAllPigHouses = () => { | ||||||
|     return http.get('/api/v1/pig-houses'); |     return http.get('/api/v1/pig-houses'); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const PigBatchApi = { | ||||||
|  |     getPigBatches, | ||||||
|  |     createPigBatch, | ||||||
|  |     getPigBatchById, | ||||||
|  |     updatePigBatch, | ||||||
|  |     deletePigBatch, | ||||||
|  |     assignPensToBatch, | ||||||
|  |     removePenFromBatch, | ||||||
|  |     buyPigsForBatch, | ||||||
|  |     sellPigsFromBatch, | ||||||
|  |     movePigsIntoPen, | ||||||
|  |     transferPigsWithinBatch, | ||||||
|  |     transferPigsAcrossBatches, | ||||||
|  |     reclassifyPenToNewBatch, | ||||||
|  |     recordSickPigsInBatch, | ||||||
|  |     recordSickPigRecoveryInBatch, | ||||||
|  |     recordSickPigDeathInBatch, | ||||||
|  |     recordSickPigCullInBatch, | ||||||
|  |     recordDeathInBatch, | ||||||
|  |     recordCullInBatch, | ||||||
|  |     getAllPens, | ||||||
|  |     getAllPigHouses, | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -1,5 +1,12 @@ | |||||||
| import http from '../utils/http'; | import http from '../utils/http'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} PigHouseResponse |  * @typedef {object} PigHouseResponse | ||||||
|  * @property {number} id |  * @property {number} id | ||||||
| @@ -58,8 +65,16 @@ export const updatePigHouse = (id, pigHouseData) => { | |||||||
| /** | /** | ||||||
|  * 根据ID删除一个猪舍 |  * 根据ID删除一个猪舍 | ||||||
|  * @param {number} id - 猪舍ID |  * @param {number} id - 猪舍ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| export const deletePigHouse = (id) => { | export const deletePigHouse = (id) => { | ||||||
|   return http.delete(`/api/v1/pig-houses/${id}`); |   return http.delete(`/api/v1/pig-houses/${id}`); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const PigHouseApi = { | ||||||
|  |   getPigHouses, | ||||||
|  |   createPigHouse, | ||||||
|  |   getPigHouseById, | ||||||
|  |   updatePigHouse, | ||||||
|  |   deletePigHouse, | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import http from '../utils/http'; | import http from '../utils/http'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {('计划分析'|'等待'|'下料')} TaskType |  * @typedef {('计划分析'|'等待'|'下料'|'全量采集')} TaskType | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -67,6 +67,10 @@ import http from '../utils/http'; | |||||||
|  * @typedef {('子计划'|'任务')} PlanContentType |  * @typedef {('子计划'|'任务')} PlanContentType | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {('自定义任务'|'系统任务')} PlanType | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @typedef {object} PlanResponse |  * @typedef {object} PlanResponse | ||||||
|  * @property {number} id |  * @property {number} id | ||||||
| @@ -78,17 +82,52 @@ import http from '../utils/http'; | |||||||
|  * @property {number} execute_count |  * @property {number} execute_count | ||||||
|  * @property {PlanStatus} status |  * @property {PlanStatus} status | ||||||
|  * @property {PlanContentType} content_type |  * @property {PlanContentType} content_type | ||||||
|  |  * @property {PlanType} plan_type | ||||||
|  * @property {Array<TaskResponse>} tasks |  * @property {Array<TaskResponse>} tasks | ||||||
|  * @property {Array<SubPlanResponse>} sub_plans |  * @property {Array<SubPlanResponse>} sub_plans | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} ListPlansResponse | ||||||
|  |  * @property {Array<PlanResponse>} plans | ||||||
|  |  * @property {number} total | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} PlanExecutionLogDTO | ||||||
|  |  * @property {string} created_at | ||||||
|  |  * @property {string} ended_at | ||||||
|  |  * @property {string} error | ||||||
|  |  * @property {number} id | ||||||
|  |  * @property {number} plan_id | ||||||
|  |  * @property {string} plan_name | ||||||
|  |  * @property {string} started_at | ||||||
|  |  * @property {string} status | ||||||
|  |  * @property {string} updated_at | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 获取所有计划的列表 |  * 获取所有计划的列表 | ||||||
|  * @returns {Promise<Array<PlanResponse>>} |  * @param {object} params - 查询参数 | ||||||
|  |  * @param {number} [params.page] - 页码 | ||||||
|  |  * @param {number} [params.page_size] - 每页大小 | ||||||
|  |  * @param {('所有任务'|'自定义任务'|'系统任务')} [params.plan_type] - 计划类型 | ||||||
|  |  * @returns {Promise<ListPlansResponse>} | ||||||
|  */ |  */ | ||||||
| const getPlans = () => { | const getPlans = (params) => { | ||||||
|   return http.get('/api/v1/plans'); |   const newParams = { | ||||||
|  |     page: params.page, | ||||||
|  |     page_size: params.page_size, | ||||||
|  |     plan_type: params.plan_type, | ||||||
|  |   }; | ||||||
|  |   return http.get('/api/v1/plans', { params: newParams }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -110,7 +149,7 @@ const getPlanById = (id) => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 根据计划ID更新计划的详细信息 |  * 根据计划ID更新计划的详细信息。系统计划不允许修改。 | ||||||
|  * @param {number} id - 计划ID |  * @param {number} id - 计划ID | ||||||
|  * @param {UpdatePlanRequest} planData - 更新后的计划信息 |  * @param {UpdatePlanRequest} planData - 更新后的计划信息 | ||||||
|  * @returns {Promise<PlanResponse>} |  * @returns {Promise<PlanResponse>} | ||||||
| @@ -120,27 +159,27 @@ const updatePlan = (id, planData) => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 根据计划ID删除计划(软删除) |  * 根据计划ID删除计划。(软删除)系统计划不允许删除。 | ||||||
|  * @param {number} id - 计划ID |  * @param {number} id - 计划ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| const deletePlan = (id) => { | const deletePlan = (id) => { | ||||||
|   return http.delete(`/api/v1/plans/${id}`); |   return http.delete(`/api/v1/plans/${id}`); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 根据计划ID启动一个计划的执行 |  * 根据计划ID启动一个计划的执行。系统计划不允许手动启动。 | ||||||
|  * @param {number} id - 计划ID |  * @param {number} id - 计划ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| const startPlan = (id) => { | const startPlan = (id) => { | ||||||
|   return http.post(`/api/v1/plans/${id}/start`); |   return http.post(`/api/v1/plans/${id}/start`); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 根据计划ID停止一个正在执行的计划 |  * 根据计划ID停止一个正在执行的计划。系统计划不能被停止。 | ||||||
|  * @param {number} id - 计划ID |  * @param {number} id - 计划ID | ||||||
|  * @returns {Promise<*>} |  * @returns {Promise<Response>} | ||||||
|  */ |  */ | ||||||
| const stopPlan = (id) => { | const stopPlan = (id) => { | ||||||
|   return http.post(`/api/v1/plans/${id}/stop`); |   return http.post(`/api/v1/plans/${id}/stop`); | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ import http from '../utils/http'; | |||||||
| /** | /** | ||||||
|  * @typedef {object} PaginationDTO |  * @typedef {object} PaginationDTO | ||||||
|  * @property {number} page |  * @property {number} page | ||||||
|  * @property {number} pageSize |  * @property {number} page_size | ||||||
|  * @property {number} total |  * @property {number} total | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @@ -64,13 +64,29 @@ import http from '../utils/http'; | |||||||
|  * @property {string} [end_time] |  * @property {string} [end_time] | ||||||
|  * @property {string} [order_by] |  * @property {string} [order_by] | ||||||
|  * @property {number} [page] |  * @property {number} [page] | ||||||
|  * @property {number} [pageSize] |  * @property {number} [page_size] | ||||||
|  * @property {string} [start_time] |  * @property {string} [start_time] | ||||||
|  * @property {string} [status] |  * @property {string} [status] | ||||||
|  * @property {number} [user_id] |  * @property {number} [user_id] | ||||||
|  * @property {string} [username] |  * @property {string} [username] | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {('邮件'|'企业微信'|'飞书'|'日志')} NotifierType | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} SendTestNotificationRequest | ||||||
|  |  * @property {NotifierType} type - Type 指定要测试的通知渠道 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {object} Response | ||||||
|  |  * @property {number} code - 业务状态码 | ||||||
|  |  * @property {object} [data] - 业务数据 | ||||||
|  |  * @property {string} [message] - 提示信息 | ||||||
|  |  */ | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 创建一个新用户 |  * 创建一个新用户 | ||||||
|  * @param {CreateUserRequest} userData - 用户信息 |  * @param {CreateUserRequest} userData - 用户信息 | ||||||
| @@ -90,17 +106,38 @@ const login = (credentials) => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 获取指定用户的操作历史 |  * 获取用户操作日志列表 | ||||||
|  * @param {number} id - 用户ID |  | ||||||
|  * @param {UserHistoryParams} params - 查询参数 |  * @param {UserHistoryParams} params - 查询参数 | ||||||
|  * @returns {Promise<ListUserActionLogResponse>} |  * @returns {Promise<ListUserActionLogResponse>} | ||||||
|  */ |  */ | ||||||
| const getUserHistory = (id, params) => { | const getUserActionLogs = (params) => { | ||||||
|   return http.get(`/api/v1/users/${id}/history`, { params }); |   const newParams = { | ||||||
|  |     action_type: params.action_type, | ||||||
|  |     end_time: params.end_time, | ||||||
|  |     order_by: params.order_by, | ||||||
|  |     page: params.page, | ||||||
|  |     page_size: params.page_size, | ||||||
|  |     start_time: params.start_time, | ||||||
|  |     status: params.status, | ||||||
|  |     user_id: params.user_id, | ||||||
|  |     username: params.username, | ||||||
|  |   }; | ||||||
|  |   return http.get('/api/v1/monitor/user-action-logs', { params: newParams }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 发送测试通知 | ||||||
|  |  * @param {number} id - 用户ID | ||||||
|  |  * @param {SendTestNotificationRequest} data - 请求体 | ||||||
|  |  * @returns {Promise<Response>} | ||||||
|  |  */ | ||||||
|  | const sendTestNotification = (id, data) => { | ||||||
|  |   return http.post(`/api/v1/users/${id}/notifications/test`, data); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const UserApi = { | export const UserApi = { | ||||||
|   createUser, |   createUser, | ||||||
|   login, |   login, | ||||||
|   getUserHistory, |   getUserActionLogs, | ||||||
|  |   sendTestNotification, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -167,7 +167,7 @@ const loadData = async () => { | |||||||
|   try { |   try { | ||||||
|     const params = { |     const params = { | ||||||
|       page: pagination.currentPage, |       page: pagination.currentPage, | ||||||
|       pageSize: pagination.pageSize, |       page_size: pagination.pageSize, // Changed from pageSize to page_size | ||||||
|       ...filters, |       ...filters, | ||||||
|       orderBy: sortOrder.prop, |       orderBy: sortOrder.prop, | ||||||
|       order: sortOrder.order === 'ascending' ? 'asc' : (sortOrder.order === 'descending' ? 'desc' : undefined), |       order: sortOrder.order === 'ascending' ? 'asc' : (sortOrder.order === 'descending' ? 'desc' : undefined), | ||||||
|   | |||||||
| @@ -29,11 +29,35 @@ | |||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|         <div class="batch-actions"> |         <div class="batch-actions"> | ||||||
|           <el-button size="small" type="primary" @click.stop="showAddPenDialog(batch)" :disabled="!batch.is_active"> |           <el-dropdown trigger="click" class="batch-dropdown"> | ||||||
|             增加猪栏 |             <el-button type="primary" size="small"> | ||||||
|  |               管理猪群<el-icon class="el-icon--right"><arrow-down /></el-icon> | ||||||
|             </el-button> |             </el-button> | ||||||
|           <el-button size="small" @click.stop="emitEditBatch(batch)">编辑</el-button> |             <template #dropdown> | ||||||
|           <el-button size="small" type="danger" @click.stop="emitDeleteBatch(batch)">删除</el-button> |               <el-dropdown-menu> | ||||||
|  |                 <el-dropdown-item @click="showAddPenDialog(batch)" :disabled="!batch.is_active">增加猪栏</el-dropdown-item> | ||||||
|  |                 <el-dropdown-item @click="emitEditBatch(batch)">编辑</el-dropdown-item> | ||||||
|  |                 <el-dropdown-item @click="emitDeleteBatch(batch)" divided>删除</el-dropdown-item> | ||||||
|  |               </el-dropdown-menu> | ||||||
|  |             </template> | ||||||
|  |           </el-dropdown> | ||||||
|  |           <el-dropdown trigger="click" class="batch-dropdown"> | ||||||
|  |             <el-button type="success" size="small"> | ||||||
|  |               调栏<el-icon class="el-icon--right"><arrow-down /></el-icon> | ||||||
|  |             </el-button> | ||||||
|  |             <template #dropdown> | ||||||
|  |               <el-dropdown-menu> | ||||||
|  |                 <el-dropdown-item  | ||||||
|  |                   @click="emitTransferPigs(batch)" | ||||||
|  |                   :disabled="!batch.is_active || !batch.pens || batch.pens.length < 2" | ||||||
|  |                 >群内调栏</el-dropdown-item> | ||||||
|  |                 <el-dropdown-item  | ||||||
|  |                   @click="emitTransferPigsAcrossBatches(batch)" | ||||||
|  |                   :disabled="!batch.is_active || !batch.pens || batch.pens.length === 0" | ||||||
|  |                 >跨群调栏</el-dropdown-item> | ||||||
|  |               </el-dropdown-menu> | ||||||
|  |             </template> | ||||||
|  |           </el-dropdown> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <div v-if="batch.isExpanded" class="batch-content"> |       <div v-if="batch.isExpanded" class="batch-content"> | ||||||
| @@ -43,6 +67,7 @@ | |||||||
|               :key="pen.id" |               :key="pen.id" | ||||||
|               :pen="pen" |               :pen="pen" | ||||||
|               :isBatchActive="batch.is_active" |               :isBatchActive="batch.is_active" | ||||||
|  |               :batchUnassignedPigCount="batch.unassigned_pig_count" | ||||||
|               @allocate-pigs="showAllocatePigsDialog($event, batch)" |               @allocate-pigs="showAllocatePigsDialog($event, batch)" | ||||||
|               @remove="emitRemovePen" |               @remove="emitRemovePen" | ||||||
|           /> |           /> | ||||||
| @@ -73,8 +98,7 @@ | |||||||
|  |  | ||||||
|     <!-- 分配猪只对话框 --> |     <!-- 分配猪只对话框 --> | ||||||
|     <AllocatePigsDialog |     <AllocatePigsDialog | ||||||
|         v-if="allocatePigsDialogVisible" |         v-model:visible="allocatePigsDialogVisible" | ||||||
|         :visible.sync="allocatePigsDialogVisible" |  | ||||||
|         :unassigned-pig-count="currentBatch ? currentBatch.unassigned_pig_count : 0" |         :unassigned-pig-count="currentBatch ? currentBatch.unassigned_pig_count : 0" | ||||||
|         :pen-id="selectedPenForAllocation ? selectedPenForAllocation.id : 0" |         :pen-id="selectedPenForAllocation ? selectedPenForAllocation.id : 0" | ||||||
|         @confirm="handleAllocatePigs" |         @confirm="handleAllocatePigs" | ||||||
| @@ -87,12 +111,14 @@ import PigBatchPenCard from './PigBatchPenCard.vue'; | |||||||
| import AllocatePigsDialog from './AllocatePigsDialog.vue'; | import AllocatePigsDialog from './AllocatePigsDialog.vue'; | ||||||
| import {getAllPens, getAllPigHouses, movePigsIntoPen} from '../api/pigBatch'; | import {getAllPens, getAllPigHouses, movePigsIntoPen} from '../api/pigBatch'; | ||||||
| import {formatRFC3339} from '../utils/format'; // 导入格式化函数 | import {formatRFC3339} from '../utils/format'; // 导入格式化函数 | ||||||
|  | import { ArrowDown } from '@element-plus/icons-vue'; // 导入 ArrowDown 图标 | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'PigBatchList', |   name: 'PigBatchList', | ||||||
|   components: { |   components: { | ||||||
|     PigBatchPenCard, |     PigBatchPenCard, | ||||||
|     AllocatePigsDialog |     AllocatePigsDialog, | ||||||
|  |     ArrowDown // 注册 ArrowDown 图标 | ||||||
|   }, |   }, | ||||||
|   props: { |   props: { | ||||||
|     pigBatches: { |     pigBatches: { | ||||||
| @@ -100,7 +126,7 @@ export default { | |||||||
|       required: true |       required: true | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   emits: ['edit-batch', 'delete-batch', 'add-pen', 'remove-pen', 'assign-pen-to-batch', 'reload-data'], |   emits: ['edit-batch', 'delete-batch', 'add-pen', 'remove-pen', 'assign-pen-to-batch', 'reload-data', 'transfer-pigs', 'transfer-pigs-across-batches'], | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       addPenDialogVisible: false, |       addPenDialogVisible: false, | ||||||
| @@ -181,6 +207,12 @@ export default { | |||||||
|     emitDeleteBatch(batch) { |     emitDeleteBatch(batch) { | ||||||
|       this.$emit('delete-batch', batch); |       this.$emit('delete-batch', batch); | ||||||
|     }, |     }, | ||||||
|  |     emitTransferPigs(batch) { | ||||||
|  |       this.$emit('transfer-pigs', batch); | ||||||
|  |     }, | ||||||
|  |     emitTransferPigsAcrossBatches(batch) { | ||||||
|  |       this.$emit('transfer-pigs-across-batches', batch); | ||||||
|  |     }, | ||||||
|     // 猪栏操作 |     // 猪栏操作 | ||||||
|     emitRemovePen(pen) { |     emitRemovePen(pen) { | ||||||
|       this.$emit('remove-pen', pen); |       this.$emit('remove-pen', pen); | ||||||
| @@ -241,6 +273,10 @@ export default { | |||||||
|   gap: 10px; |   gap: 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .batch-dropdown { | ||||||
|  |   margin-left: 10px; /* 为下拉菜单添加左边距 */ | ||||||
|  | } | ||||||
|  |  | ||||||
| .batch-content { | .batch-content { | ||||||
|   padding: 16px; |   padding: 16px; | ||||||
|   border-top: 1px solid #eee; |   border-top: 1px solid #eee; | ||||||
|   | |||||||
| @@ -7,10 +7,10 @@ | |||||||
|       <div class="info-item">猪舍: {{ pen.house_name || '未知' }}</div> |       <div class="info-item">猪舍: {{ pen.house_name || '未知' }}</div> | ||||||
|       <div class="info-item border-left">容量: {{ pen.capacity }}</div> |       <div class="info-item border-left">容量: {{ pen.capacity }}</div> | ||||||
|       <div class="info-item">批次: {{ pen.batch_number || '未分配' }}</div> |       <div class="info-item">批次: {{ pen.batch_number || '未分配' }}</div> | ||||||
|       <div class="info-item border-left">存栏: {{ pen.current_pig_count || 0 }}</div> |       <div class="info-item border-left">存栏: <span :class="{'over-capacity': pen.current_pig_count > pen.capacity}">{{ pen.current_pig_count || 0 }}</span></div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="actions-section"> |     <div class="actions-section"> | ||||||
|       <el-button size="small" @click="emitAllocatePigs" :disabled="!isBatchActive">分配猪只</el-button> |       <el-button size="small" @click="emitAllocatePigs" :disabled="!isBatchActive || batchUnassignedPigCount <= 0">分配猪只</el-button> | ||||||
|       <el-button size="small" type="danger" @click="emitRemove" :disabled="!isBatchActive || pen.current_pig_count > 0">移除</el-button> |       <el-button size="small" type="danger" @click="emitRemove" :disabled="!isBatchActive || pen.current_pig_count > 0">移除</el-button> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| @@ -29,6 +29,10 @@ export default { | |||||||
|     isBatchActive: { |     isBatchActive: { | ||||||
|       type: Boolean, |       type: Boolean, | ||||||
|       default: true // 默认活跃,以防万一没有传递 |       default: true // 默认活跃,以防万一没有传递 | ||||||
|  |     }, | ||||||
|  |     batchUnassignedPigCount: { | ||||||
|  |       type: Number, | ||||||
|  |       default: 0 | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   emits: ['remove', 'allocate-pigs'], |   emits: ['remove', 'allocate-pigs'], | ||||||
| @@ -124,4 +128,8 @@ export default { | |||||||
|   width: 100%; |   width: 100%; | ||||||
|   margin: 0; |   margin: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .over-capacity { | ||||||
|  |   color: red; | ||||||
|  | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|       <div class="info-item">猪舍: {{ pen.house_name || '未知' }}</div> |       <div class="info-item">猪舍: {{ pen.house_name || '未知' }}</div> | ||||||
|       <div class="info-item border-left">容量: {{ pen.capacity }}</div> |       <div class="info-item border-left">容量: {{ pen.capacity }}</div> | ||||||
|       <div class="info-item">批次: {{ pen.batch_number || '未分配' }}</div> |       <div class="info-item">批次: {{ pen.batch_number || '未分配' }}</div> | ||||||
|       <div class="info-item border-left">存栏: {{ pen.current_pig_count || 0 }}</div> |       <div class="info-item border-left">存栏: <span :class="{'over-capacity': pen.current_pig_count > pen.capacity}">{{ pen.current_pig_count || 0 }}</span></div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="actions-section"> |     <div class="actions-section"> | ||||||
|       <el-button size="small" @click="emitEdit">编辑</el-button> |       <el-button size="small" @click="emitEdit">编辑</el-button> | ||||||
| @@ -120,4 +120,8 @@ export default { | |||||||
|   width: 100%; |   width: 100%; | ||||||
|   margin: 0; |   margin: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .over-capacity { | ||||||
|  |   color: red; | ||||||
|  | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -20,9 +20,15 @@ | |||||||
|             <span>{{ plan.name }} - 内容</span> |             <span>{{ plan.name }} - 内容</span> | ||||||
|             <div> |             <div> | ||||||
|               <template v-if="!isSubPlan"> |               <template v-if="!isSubPlan"> | ||||||
|                 <el-button class="button" type="primary" @click="savePlanContent" v-if="isEditingContent">保存</el-button> |                 <el-button class="button" type="primary" @click="savePlanContent" v-if="isEditingContent" | ||||||
|                 <el-button class="button" type="danger" @click="cancelEdit" v-if="isEditingContent">取消</el-button> |                            :disabled="plan.plan_type === '系统任务'">保存 | ||||||
|                 <el-button class="button" @click="enterEditMode" v-else>编辑内容</el-button> |                 </el-button> | ||||||
|  |                 <el-button class="button" type="danger" @click="cancelEdit" v-if="isEditingContent" | ||||||
|  |                            :disabled="plan.plan_type === '系统任务'">取消 | ||||||
|  |                 </el-button> | ||||||
|  |                 <el-button class="button" @click="enterEditMode" v-else :disabled="plan.plan_type === '系统任务'"> | ||||||
|  |                   编辑内容 | ||||||
|  |                 </el-button> | ||||||
|               </template> |               </template> | ||||||
|  |  | ||||||
|               <!-- Dynamic Add Buttons --> |               <!-- Dynamic Add Buttons --> | ||||||
| @@ -32,13 +38,17 @@ | |||||||
|                     type="primary" |                     type="primary" | ||||||
|                     size="small" |                     size="small" | ||||||
|                     @click="showAddSubPlanDialog" |                     @click="showAddSubPlanDialog" | ||||||
|                 >增加子计划</el-button> |                     :disabled="plan.plan_type === '系统任务'" | ||||||
|  |                 >增加子计划 | ||||||
|  |                 </el-button> | ||||||
|                 <el-button |                 <el-button | ||||||
|                     v-if="plan.content_type === 'tasks' || !plan.content_type" |                     v-if="plan.content_type === 'tasks' || !plan.content_type" | ||||||
|                     type="primary" |                     type="primary" | ||||||
|                     size="small" |                     size="small" | ||||||
|                     @click="showTaskEditorDialog()" |                     @click="showTaskEditorDialog()" | ||||||
|                 >增加子任务</el-button> |                     :disabled="plan.plan_type === '系统任务'" | ||||||
|  |                 >增加子任务 | ||||||
|  |                 </el-button> | ||||||
|               </template> |               </template> | ||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
| @@ -61,8 +71,12 @@ | |||||||
|                   延时: {{ task.parameters.delay_duration }} 秒 |                   延时: {{ task.parameters.delay_duration }} 秒 | ||||||
|                 </p> |                 </p> | ||||||
|                 <el-button-group v-if="isEditingContent"> |                 <el-button-group v-if="isEditingContent"> | ||||||
|                   <el-button type="primary" size="small" @click="editTask(task)">编辑</el-button> |                   <el-button type="primary" size="small" @click="editTask(task)" | ||||||
|                   <el-button type="danger" size="small" @click="deleteTask(task)">删除</el-button> |                              :disabled="plan.plan_type === '系统任务'">编辑 | ||||||
|  |                   </el-button> | ||||||
|  |                   <el-button type="danger" size="small" @click="deleteTask(task)" | ||||||
|  |                              :disabled="plan.plan_type === '系统任务'">删除 | ||||||
|  |                   </el-button> | ||||||
|                 </el-button-group> |                 </el-button-group> | ||||||
|               </el-card> |               </el-card> | ||||||
|             </el-timeline-item> |             </el-timeline-item> | ||||||
| @@ -74,13 +88,16 @@ | |||||||
|         <div v-else-if="plan.content_type === 'sub_plans'"> |         <div v-else-if="plan.content_type === 'sub_plans'"> | ||||||
|           <h4>子计划列表</h4> |           <h4>子计划列表</h4> | ||||||
|           <div v-if="plan.sub_plans.length > 0"> |           <div v-if="plan.sub_plans.length > 0"> | ||||||
|             <div v-for="(subPlan, index) in plan.sub_plans" :key="subPlan.id || 'new-subplan-' + index" class="sub-plan-wrapper"> |             <div v-for="(subPlan, index) in plan.sub_plans" :key="subPlan.id || 'new-subplan-' + index" | ||||||
|  |                  class="sub-plan-wrapper"> | ||||||
|               <el-card> |               <el-card> | ||||||
|                 <div class="sub-plan-card-content"> |                 <div class="sub-plan-card-content"> | ||||||
|                   <!-- Pass child_plan_id to recursive PlanDetail --> |                   <!-- Pass child_plan_id to recursive PlanDetail --> | ||||||
|                   <plan-detail :plan-id="subPlan.child_plan_id" :is-sub-plan="true"/> |                   <plan-detail :plan-id="subPlan.child_plan_id" :is-sub-plan="true"/> | ||||||
|                   <el-button-group v-if="isEditingContent" class="sub-plan-actions"> |                   <el-button-group v-if="isEditingContent" class="sub-plan-actions"> | ||||||
|                     <el-button type="danger" size="small" @click="deleteSubPlan(subPlan)">删除</el-button> |                     <el-button type="danger" size="small" @click="deleteSubPlan(subPlan)" | ||||||
|  |                                :disabled="plan.plan_type === '系统任务'">删除 | ||||||
|  |                     </el-button> | ||||||
|                   </el-button-group> |                   </el-button-group> | ||||||
|                 </div> |                 </div> | ||||||
|               </el-card> |               </el-card> | ||||||
| @@ -135,16 +152,19 @@ | |||||||
|     > |     > | ||||||
|       <el-form :model="currentTaskForm" ref="taskFormRef" :rules="taskFormRules" label-width="100px"> |       <el-form :model="currentTaskForm" ref="taskFormRef" :rules="taskFormRules" label-width="100px"> | ||||||
|         <el-form-item label="任务类型" prop="type"> |         <el-form-item label="任务类型" prop="type"> | ||||||
|           <el-select v-model="currentTaskForm.type" placeholder="请选择任务类型" style="width: 100%;" :disabled="isEditingTask"> |           <el-select v-model="currentTaskForm.type" placeholder="请选择任务类型" style="width: 100%;" | ||||||
|  |                      :disabled="isEditingTask || plan.plan_type === '系统任务'"> | ||||||
|             <!-- Only Delay Task for now --> |             <!-- Only Delay Task for now --> | ||||||
|             <el-option label="延时任务" value="delay_task"></el-option> |             <el-option label="延时任务" value="delay_task"></el-option> | ||||||
|           </el-select> |           </el-select> | ||||||
|         </el-form-item> |         </el-form-item> | ||||||
|         <el-form-item label="任务名称" prop="name"> |         <el-form-item label="任务名称" prop="name"> | ||||||
|           <el-input v-model="currentTaskForm.name" placeholder="请输入任务名称"></el-input> |           <el-input v-model="currentTaskForm.name" placeholder="请输入任务名称" | ||||||
|  |                     :disabled="plan.plan_type === '系统任务'"></el-input> | ||||||
|         </el-form-item> |         </el-form-item> | ||||||
|         <el-form-item label="任务描述" prop="description"> |         <el-form-item label="任务描述" prop="description"> | ||||||
|           <el-input type="textarea" v-model="currentTaskForm.description" placeholder="请输入任务描述"></el-input> |           <el-input type="textarea" v-model="currentTaskForm.description" placeholder="请输入任务描述" | ||||||
|  |                     :disabled="plan.plan_type === '系统任务'"></el-input> | ||||||
|         </el-form-item> |         </el-form-item> | ||||||
|         <!-- Dynamic task component for specific parameters --> |         <!-- Dynamic task component for specific parameters --> | ||||||
|         <template v-if="currentTaskForm.type === 'delay_task'"> |         <template v-if="currentTaskForm.type === 'delay_task'"> | ||||||
| @@ -153,6 +173,7 @@ | |||||||
|               @update:parameters="val => currentTaskForm.parameters = val" |               @update:parameters="val => currentTaskForm.parameters = val" | ||||||
|               prop-path="parameters.delay_duration" |               prop-path="parameters.delay_duration" | ||||||
|               :is-editing="true" |               :is-editing="true" | ||||||
|  |               :disabled="plan.plan_type === '系统任务'" | ||||||
|           /> |           /> | ||||||
|         </template> |         </template> | ||||||
|         <!-- More task types can be rendered here --> |         <!-- More task types can be rendered here --> | ||||||
| @@ -160,7 +181,7 @@ | |||||||
|       <template #footer> |       <template #footer> | ||||||
|         <span class="dialog-footer"> |         <span class="dialog-footer"> | ||||||
|           <el-button @click="taskEditorDialogVisible = false">取消</el-button> |           <el-button @click="taskEditorDialogVisible = false">取消</el-button> | ||||||
|           <el-button type="primary" @click="confirmTaskEdit">确定</el-button> |           <el-button type="primary" @click="confirmTaskEdit" :disabled="plan.plan_type === '系统任务'">确定</el-button> | ||||||
|         </span> |         </span> | ||||||
|       </template> |       </template> | ||||||
|     </el-dialog> |     </el-dialog> | ||||||
| @@ -355,7 +376,7 @@ export default { | |||||||
|     }, |     }, | ||||||
|     async fetchAvailablePlans() { |     async fetchAvailablePlans() { | ||||||
|       try { |       try { | ||||||
|         const response = await apiClient.plans.getPlans(); // 更正此处 |         const response = await apiClient.plans.getPlans({plan_type: '自定义任务', page: 1, page_size: 1000}); | ||||||
|         this.availablePlans = response.data.plans.filter(p => |         this.availablePlans = response.data.plans.filter(p => | ||||||
|             p.id !== this.planId |             p.id !== this.planId | ||||||
|         ); |         ); | ||||||
| @@ -540,35 +561,43 @@ export default { | |||||||
| .plan-detail { | .plan-detail { | ||||||
|   margin-top: 10px; |   margin-top: 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .loading, .error { | .loading, .error { | ||||||
|   padding: 20px; |   padding: 20px; | ||||||
|   text-align: center; |   text-align: center; | ||||||
| } | } | ||||||
|  |  | ||||||
| .retry-btn { | .retry-btn { | ||||||
|   margin-top: 15px; |   margin-top: 15px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .sub-plan-wrapper { | .sub-plan-wrapper { | ||||||
|   margin-bottom: 10px; |   margin-bottom: 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .sub-plan-container { | .sub-plan-container { | ||||||
|   margin-left: 20px; |   margin-left: 20px; | ||||||
|   margin-top: 10px; |   margin-top: 10px; | ||||||
|   border-left: 2px solid #ebeef5; |   border-left: 2px solid #ebeef5; | ||||||
|   padding-left: 10px; |   padding-left: 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .sub-plan-card-content { | .sub-plan-card-content { | ||||||
|   display: flex; |   display: flex; | ||||||
|   flex-direction: column; |   flex-direction: column; | ||||||
|   gap: 10px; |   gap: 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .sub-plan-actions { | .sub-plan-actions { | ||||||
|   align-self: flex-end; |   align-self: flex-end; | ||||||
| } | } | ||||||
|  |  | ||||||
| .card-header { | .card-header { | ||||||
|   display: flex; |   display: flex; | ||||||
|   justify-content: space-between; |   justify-content: space-between; | ||||||
|   align-items: center; |   align-items: center; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* 调整子计划卡片内部的header,避免重复样式 */ | /* 调整子计划卡片内部的header,避免重复样式 */ | ||||||
| .sub-plan-container .card-header { | .sub-plan-container .card-header { | ||||||
|   padding: 0; |   padding: 0; | ||||||
|   | |||||||
| @@ -145,7 +145,7 @@ export default { | |||||||
|     // 处理执行方式变更 |     // 处理执行方式变更 | ||||||
|     const handleExecutionTypeChange = (value) => { |     const handleExecutionTypeChange = (value) => { | ||||||
|       // 如果切换为手动执行,清空执行次数和cron表达式 |       // 如果切换为手动执行,清空执行次数和cron表达式 | ||||||
|       if (value === 'manual') { |       if (value === '手动') { | ||||||
|         formData.execute_num = 0; |         formData.execute_num = 0; | ||||||
|         formData.cron_expression = ''; |         formData.cron_expression = ''; | ||||||
|       } else { |       } else { | ||||||
| @@ -178,7 +178,7 @@ export default { | |||||||
|             } |             } | ||||||
|              |              | ||||||
|             // 如果是手动执行,清除执行次数和cron表达式 |             // 如果是手动执行,清除执行次数和cron表达式 | ||||||
|             if (formData.execution_type === 'manual') { |             if (formData.execution_type === '手动') { | ||||||
|               submitData.execute_num = 0; |               submitData.execute_num = 0; | ||||||
|               submitData.cron_expression = ''; |               submitData.cron_expression = ''; | ||||||
|             } |             } | ||||||
|   | |||||||
							
								
								
									
										204
									
								
								src/components/TransferPigsAcrossBatchesModal.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								src/components/TransferPigsAcrossBatchesModal.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | |||||||
|  | <template> | ||||||
|  |   <el-dialog | ||||||
|  |     title="跨群调栏" | ||||||
|  |     :model-value="visible" | ||||||
|  |     @update:model-value="$emit('update:visible', $event)" | ||||||
|  |     width="40%" | ||||||
|  |     @close="resetForm" | ||||||
|  |   > | ||||||
|  |     <el-form ref="form" :model="form" :rules="rules" label-width="120px"> | ||||||
|  |       <el-form-item label="源猪群批次"> | ||||||
|  |         <span>{{ batch.batch_number }}</span> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="源猪栏" prop="fromPenID"> | ||||||
|  |         <el-select v-model="form.fromPenID" placeholder="请选择源猪栏" style="width: 100%;"> | ||||||
|  |           <el-option | ||||||
|  |             v-for="pen in sourcePens" | ||||||
|  |             :key="pen.id" | ||||||
|  |             :label="`${pen.pen_number} (存栏: ${pen.current_pig_count})`" | ||||||
|  |             :value="pen.id" | ||||||
|  |           ></el-option> | ||||||
|  |         </el-select> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="目标猪群批次" prop="destBatchID"> | ||||||
|  |         <el-select v-model="form.destBatchID" placeholder="请选择目标猪群" style="width: 100%;" @change="onDestBatchChange"> | ||||||
|  |           <el-option | ||||||
|  |             v-for="b in availableBatches" | ||||||
|  |             :key="b.id" | ||||||
|  |             :label="b.batch_number" | ||||||
|  |             :value="b.id" | ||||||
|  |           ></el-option> | ||||||
|  |         </el-select> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="目标猪栏" prop="toPenID"> | ||||||
|  |         <el-select v-model="form.toPenID" placeholder="请选择目标猪栏" style="width: 100%;"> | ||||||
|  |           <el-option | ||||||
|  |             v-for="pen in destinationPens" | ||||||
|  |             :key="pen.id" | ||||||
|  |             :label="`${pen.pen_number} (容量: ${pen.capacity})`" | ||||||
|  |             :value="pen.id" | ||||||
|  |           ></el-option> | ||||||
|  |         </el-select> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="调栏数量" prop="quantity"> | ||||||
|  |         <el-input-number v-model="form.quantity" :min="1" :max="maxTransferQuantity" /> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="备注" prop="remarks"> | ||||||
|  |         <el-input v-model="form.remarks" type="textarea" :rows="2" placeholder="请输入备注" /> | ||||||
|  |       </el-form-item> | ||||||
|  |     </el-form> | ||||||
|  |     <template #footer> | ||||||
|  |       <span class="dialog-footer"> | ||||||
|  |         <el-button @click="$emit('update:visible', false)">取 消</el-button> | ||||||
|  |         <el-button type="primary" @click="handleConfirm">确 定</el-button> | ||||||
|  |       </span> | ||||||
|  |     </template> | ||||||
|  |   </el-dialog> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import { getPigBatches, transferPigsAcrossBatches } from '@/api/pigBatch'; | ||||||
|  | import { getPens } from '@/api/pen'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: 'TransferPigsAcrossBatchesModal', | ||||||
|  |   props: { | ||||||
|  |     visible: { | ||||||
|  |       type: Boolean, | ||||||
|  |       required: true | ||||||
|  |     }, | ||||||
|  |     batch: { | ||||||
|  |       type: Object, | ||||||
|  |       required: true // 源猪群批次信息 | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   emits: ['update:visible', 'success'], | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       form: { | ||||||
|  |         fromPenID: null, | ||||||
|  |         destBatchID: null, | ||||||
|  |         toPenID: null, | ||||||
|  |         quantity: 1, | ||||||
|  |         remarks: '' | ||||||
|  |       }, | ||||||
|  |       rules: { | ||||||
|  |         fromPenID: [{ required: true, message: '请选择源猪栏', trigger: 'change' }], | ||||||
|  |         destBatchID: [{ required: true, message: '请选择目标猪群批次', trigger: 'change' }], | ||||||
|  |         toPenID: [{ required: true, message: '请选择目标猪栏', trigger: 'change' }], | ||||||
|  |         quantity: [ | ||||||
|  |           { required: true, message: '请输入调栏数量', trigger: 'blur' }, | ||||||
|  |           { type: 'integer', message: '请输入整数', trigger: 'blur' }, | ||||||
|  |           { validator: this.validateQuantity, trigger: 'blur' } | ||||||
|  |         ] | ||||||
|  |       }, | ||||||
|  |       sourcePens: [], // 源猪群的猪栏列表 | ||||||
|  |       availableBatches: [], // 可用的目标猪群列表 | ||||||
|  |       destinationPens: [], // 目标猪群的猪栏列表 | ||||||
|  |       maxTransferQuantity: 1 // 最大可调栏数量 | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  |   watch: { | ||||||
|  |     visible(newVal) { | ||||||
|  |       if (newVal) { | ||||||
|  |         this.initData(); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     'form.fromPenID': function(newVal) { | ||||||
|  |       if (newVal) { | ||||||
|  |         const selectedPen = this.sourcePens.find(pen => pen.id === newVal); | ||||||
|  |         this.maxTransferQuantity = selectedPen ? selectedPen.current_pig_count : 1; | ||||||
|  |         // 如果当前数量大于最大值,重置数量 | ||||||
|  |         if (this.form.quantity > this.maxTransferQuantity) { | ||||||
|  |           this.form.quantity = this.maxTransferQuantity; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     async initData() { | ||||||
|  |       this.resetForm(); | ||||||
|  |       this.sourcePens = this.batch.pens.filter(pen => pen.current_pig_count > 0); // 过滤掉没有猪的猪栏 | ||||||
|  |       await this.fetchAvailableBatchesAndPens(); | ||||||
|  |     }, | ||||||
|  |     async fetchAvailableBatchesAndPens() { | ||||||
|  |       try { | ||||||
|  |         const [batchesResponse, pensResponse] = await Promise.all([ | ||||||
|  |           getPigBatches({ is_active: true }), // 获取所有活跃猪群 | ||||||
|  |           getPens() // 获取所有猪栏 | ||||||
|  |         ]); | ||||||
|  |  | ||||||
|  |         const allBatches = batchesResponse.data || []; | ||||||
|  |         const allPens = pensResponse.data || []; | ||||||
|  |  | ||||||
|  |         // 过滤掉源猪群自身,以及非活跃的猪群 | ||||||
|  |         this.availableBatches = allBatches.filter(b => b.id !== this.batch.id && b.is_active); | ||||||
|  |  | ||||||
|  |         // 将所有猪栏按批次ID分组,方便后续查找 | ||||||
|  |         const pensByBatch = allPens.reduce((acc, pen) => { | ||||||
|  |           if (pen.pig_batch_id) { | ||||||
|  |             if (!acc[pen.pig_batch_id]) { | ||||||
|  |               acc[pen.pig_batch_id] = []; | ||||||
|  |             } | ||||||
|  |             acc[pen.pig_batch_id].push(pen); | ||||||
|  |           } | ||||||
|  |           return acc; | ||||||
|  |         }, {}); | ||||||
|  |         this.pensByBatch = pensByBatch; // 存储起来,以便 onDestBatchChange 使用 | ||||||
|  |  | ||||||
|  |       } catch (error) { | ||||||
|  |         console.error("Error fetching batches or pens:", error); | ||||||
|  |         this.$message.error("获取猪群或猪栏信息失败"); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     onDestBatchChange(batchId) { | ||||||
|  |       this.form.toPenID = null; // 重置目标猪栏选择 | ||||||
|  |       // 允许选择目标批次下的所有猪栏,包括已满的 | ||||||
|  |       this.destinationPens = (this.pensByBatch[batchId] || []); | ||||||
|  |     }, | ||||||
|  |     validateQuantity(rule, value, callback) { | ||||||
|  |       if (value > this.maxTransferQuantity) { | ||||||
|  |         callback(new Error(`调栏数量不能超过源猪栏存栏数量 (${this.maxTransferQuantity})`)); | ||||||
|  |       } else { | ||||||
|  |         callback(); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     handleConfirm() { | ||||||
|  |       this.$refs.form.validate(async valid => { | ||||||
|  |         if (valid) { | ||||||
|  |           try { | ||||||
|  |             await transferPigsAcrossBatches(this.batch.id, { | ||||||
|  |               fromPenID: this.form.fromPenID, | ||||||
|  |               destBatchID: this.form.destBatchID, | ||||||
|  |               toPenID: this.form.toPenID, | ||||||
|  |               quantity: this.form.quantity, | ||||||
|  |               remarks: this.form.remarks | ||||||
|  |             }); | ||||||
|  |             this.$message.success('跨群调栏成功'); | ||||||
|  |             this.$emit('success'); | ||||||
|  |             this.$emit('update:visible', false); | ||||||
|  |           } catch (error) { | ||||||
|  |             console.error('Error transferring pigs across batches:', error); | ||||||
|  |             this.$message.error('跨群调栏失败: ' + (error.response?.data?.message || error.message || '未知错误')); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |     resetForm() { | ||||||
|  |       this.$refs.form?.resetFields(); | ||||||
|  |       this.form.fromPenID = null; | ||||||
|  |       this.form.destBatchID = null; | ||||||
|  |       this.form.toPenID = null; | ||||||
|  |       this.form.quantity = 1; | ||||||
|  |       this.form.remarks = ''; | ||||||
|  |       this.sourcePens = []; | ||||||
|  |       this.availableBatches = []; | ||||||
|  |       this.destinationPens = []; | ||||||
|  |       this.maxTransferQuantity = 1; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | </style> | ||||||
							
								
								
									
										161
									
								
								src/components/TransferPigsModal.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/components/TransferPigsModal.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | |||||||
|  | <template> | ||||||
|  |   <el-dialog | ||||||
|  |     title="群内调栏" | ||||||
|  |     :model-value="visible" | ||||||
|  |     @update:model-value="$emit('update:visible', $event)" | ||||||
|  |     width="500px" | ||||||
|  |     :before-close="handleClose" | ||||||
|  |   > | ||||||
|  |     <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> | ||||||
|  |       <el-form-item label="调出猪栏" prop="fromPenID"> | ||||||
|  |         <el-select v-model="form.fromPenID" placeholder="请选择调出猪栏" style="width: 100%;" @change="handleFromPenChange"> | ||||||
|  |           <el-option | ||||||
|  |             v-for="pen in sourcePens" | ||||||
|  |             :key="pen.id" | ||||||
|  |             :label="`${pen.pen_number} (存栏: ${pen.current_pig_count})`" | ||||||
|  |             :value="pen.id" | ||||||
|  |             :disabled="pen.current_pig_count === 0" | ||||||
|  |           /> | ||||||
|  |         </el-select> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="调入猪栏" prop="toPenID"> | ||||||
|  |         <el-select v-model="form.toPenID" placeholder="请选择调入猪栏" style="width: 100%;" :disabled="!form.fromPenID"> | ||||||
|  |           <el-option | ||||||
|  |             v-for="pen in destinationPens" | ||||||
|  |             :key="pen.id" | ||||||
|  |             :label="`${pen.pen_number} (存栏: ${pen.current_pig_count})`" | ||||||
|  |             :value="pen.id" | ||||||
|  |           /> | ||||||
|  |         </el-select> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="调栏数量" prop="quantity"> | ||||||
|  |         <el-input-number | ||||||
|  |           v-model="form.quantity" | ||||||
|  |           :min="1" | ||||||
|  |           :max="maxQuantity" | ||||||
|  |           :disabled="!form.fromPenID" | ||||||
|  |           placeholder="请输入数量" | ||||||
|  |           style="width: 100%;" | ||||||
|  |         /> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="备注" prop="remarks"> | ||||||
|  |         <el-input v-model="form.remarks" type="textarea" placeholder="请输入备注" /> | ||||||
|  |       </el-form-item> | ||||||
|  |     </el-form> | ||||||
|  |     <template #footer> | ||||||
|  |       <span class="dialog-footer"> | ||||||
|  |         <el-button @click="handleClose">取 消</el-button> | ||||||
|  |         <el-button type="primary" @click="handleSubmit" :loading="loading">确 定</el-button> | ||||||
|  |       </span> | ||||||
|  |     </template> | ||||||
|  |   </el-dialog> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import { transferPigsWithinBatch } from '@/api/pigBatch.js'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: 'TransferPigsModal', | ||||||
|  |   props: { | ||||||
|  |     visible: { | ||||||
|  |       type: Boolean, | ||||||
|  |       default: false, | ||||||
|  |     }, | ||||||
|  |     batch: { | ||||||
|  |       type: Object, | ||||||
|  |       required: true, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   emits: ['update:visible', 'success'], | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       loading: false, | ||||||
|  |       form: { | ||||||
|  |         fromPenID: null, | ||||||
|  |         toPenID: null, | ||||||
|  |         quantity: 1, | ||||||
|  |         remarks: '', | ||||||
|  |       }, | ||||||
|  |       rules: { | ||||||
|  |         fromPenID: [{ required: true, message: '请选择调出猪栏', trigger: 'change' }], | ||||||
|  |         toPenID: [{ required: true, message: '请选择调入猪栏', trigger: 'change' }], | ||||||
|  |         quantity: [{ required: true, message: '请输入调栏数量', trigger: 'blur' }], | ||||||
|  |       }, | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  |   computed: { | ||||||
|  |     sourcePens() { | ||||||
|  |       return this.batch.pens || []; | ||||||
|  |     }, | ||||||
|  |     destinationPens() { | ||||||
|  |       if (!this.form.fromPenID) return []; | ||||||
|  |       return this.batch.pens.filter(pen => pen.id !== this.form.fromPenID); | ||||||
|  |     }, | ||||||
|  |     maxQuantity() { | ||||||
|  |       if (!this.form.fromPenID) return 1; | ||||||
|  |       const selectedPen = this.sourcePens.find(p => p.id === this.form.fromPenID); | ||||||
|  |       return selectedPen ? selectedPen.current_pig_count : 1; | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   watch: { | ||||||
|  |     visible(newVal) { | ||||||
|  |       if (newVal) { | ||||||
|  |         this.resetForm(); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     handleFromPenChange(penId) { | ||||||
|  |       this.form.toPenID = null; | ||||||
|  |       this.form.quantity = 1; | ||||||
|  |       const selectedPen = this.sourcePens.find(p => p.id === penId); | ||||||
|  |       if (selectedPen && selectedPen.current_pig_count === 0) { | ||||||
|  |         this.$message.warning('该猪栏没有猪,无法调出。'); | ||||||
|  |         this.form.fromPenID = null; | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     handleSubmit() { | ||||||
|  |       this.$refs.formRef.validate(async (valid) => { | ||||||
|  |         if (valid) { | ||||||
|  |           if (this.form.quantity > this.maxQuantity) { | ||||||
|  |             this.$message.error('调栏数量不能超过当前存栏量'); | ||||||
|  |             return; | ||||||
|  |           } | ||||||
|  |           this.loading = true; | ||||||
|  |           try { | ||||||
|  |             await transferPigsWithinBatch(this.batch.id, this.form); | ||||||
|  |             this.$message.success('调栏成功'); | ||||||
|  |             this.$emit('success'); | ||||||
|  |             this.handleClose(); | ||||||
|  |           } catch (error) { | ||||||
|  |             this.$message.error('调栏失败: ' + (error.response?.data?.message || error.message)); | ||||||
|  |             console.error('Failed to transfer pigs:', error); | ||||||
|  |           } finally { | ||||||
|  |             this.loading = false; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |     handleClose() { | ||||||
|  |       this.$emit('update:visible', false); | ||||||
|  |     }, | ||||||
|  |     resetForm() { | ||||||
|  |       if (this.$refs.formRef) { | ||||||
|  |         this.$refs.formRef.resetFields(); | ||||||
|  |       } | ||||||
|  |       this.form = { | ||||||
|  |         fromPenID: null, | ||||||
|  |         toPenID: null, | ||||||
|  |         quantity: 1, | ||||||
|  |         remarks: '', | ||||||
|  |       }; | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .dialog-footer { | ||||||
|  |   text-align: right; | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -77,6 +77,10 @@ | |||||||
|             <el-icon><FirstAidKit /></el-icon> |             <el-icon><FirstAidKit /></el-icon> | ||||||
|             <template #title>用药记录</template> |             <template #title>用药记录</template> | ||||||
|           </el-menu-item> |           </el-menu-item> | ||||||
|  |           <el-menu-item index="/monitor/notifications"> | ||||||
|  |             <el-icon><Bell /></el-icon> | ||||||
|  |             <template #title>通知记录</template> | ||||||
|  |           </el-menu-item> | ||||||
|           <el-menu-item index="/monitor/pending-collections"> |           <el-menu-item index="/monitor/pending-collections"> | ||||||
|             <el-icon><Clock /></el-icon> |             <el-icon><Clock /></el-icon> | ||||||
|             <template #title>待采集请求</template> |             <template #title>待采集请求</template> | ||||||
| @@ -183,14 +187,14 @@ import { ref, computed, onMounted, onUnmounted } from 'vue'; | |||||||
| import { useRoute, useRouter } from 'vue-router'; | import { useRoute, useRouter } from 'vue-router'; | ||||||
| import {  | import {  | ||||||
|   House, Monitor, Calendar, ArrowDown, Menu, Fold, Expand, Setting, Tickets, DataAnalysis, Document, Food, |   House, Monitor, Calendar, ArrowDown, Menu, Fold, Expand, Setting, Tickets, DataAnalysis, Document, Food, | ||||||
|   FirstAidKit, Clock, Files, ShoppingCart, SoldOut, Warning, Switch, List, Shop, Coin, DataLine, Finished, User, ScaleToOriginal, OfficeBuilding, Management |   FirstAidKit, Clock, Files, ShoppingCart, SoldOut, Warning, Switch, List, Shop, Coin, DataLine, Finished, User, ScaleToOriginal, OfficeBuilding, Management, Bell | ||||||
| } from '@element-plus/icons-vue'; | } from '@element-plus/icons-vue'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'MainLayout', |   name: 'MainLayout', | ||||||
|   components: { |   components: { | ||||||
|     House, Monitor, Calendar, ArrowDown, Menu, Fold, Expand, Setting, Tickets, DataAnalysis, Document, Food, |     House, Monitor, Calendar, ArrowDown, Menu, Fold, Expand, Setting, Tickets, DataAnalysis, Document, Food, | ||||||
|     FirstAidKit, Clock, Files, ShoppingCart, SoldOut, Warning, Switch, List, Shop, Coin, DataLine, Finished, User, ScaleToOriginal, OfficeBuilding, Management |     FirstAidKit, Clock, Files, ShoppingCart, SoldOut, Warning, Switch, List, Shop, Coin, DataLine, Finished, User, ScaleToOriginal, OfficeBuilding, Management, Bell | ||||||
|   }, |   }, | ||||||
|   setup() { |   setup() { | ||||||
|     const route = useRoute(); |     const route = useRoute(); | ||||||
| @@ -233,6 +237,7 @@ export default { | |||||||
|         '/monitor/device-command-logs': '设备命令日志', |         '/monitor/device-command-logs': '设备命令日志', | ||||||
|         '/monitor/feed-usage-records': '饲料使用记录', |         '/monitor/feed-usage-records': '饲料使用记录', | ||||||
|         '/monitor/medication-logs': '用药记录', |         '/monitor/medication-logs': '用药记录', | ||||||
|  |         '/monitor/notifications': '通知记录', | ||||||
|         '/monitor/pending-collections': '待采集请求', |         '/monitor/pending-collections': '待采集请求', | ||||||
|         '/monitor/pig-batch-logs': '猪批次日志', |         '/monitor/pig-batch-logs': '猪批次日志', | ||||||
|         '/monitor/pig-purchases': '猪只采购记录', |         '/monitor/pig-purchases': '猪只采购记录', | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ import PigBatchManagementView from './views/pms/PigBatchManagementView.vue'; // | |||||||
| import DeviceCommandLogView from './views/monitor/DeviceCommandLogView.vue'; | import DeviceCommandLogView from './views/monitor/DeviceCommandLogView.vue'; | ||||||
| import FeedUsageRecordsView from './views/monitor/FeedUsageRecordsView.vue'; | import FeedUsageRecordsView from './views/monitor/FeedUsageRecordsView.vue'; | ||||||
| import MedicationLogsView from './views/monitor/MedicationLogsView.vue'; | import MedicationLogsView from './views/monitor/MedicationLogsView.vue'; | ||||||
|  | import NotificationLogView from './views/monitor/NotificationLogView.vue'; | ||||||
| import PendingCollectionsView from './views/monitor/PendingCollectionsView.vue'; | import PendingCollectionsView from './views/monitor/PendingCollectionsView.vue'; | ||||||
| import PigBatchLogsView from './views/monitor/PigBatchLogsView.vue'; | import PigBatchLogsView from './views/monitor/PigBatchLogsView.vue'; | ||||||
| import PigPurchasesView from './views/monitor/PigPurchasesView.vue'; | import PigPurchasesView from './views/monitor/PigPurchasesView.vue'; | ||||||
| @@ -50,6 +51,7 @@ const routes = [ | |||||||
|     {path: '/monitor/device-command-logs', component: DeviceCommandLogView, meta: {requiresAuth: true}}, |     {path: '/monitor/device-command-logs', component: DeviceCommandLogView, meta: {requiresAuth: true}}, | ||||||
|     {path: '/monitor/feed-usage-records', component: FeedUsageRecordsView, meta: {requiresAuth: true}}, |     {path: '/monitor/feed-usage-records', component: FeedUsageRecordsView, meta: {requiresAuth: true}}, | ||||||
|     {path: '/monitor/medication-logs', component: MedicationLogsView, meta: {requiresAuth: true}}, |     {path: '/monitor/medication-logs', component: MedicationLogsView, meta: {requiresAuth: true}}, | ||||||
|  |     {path: '/monitor/notifications', component: NotificationLogView, meta: {requiresAuth: true}}, | ||||||
|     {path: '/monitor/pending-collections', component: PendingCollectionsView, meta: {requiresAuth: true}}, |     {path: '/monitor/pending-collections', component: PendingCollectionsView, meta: {requiresAuth: true}}, | ||||||
|     {path: '/monitor/pig-batch-logs', component: PigBatchLogsView, meta: {requiresAuth: true}}, |     {path: '/monitor/pig-batch-logs', component: PigBatchLogsView, meta: {requiresAuth: true}}, | ||||||
|     {path: '/monitor/pig-purchases', component: PigPurchasesView, meta: {requiresAuth: true}}, |     {path: '/monitor/pig-purchases', component: PigPurchasesView, meta: {requiresAuth: true}}, | ||||||
|   | |||||||
| @@ -53,9 +53,7 @@ http.interceptors.response.use( | |||||||
|       if (error.response.status === 401) { |       if (error.response.status === 401) { | ||||||
|         // 清除token并重定向到登录页 |         // 清除token并重定向到登录页 | ||||||
|         localStorage.removeItem('jwt_token'); |         localStorage.removeItem('jwt_token'); | ||||||
|         // 这里需要访问router,但http.js是纯工具文件,不应直接依赖Vue Router实例 |         window.location.href = '/login'; | ||||||
|         // 可以在main.js的全局错误处理或组件中处理401错误 |  | ||||||
|         // 例如:window.location.href = '/login'; |  | ||||||
|       } |       } | ||||||
|     } else if (error.request) { |     } else if (error.request) { | ||||||
|       // 请求发出但没有收到响应 |       // 请求发出但没有收到响应 | ||||||
|   | |||||||
							
								
								
									
										111
									
								
								src/views/monitor/NotificationLogView.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/views/monitor/NotificationLogView.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | <template> | ||||||
|  |   <div class="notification-log-view"> | ||||||
|  |     <GenericMonitorList | ||||||
|  |       :fetchData="fetchNotifications" | ||||||
|  |       :columnsConfig="notificationLogColumns" | ||||||
|  |     /> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import GenericMonitorList from '../../components/GenericMonitorList.vue'; | ||||||
|  | import { getNotifications, ZapcoreLevel } from '../../api/monitor.js'; | ||||||
|  | import { formatRFC3339 } from '../../utils/format.js'; | ||||||
|  |  | ||||||
|  | // 适配通用组件的 fetchData prop | ||||||
|  | const fetchNotifications = async (params) => { | ||||||
|  |   return await getNotifications(params); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // 定义表格的列 | ||||||
|  | const notificationLogColumns = [ | ||||||
|  |   { | ||||||
|  |     title: '用户ID', | ||||||
|  |     dataIndex: 'user_id', | ||||||
|  |     key: 'user_id', | ||||||
|  |     sorter: true, | ||||||
|  |     filterType: 'number', | ||||||
|  |     minWidth: 100, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '通知渠道', | ||||||
|  |     dataIndex: 'notifier_type', | ||||||
|  |     key: 'notifier_type', | ||||||
|  |     filterType: 'select', | ||||||
|  |     filterOptions: [ | ||||||
|  |       { value: '邮件', text: '邮件' }, | ||||||
|  |       { value: '企业微信', text: '企业微信' }, | ||||||
|  |       { value: '飞书', text: '飞书' }, | ||||||
|  |       { value: '日志', text: '日志' }, | ||||||
|  |     ], | ||||||
|  |     minWidth: 120, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '目标地址', | ||||||
|  |     dataIndex: 'to_address', | ||||||
|  |     key: 'to_address', | ||||||
|  |     minWidth: 200, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '标题', | ||||||
|  |     dataIndex: 'title', | ||||||
|  |     key: 'title', | ||||||
|  |     minWidth: 200, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '消息', | ||||||
|  |     dataIndex: 'message', | ||||||
|  |     key: 'message', | ||||||
|  |     minWidth: 300, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '日志级别', | ||||||
|  |     dataIndex: 'level', | ||||||
|  |     key: 'level', | ||||||
|  |     sorter: true, | ||||||
|  |     filterType: 'select', | ||||||
|  |     filterOptions: Object.entries(ZapcoreLevel).map(([text, value]) => ({ value, text })), | ||||||
|  |     minWidth: 110, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '告警时间', | ||||||
|  |     dataIndex: 'alarm_timestamp', | ||||||
|  |     key: 'alarm_timestamp', | ||||||
|  |     sorter: true, | ||||||
|  |     formatter: (row, column, cellValue) => formatRFC3339(cellValue), | ||||||
|  |     minWidth: 180, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '状态', | ||||||
|  |     dataIndex: 'status', | ||||||
|  |     key: 'status', | ||||||
|  |     filterType: 'select', | ||||||
|  |     filterOptions: [ | ||||||
|  |       { value: '发送成功', text: '发送成功' }, | ||||||
|  |       { value: '发送失败', text: '发送失败' }, | ||||||
|  |       { value: '已跳过', text: '已跳过' }, | ||||||
|  |     ], | ||||||
|  |     minWidth: 120, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '错误信息', | ||||||
|  |     dataIndex: 'error_message', | ||||||
|  |     key: 'error_message', | ||||||
|  |     minWidth: 200, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '创建时间', | ||||||
|  |     dataIndex: 'created_at', | ||||||
|  |     key: 'created_at', | ||||||
|  |     sorter: true, | ||||||
|  |     formatter: (row, column, cellValue) => formatRFC3339(cellValue), | ||||||
|  |     minWidth: 180, | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  | .notification-log-view { | ||||||
|  |   /* 视图容器样式 */ | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -34,6 +34,12 @@ const planExecutionLogColumns = [ | |||||||
|     sorter: true, |     sorter: true, | ||||||
|     minWidth: 120, |     minWidth: 120, | ||||||
|   }, |   }, | ||||||
|  |   { | ||||||
|  |     title: '计划名称', | ||||||
|  |     dataIndex: 'plan_name', | ||||||
|  |     key: 'plan_name', | ||||||
|  |     minWidth: 150, | ||||||
|  |   }, | ||||||
|   { |   { | ||||||
|     title: '状态', |     title: '状态', | ||||||
|     dataIndex: 'status', |     dataIndex: 'status', | ||||||
|   | |||||||
| @@ -6,11 +6,22 @@ | |||||||
|           <div class="title-container"> |           <div class="title-container"> | ||||||
|             <h2 class="page-title">计划管理</h2> |             <h2 class="page-title">计划管理</h2> | ||||||
|             <el-button type="text" @click="loadPlans" class="refresh-btn" title="刷新计划列表"> |             <el-button type="text" @click="loadPlans" class="refresh-btn" title="刷新计划列表"> | ||||||
|               <el-icon :size="20"><Refresh /></el-icon> |               <el-icon :size="20"> | ||||||
|  |                 <Refresh/> | ||||||
|  |               </el-icon> | ||||||
|             </el-button> |             </el-button> | ||||||
|           </div> |           </div> | ||||||
|  |  | ||||||
|  |           <div class="filter-and-add"> | ||||||
|  |             <el-select v-model="planTypeFilter" placeholder="选择计划类型" @change="loadPlans" | ||||||
|  |                        style="width: 150px; margin-right: 10px;"> | ||||||
|  |               <el-option label="所有任务" value="所有任务"></el-option> | ||||||
|  |               <el-option label="自定义任务" value="自定义任务"></el-option> | ||||||
|  |               <el-option label="系统任务" value="系统任务"></el-option> | ||||||
|  |             </el-select> | ||||||
|             <el-button type="primary" @click="addPlan">添加计划</el-button> |             <el-button type="primary" @click="addPlan">添加计划</el-button> | ||||||
|           </div> |           </div> | ||||||
|  |         </div> | ||||||
|       </template> |       </template> | ||||||
|  |  | ||||||
|       <!-- 加载状态 --> |       <!-- 加载状态 --> | ||||||
| @@ -44,7 +55,7 @@ | |||||||
|         <el-table-column prop="description" label="计划描述" min-width="150"/> |         <el-table-column prop="description" label="计划描述" min-width="150"/> | ||||||
|         <el-table-column prop="execution_type" label="执行类型" min-width="150" sortable="custom"> |         <el-table-column prop="execution_type" label="执行类型" min-width="150" sortable="custom"> | ||||||
|           <template #default="scope"> |           <template #default="scope"> | ||||||
|             <el-tag v-if="scope.row.execution_type === 'manual'">手动</el-tag> |             <el-tag v-if="scope.row.execution_type === '手动'">手动</el-tag> | ||||||
|             <el-tag v-else-if="scope.row.execute_num === 0" type="success">自动(无限执行)</el-tag> |             <el-tag v-else-if="scope.row.execute_num === 0" type="success">自动(无限执行)</el-tag> | ||||||
|             <el-tag v-else type="warning">自动({{ scope.row.execute_num }}次)</el-tag> |             <el-tag v-else type="warning">自动({{ scope.row.execute_num }}次)</el-tag> | ||||||
|           </template> |           </template> | ||||||
| @@ -65,17 +76,21 @@ | |||||||
|         </el-table-column> |         </el-table-column> | ||||||
|         <el-table-column label="操作" width="280"> |         <el-table-column label="操作" width="280"> | ||||||
|           <template #default="scope"> |           <template #default="scope"> | ||||||
|             <el-button size="small" @click="editPlan(scope.row)">编辑</el-button> |             <el-button size="small" @click="editPlan(scope.row)" :disabled="scope.row.plan_type === '系统任务'">编辑 | ||||||
|  |             </el-button> | ||||||
|             <el-button size="small" @click="showDetails(scope.row)">详情</el-button> |             <el-button size="small" @click="showDetails(scope.row)">详情</el-button> | ||||||
|             <el-button |             <el-button | ||||||
|                 size="small" |                 size="small" | ||||||
|                 :type="scope.row.status === 1 ? 'warning' : 'primary'" |                 :type="scope.row.status === 1 ? 'warning' : 'primary'" | ||||||
|                 @click="scope.row.status === 1 ? stopPlan(scope.row) : startPlan(scope.row)" |                 @click="scope.row.status === 1 ? stopPlan(scope.row) : startPlan(scope.row)" | ||||||
|                 :loading="stoppingPlanId === scope.row.id || startingPlanId === scope.row.id" |                 :loading="stoppingPlanId === scope.row.id || startingPlanId === scope.row.id" | ||||||
|  |                 :disabled="scope.row.plan_type === '系统任务'" | ||||||
|             > |             > | ||||||
|               {{ scope.row.status === 1 ? '停止' : '启动' }} |               {{ scope.row.status === 1 ? '停止' : '启动' }} | ||||||
|             </el-button> |             </el-button> | ||||||
|             <el-button size="small" type="danger" @click="deletePlan(scope.row)">删除</el-button> |             <el-button size="small" type="danger" @click="deletePlan(scope.row)" | ||||||
|  |                        :disabled="scope.row.plan_type === '系统任务'">删除 | ||||||
|  |             </el-button> | ||||||
|           </template> |           </template> | ||||||
|         </el-table-column> |         </el-table-column> | ||||||
|       </el-table> |       </el-table> | ||||||
| @@ -145,7 +160,8 @@ export default { | |||||||
|       }, |       }, | ||||||
|       selectedPlanIdForDetails: null, // 当前要查看详情的计划ID |       selectedPlanIdForDetails: null, // 当前要查看详情的计划ID | ||||||
|       startingPlanId: null, |       startingPlanId: null, | ||||||
|       stoppingPlanId: null |       stoppingPlanId: null, | ||||||
|  |       planTypeFilter: '自定义任务', // 新增:计划类型筛选,默认自定义任务 | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|   async mounted() { |   async mounted() { | ||||||
| @@ -158,7 +174,7 @@ export default { | |||||||
|       this.error = null; |       this.error = null; | ||||||
|  |  | ||||||
|       try { |       try { | ||||||
|         const response = await apiClient.plans.getPlans(); // 更正此处 |         const response = await apiClient.plans.getPlans({plan_type: this.planTypeFilter, page: 1, page_size: 1000}); // 传递 plan_typeFilter | ||||||
|         let fetchedPlans = response.data?.plans || []; |         let fetchedPlans = response.data?.plans || []; | ||||||
|         // Default sort by ID ascending |         // Default sort by ID ascending | ||||||
|         fetchedPlans.sort((a, b) => a.id - b.id); |         fetchedPlans.sort((a, b) => a.id - b.id); | ||||||
| @@ -326,6 +342,10 @@ export default { | |||||||
|     handlePlanCancel() { |     handlePlanCancel() { | ||||||
|       this.dialogVisible = false; |       this.dialogVisible = false; | ||||||
|     } |     } | ||||||
|  |   }, | ||||||
|  |   watch: { | ||||||
|  |     // 监听 planTypeFilter 变化,重新加载计划列表 | ||||||
|  |     planTypeFilter: 'loadPlans' | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
| @@ -388,10 +408,16 @@ export default { | |||||||
|   height: 20px; |   height: 20px; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .filter-and-add { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
| @media (max-width: 768px) { | @media (max-width: 768px) { | ||||||
|   .plan-list { |   .plan-list { | ||||||
|     padding: 10px; |     padding: 10px; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .card-header { |   .card-header { | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|     gap: 15px; |     gap: 15px; | ||||||
|   | |||||||
| @@ -42,6 +42,8 @@ | |||||||
|           @modify-pig-count-pen="handleModifyPigCountPen" |           @modify-pig-count-pen="handleModifyPigCountPen" | ||||||
|           @remove-pen="handleRemovePen" |           @remove-pen="handleRemovePen" | ||||||
|           @assign-pen-to-batch="handleAssignPenToBatch" |           @assign-pen-to-batch="handleAssignPenToBatch" | ||||||
|  |           @transfer-pigs="handleTransferPigs" | ||||||
|  |           @transfer-pigs-across-batches="handleTransferPigsAcrossBatches" | ||||||
|           @reload-data="loadData" |           @reload-data="loadData" | ||||||
|         /> |         /> | ||||||
|         <el-empty v-else description="暂无数据" /> |         <el-empty v-else description="暂无数据" /> | ||||||
| @@ -66,6 +68,21 @@ | |||||||
|       @success="handlePenSuccess" |       @success="handlePenSuccess" | ||||||
|       @cancel="penDialogVisible = false" |       @cancel="penDialogVisible = false" | ||||||
|     /> |     /> | ||||||
|  |  | ||||||
|  |     <!-- 群内调栏对话框 --> | ||||||
|  |     <TransferPigsModal | ||||||
|  |       v-if="transferDialogVisible" | ||||||
|  |       v-model:visible="transferDialogVisible" | ||||||
|  |       :batch="currentBatchForTransfer" | ||||||
|  |       @success="handleTransferSuccess" | ||||||
|  |     /> | ||||||
|  |  | ||||||
|  |     <!-- 跨群调栏对话框 --> | ||||||
|  |     <TransferPigsAcrossBatchesModal | ||||||
|  |       v-model:visible="transferAcrossBatchesDialogVisible" | ||||||
|  |       :batch="currentBatchForTransferAcrossBatches" | ||||||
|  |       @success="handleTransferAcrossBatchesSuccess" | ||||||
|  |     /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -76,6 +93,8 @@ import { getPigHouses } from '@/api/pigHouse.js'; | |||||||
| import PigBatchList from '@/components/PigBatchList.vue'; | import PigBatchList from '@/components/PigBatchList.vue'; | ||||||
| import PigBatchForm from '@/components/PigBatchForm.vue'; | import PigBatchForm from '@/components/PigBatchForm.vue'; | ||||||
| import PenForm from '@/components/PenForm.vue'; | import PenForm from '@/components/PenForm.vue'; | ||||||
|  | import TransferPigsModal from '@/components/TransferPigsModal.vue'; | ||||||
|  | import TransferPigsAcrossBatchesModal from '@/components/TransferPigsAcrossBatchesModal.vue'; | ||||||
| import { Refresh } from '@element-plus/icons-vue'; | import { Refresh } from '@element-plus/icons-vue'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
| @@ -84,6 +103,8 @@ export default { | |||||||
|     PigBatchList, |     PigBatchList, | ||||||
|     PigBatchForm, |     PigBatchForm, | ||||||
|     PenForm, |     PenForm, | ||||||
|  |     TransferPigsModal, | ||||||
|  |     TransferPigsAcrossBatchesModal, | ||||||
|     Refresh |     Refresh | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
| @@ -99,6 +120,12 @@ export default { | |||||||
|       penDialogVisible: false, |       penDialogVisible: false, | ||||||
|       isEditPen: false, |       isEditPen: false, | ||||||
|       currentPen: {}, |       currentPen: {}, | ||||||
|  |       // 调栏模态框状态 | ||||||
|  |       transferDialogVisible: false, | ||||||
|  |       currentBatchForTransfer: {}, | ||||||
|  |       // 跨群调栏模态框状态 | ||||||
|  |       transferAcrossBatchesDialogVisible: false, | ||||||
|  |       currentBatchForTransferAcrossBatches: {}, | ||||||
|       // 辅助映射 |       // 辅助映射 | ||||||
|       houseMap: new Map(), // 用于猪栏显示猪舍名称 |       houseMap: new Map(), // 用于猪栏显示猪舍名称 | ||||||
|     }; |     }; | ||||||
| @@ -208,6 +235,11 @@ export default { | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     // --- 猪栏操作 (在猪群管理中) --- |     // --- 猪栏操作 (在猪群管理中) --- | ||||||
|  |     handleAddPen(house) { | ||||||
|  |       this.currentPen = { ...house }; // 修正:这里应该是传入house对象,而不是pen对象 | ||||||
|  |       this.isEditPen = false; | ||||||
|  |       this.penDialogVisible = true; | ||||||
|  |     }, | ||||||
|     handleModifyPigCountPen(pen) { |     handleModifyPigCountPen(pen) { | ||||||
|       this.currentPen = { ...pen }; |       this.currentPen = { ...pen }; | ||||||
|       this.isEditPen = true; |       this.isEditPen = true; | ||||||
| @@ -264,6 +296,25 @@ export default { | |||||||
|         this.$message.error('分配猪栏失败: ' + (error.response?.data?.message || error.message || '未知错误')); |         this.$message.error('分配猪栏失败: ' + (error.response?.data?.message || error.message || '未知错误')); | ||||||
|         console.error('Failed to assign pen to batch:', error); |         console.error('Failed to assign pen to batch:', error); | ||||||
|       } |       } | ||||||
|  |     }, | ||||||
|  |     // --- 调栏操作 --- | ||||||
|  |     handleTransferPigs(batch) { | ||||||
|  |       this.currentBatchForTransfer = batch; | ||||||
|  |       this.transferDialogVisible = true; | ||||||
|  |     }, | ||||||
|  |     handleTransferSuccess() { | ||||||
|  |       this.transferDialogVisible = false; | ||||||
|  |       this.loadData(); // 重新加载数据以反映变化 | ||||||
|  |     }, | ||||||
|  |     handleTransferPigsAcrossBatches(batch) { | ||||||
|  |       console.log('handleTransferPigsAcrossBatches called with batch:', batch); | ||||||
|  |       this.currentBatchForTransferAcrossBatches = batch; | ||||||
|  |       this.transferAcrossBatchesDialogVisible = true; | ||||||
|  |       console.log('transferAcrossBatchesDialogVisible set to:', this.transferAcrossBatchesDialogVisible); | ||||||
|  |     }, | ||||||
|  |     handleTransferAcrossBatchesSuccess() { | ||||||
|  |       this.transferAcrossBatchesDialogVisible = false; | ||||||
|  |       this.loadData(); // 重新加载数据以反映变化 | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user