Compare commits
	
		
			11 Commits
		
	
	
		
			accbb1a9f6
			...
			d85cfb303b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d85cfb303b | |||
| 2e5c04d2d4 | |||
| 2fe6f0c576 | |||
| c176fadafe | |||
| ced688a7a3 | |||
| 263af9fa3a | |||
| 1a55330734 | |||
| 0026f24002 | |||
| 2d6bb69387 | |||
| 70e3a4f2b0 | |||
| 98cd24ee29 | 
| @@ -191,3 +191,21 @@ export const recordDeathInBatch = (id, deathData) => { | ||||
| export const recordCullInBatch = (id, cullData) => { | ||||
|   return http.post(`/api/v1/pig-batches/record-cull/${id}`, cullData); | ||||
| }; | ||||
|  | ||||
| // --- 新增的猪栏和猪舍API --- | ||||
|  | ||||
| /** | ||||
|  * 获取所有猪栏的列表 | ||||
|  * @returns {Promise<*>} | ||||
|  */ | ||||
| export const getAllPens = () => { | ||||
|   return http.get('/api/v1/pens'); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * 获取所有猪舍的列表 | ||||
|  * @returns {Promise<*>} | ||||
|  */ | ||||
| export const getAllPigHouses = () => { | ||||
|   return http.get('/api/v1/pig-houses'); | ||||
| }; | ||||
|   | ||||
| @@ -3,24 +3,44 @@ | ||||
|     <div v-for="batch in pigBatches" :key="batch.id" class="pig-batch-item"> | ||||
|       <div class="batch-header" @click="toggleExpand(batch)"> | ||||
|         <div class="batch-info"> | ||||
|           <span>批次编号: {{ batch.batch_number }}</span> | ||||
|           <span>状态: {{ batch.status }}</span> | ||||
|           <span>初始数量: {{ batch.initial_count }}</span> | ||||
|           <div class="batch-info-line"> | ||||
|             <span>批次编号: {{ batch.batch_number }}</span> | ||||
|             <span>状态: {{ batch.status }}</span> | ||||
|             <span>初始数量: {{ batch.initial_count }}</span> | ||||
|             <span v-if="batch.currentTotalQuantity !== undefined && batch.currentTotalQuantity !== null">当前总数: {{ batch.currentTotalQuantity }}</span> | ||||
|             <span v-if="batch.origin_type">批次来源: {{ batch.origin_type }}</span> | ||||
|           </div> | ||||
|           <div class="batch-info-line"> | ||||
|             <span v-if="batch.start_date">批次开始日期: {{ formatRFC3339(batch.start_date) }}</span> | ||||
|             <span v-if="batch.end_date"> | ||||
|               批次结束日期: | ||||
|               <template v-if="formatRFC3339(batch.end_date) === '0001-01-01 08:00:00'"> | ||||
|                 正在饲养中 | ||||
|               </template> | ||||
|               <template v-else> | ||||
|                 {{ formatRFC3339(batch.end_date) }} | ||||
|               </template> | ||||
|             </span> | ||||
|             <span v-if="batch.unassigned_pig_count !== undefined && batch.unassigned_pig_count > 0" class="red-text"> | ||||
|               未分配数量: {{ batch.unassigned_pig_count }} | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="batch-actions"> | ||||
|           <el-button size="small" type="primary" @click.stop="emitAddPen(batch)">增加猪栏</el-button> | ||||
|           <el-button size="small" type="primary" @click.stop="showAddPenDialog(batch)" :disabled="!batch.is_active">增加猪栏</el-button> | ||||
|           <el-button size="small" @click.stop="emitEditBatch(batch)">编辑</el-button> | ||||
|           <el-button size="small" type="danger" @click.stop="emitDeleteBatch(batch)">删除</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div v-if="batch.isExpanded" class="batch-content"> | ||||
|         <div v-if="batch.pens && batch.pens.length > 0" class="pig-pen-list"> | ||||
|           <PigPenInfoCard | ||||
|           <PigBatchPenCard | ||||
|             v-for="pen in batch.pens" | ||||
|             :key="pen.id" | ||||
|             :pen="pen" | ||||
|             @edit="emitEditPen" | ||||
|             @delete="emitDeletePen" | ||||
|             :isBatchActive="batch.is_active" | ||||
|             @modify-pig-count="emitModifyPigCountPen" | ||||
|             @remove="emitRemovePen" | ||||
|           /> | ||||
|         </div> | ||||
|         <div v-else class="no-pens-message"> | ||||
| @@ -28,16 +48,36 @@ | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <!-- 增加猪栏对话框 --> | ||||
|     <el-dialog title="选择猪栏" v-model="addPenDialogVisible" width="30%"> | ||||
|       <el-select v-model="selectedPenId" placeholder="请选择猪栏" style="width: 100%;"> | ||||
|         <el-option | ||||
|           v-for="pen in availablePens" | ||||
|           :key="pen.id" | ||||
|           :label="pen.label" | ||||
|           :value="pen.id"> | ||||
|         </el-option> | ||||
|       </el-select> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button @click="addPenDialogVisible = false">取 消</el-button> | ||||
|           <el-button type="primary" @click="assignPen">确 定</el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import PigPenInfoCard from './PigPenInfoCard.vue'; | ||||
| import PigBatchPenCard from './PigBatchPenCard.vue'; | ||||
| import { getAllPens, getAllPigHouses } from '../api/pigBatch'; | ||||
| import { formatRFC3339 } from '../utils/format'; // 导入格式化函数 | ||||
|  | ||||
| export default { | ||||
|   name: 'PigBatchList', | ||||
|   components: { | ||||
|     PigPenInfoCard | ||||
|     PigBatchPenCard | ||||
|   }, | ||||
|   props: { | ||||
|     pigBatches: { | ||||
| @@ -45,15 +85,60 @@ export default { | ||||
|       required: true | ||||
|     } | ||||
|   }, | ||||
|   emits: ['edit-batch', 'delete-batch', 'add-pen', 'edit-pen', 'delete-pen'], | ||||
|   emits: ['edit-batch', 'delete-batch', 'add-pen', 'modify-pig-count-pen', 'remove-pen', 'assign-pen-to-batch'], | ||||
|   data() { | ||||
|     return { | ||||
|       addPenDialogVisible: false, | ||||
|       availablePens: [], | ||||
|       selectedPenId: null, | ||||
|       currentBatch: null // To store the batch for which we are adding a pen | ||||
|     }; | ||||
|   }, | ||||
|   methods: { | ||||
|     formatRFC3339, | ||||
|     toggleExpand(batch) { | ||||
|       batch.isExpanded = !batch.isExpanded; | ||||
|     }, | ||||
|     // 猪群操作 | ||||
|     emitAddPen(batch) { | ||||
|       this.$emit('add-pen', batch); | ||||
|     async fetchAvailablePens() { | ||||
|       try { | ||||
|         const [pensResponse, housesResponse] = await Promise.all([ | ||||
|           getAllPens(), | ||||
|           getAllPigHouses() | ||||
|         ]); | ||||
|  | ||||
|         const pens = pensResponse.data;  | ||||
|         const houses = housesResponse.data; | ||||
|  | ||||
|         // Create a map for quick lookup of house names by ID | ||||
|         const houseMap = new Map(houses.map(house => [house.id, house.name])); | ||||
|  | ||||
|         this.availablePens = pens.map(pen => ({ | ||||
|           id: pen.id, | ||||
|           label: `${pen.pen_number}(${houseMap.get(pen.house_id) || '未知猪舍'})` // Changed format here | ||||
|         })); | ||||
|       } catch (error) { | ||||
|         console.error("Error fetching pens or houses:", error); | ||||
|         this.$message.error("获取猪栏或猪舍信息失败"); | ||||
|       } | ||||
|     }, | ||||
|     showAddPenDialog(batch) { | ||||
|       this.currentBatch = batch; | ||||
|       this.selectedPenId = null; // Reset selection | ||||
|       this.fetchAvailablePens(); | ||||
|       this.addPenDialogVisible = true; | ||||
|     }, | ||||
|     assignPen() { | ||||
|       if (this.selectedPenId && this.currentBatch) { | ||||
|         this.$emit('assign-pen-to-batch', { | ||||
|           batchId: this.currentBatch.id, | ||||
|           penId: this.selectedPenId | ||||
|         }); | ||||
|         this.addPenDialogVisible = false; | ||||
|       } else { | ||||
|         this.$message.warning("请选择一个猪栏"); | ||||
|       } | ||||
|     }, | ||||
|     // 猪群操作 | ||||
|     emitEditBatch(batch) { | ||||
|       this.$emit('edit-batch', batch); | ||||
|     }, | ||||
| @@ -61,11 +146,11 @@ export default { | ||||
|       this.$emit('delete-batch', batch); | ||||
|     }, | ||||
|     // 猪栏操作 | ||||
|     emitEditPen(pen) { | ||||
|       this.$emit('edit-pen', pen); | ||||
|     emitModifyPigCountPen(pen) { | ||||
|       this.$emit('modify-pig-count-pen', pen); | ||||
|     }, | ||||
|     emitDeletePen(pen) { | ||||
|       this.$emit('delete-pen', pen); | ||||
|     emitRemovePen(pen) { | ||||
|       this.$emit('remove-pen', pen); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -99,16 +184,21 @@ export default { | ||||
|  | ||||
| .batch-info { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   gap: 8px; | ||||
|   flex-direction: column; /* 垂直堆叠子元素 */ | ||||
|   gap: 8px; /* 行间距 */ | ||||
| } | ||||
|  | ||||
| .batch-info span:first-child { | ||||
| .batch-info-line { | ||||
|   display: flex; | ||||
|   flex-wrap: wrap; | ||||
|   gap: 0 20px; /* 列间距 */ | ||||
| } | ||||
|  | ||||
| .batch-info-line:first-child span:first-child { | ||||
|   font-weight: bold; | ||||
| } | ||||
|  | ||||
| .batch-info span { | ||||
|   margin-right: 20px; | ||||
|   font-size: 14px; | ||||
|   color: #606266; | ||||
| } | ||||
| @@ -134,4 +224,8 @@ export default { | ||||
|   text-align: center; | ||||
|   padding: 20px 0; | ||||
| } | ||||
|  | ||||
| .batch-info-line .red-text { | ||||
|   color: red !important; | ||||
| } | ||||
| </style> | ||||
|   | ||||
							
								
								
									
										127
									
								
								src/components/PigBatchPenCard.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/components/PigBatchPenCard.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| <template> | ||||
|   <div class="pig-pen-info-card"> | ||||
|     <div class="info-section"> | ||||
|       <div class="title"> | ||||
|         猪栏: {{ pen.pen_number }} <el-tag size="small" :type="statusType">{{ pen.status || '未知' }}</el-tag> | ||||
|       </div> | ||||
|       <div class="info-item">猪舍: {{ pen.house_name || '未知' }}</div> | ||||
|       <div class="info-item border-left">容量: {{ pen.capacity }}</div> | ||||
|       <div class="info-item">批次: {{ pen.batch_number || '未分配' }}</div> | ||||
|       <div class="info-item border-left">存栏: {{ pen.current_pig_count || 0 }}</div> | ||||
|     </div> | ||||
|     <div class="actions-section"> | ||||
|       <el-button size="small" @click="emitModifyPigCount" :disabled="!isBatchActive">修改猪只数量</el-button> | ||||
|       <el-button size="small" type="danger" @click="emitRemove" :disabled="!isBatchActive">移除</el-button> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { computed } from 'vue'; | ||||
|  | ||||
| export default { | ||||
|   name: 'PigBatchPenCard', | ||||
|   props: { | ||||
|     pen: { | ||||
|       type: Object, | ||||
|       required: true | ||||
|     }, | ||||
|     isBatchActive: { | ||||
|       type: Boolean, | ||||
|       default: true // 默认活跃,以防万一没有传递 | ||||
|     } | ||||
|   }, | ||||
|   emits: ['remove', 'modify-pig-count'], | ||||
|   setup(props, { emit }) { | ||||
|     const statusType = computed(() => { | ||||
|       switch (props.pen.status) { | ||||
|         case '使用中': | ||||
|           return 'success'; | ||||
|         case '病猪栏': | ||||
|         case '维修中': | ||||
|           return 'danger'; | ||||
|         case '清洗消毒': | ||||
|           return 'warning'; | ||||
|         case '空闲': | ||||
|         default: | ||||
|           return 'info'; | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     const emitModifyPigCount = () => { | ||||
|       emit('modify-pig-count', props.pen); | ||||
|     }; | ||||
|  | ||||
|     const emitRemove = () => { | ||||
|       emit('remove', props.pen); | ||||
|     }; | ||||
|  | ||||
|     return { | ||||
|       statusType, | ||||
|       emitModifyPigCount, | ||||
|       emitRemove | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
| .pig-pen-info-card { | ||||
|   border: 2px solid #ccc; | ||||
|   border-radius: 8px; | ||||
|   padding: 16px; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   justify-content: space-between; | ||||
|   width: 220px; /* 适当加宽以容纳更多信息 */ | ||||
|   height: auto; /* 让高度自适应内容 */ | ||||
|   min-height: 240px; /* 设置最小高度 */ | ||||
|   background-color: #fff; | ||||
|   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||
|   transition: box-shadow 0.3s; | ||||
| } | ||||
|  | ||||
| .pig-pen-info-card:hover { | ||||
|   box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | ||||
| } | ||||
|  | ||||
| .info-section { | ||||
|   display: grid; /* 使用grid布局创建两列 */ | ||||
|   grid-template-columns: 1fr 1fr; /* 两列等宽 */ | ||||
|   gap: 8px 10px; /* 行间距 8px, 列间距 10px */ | ||||
|   margin-bottom: 10px; | ||||
|   flex-grow: 1; /* 允许信息部分填充可用空间 */ | ||||
| } | ||||
|  | ||||
| .info-section .title { | ||||
|   font-weight: bold; | ||||
|   font-size: 1.1em; | ||||
|   color: #303133; | ||||
|   grid-column: 1 / -1; /* 标题横跨两列 */ | ||||
|   margin-bottom: 5px; /* 标题下方增加一点间距 */ | ||||
|   display: flex; /* Add flexbox for alignment */ | ||||
|   align-items: center; /* Vertically align items */ | ||||
|   gap: 8px; /* Space between title text and tag */ | ||||
| } | ||||
|  | ||||
| .info-section .info-item { | ||||
|   font-size: 0.9em; | ||||
|   color: #606266; | ||||
| } | ||||
|  | ||||
| .info-item.border-left { | ||||
|   border-left: 1px solid #eee; /* 添加左边框作为分隔线 */ | ||||
|   padding-left: 10px; /* 增加左内边距,使内容不紧贴边框 */ | ||||
| } | ||||
|  | ||||
| .actions-section { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   gap: 8px; | ||||
| } | ||||
|  | ||||
| .actions-section .el-button { | ||||
|   width: 100%; | ||||
|   margin: 0; | ||||
| } | ||||
| </style> | ||||
| @@ -1,7 +1,7 @@ | ||||
| <template> | ||||
|   <div class="pig-house-list"> | ||||
|     <div v-for="house in pigHouses" :key="house.id" class="pig-house-item"> | ||||
|       <div class="house-header" @click="toggleExpand(house)"> | ||||
|     <div v-for="house in enrichedPigHouses" :key="house.id" class="pig-house-item"> | ||||
|       <div class="house-header" @click="emitToggleExpand(house.id)"> | ||||
|         <div class="house-info"> | ||||
|           <span>猪舍: {{ house.name }}</span> | ||||
|           <span v-if="house.description">描述: {{ house.description }}</span> | ||||
| @@ -44,10 +44,25 @@ export default { | ||||
|       required: true | ||||
|     } | ||||
|   }, | ||||
|   emits: ['edit-house', 'delete-house', 'add-pen', 'edit-pen', 'delete-pen'], | ||||
|   emits: ['edit-house', 'delete-house', 'add-pen', 'edit-pen', 'delete-pen', 'toggle-house-expand'], | ||||
|   computed: { | ||||
|     enrichedPigHouses() { | ||||
|       return this.pigHouses.map(house => { | ||||
|         const pensWithHouseInfo = house.pens ? house.pens.map(pen => ({ | ||||
|           ...pen, | ||||
|           house_name: house.name, | ||||
|           house_id: house.id | ||||
|         })) : []; | ||||
|         return { | ||||
|           ...house, | ||||
|           pens: pensWithHouseInfo | ||||
|         }; | ||||
|       }); | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     toggleExpand(house) { | ||||
|       house.isExpanded = !house.isExpanded; | ||||
|     emitToggleExpand(houseId) { | ||||
|       this.$emit('toggle-house-expand', houseId); | ||||
|     }, | ||||
|     // 猪舍操作 | ||||
|     emitAddPen(house) { | ||||
| @@ -79,7 +94,7 @@ export default { | ||||
|   border: 1px solid #eee; | ||||
|   border-radius: 4px; | ||||
|   margin-bottom: 16px; | ||||
|   overflow: hidden; /* 防止子元素溢出圆角 */ | ||||
|   overflow: hidden; | ||||
| } | ||||
|  | ||||
| .house-header { | ||||
|   | ||||
| @@ -1,12 +1,13 @@ | ||||
| <template> | ||||
|   <div class="pig-pen-info-card"> | ||||
|     <div class="info-section"> | ||||
|       <div class="title">猪栏: {{ pen.pen_number }}</div> | ||||
|       <div class="info-item">状态: <el-tag size="small" :type="statusType">{{ pen.status || '未知' }}</el-tag></div> | ||||
|       <div class="info-item">容量: {{ pen.capacity }}</div> | ||||
|       <div class="info-item">存栏: {{ pen.current_pig_count || 0 }}</div> | ||||
|       <div class="info-item">批次: {{ pen.batch_number || '未分配' }}</div> | ||||
|       <div class="title"> | ||||
|         猪栏: {{ pen.pen_number }} <el-tag size="small" :type="statusType">{{ pen.status || '未知' }}</el-tag> | ||||
|       </div> | ||||
|       <div class="info-item">猪舍: {{ pen.house_name || '未知' }}</div> | ||||
|       <div class="info-item border-left">容量: {{ pen.capacity }}</div> | ||||
|       <div class="info-item">批次: {{ pen.batch_number || '未分配' }}</div> | ||||
|       <div class="info-item border-left">存栏: {{ pen.current_pig_count || 0 }}</div> | ||||
|     </div> | ||||
|     <div class="actions-section"> | ||||
|       <el-button size="small" @click="emitEdit">编辑</el-button> | ||||
| @@ -62,14 +63,15 @@ export default { | ||||
|  | ||||
| <style scoped> | ||||
| .pig-pen-info-card { | ||||
|   border: 1px solid #eee; | ||||
|   border: 2px solid #ccc; | ||||
|   border-radius: 8px; | ||||
|   padding: 16px; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   justify-content: space-between; | ||||
|   width: 200px; /* 适当加宽以容纳更多信息 */ | ||||
|   height: 260px; /* 调整高度以适应更多信息 */ | ||||
|   width: 220px; /* 适当加宽以容纳更多信息 */ | ||||
|   height: auto; /* 让高度自适应内容 */ | ||||
|   min-height: 240px; /* 设置最小高度 */ | ||||
|   background-color: #fff; | ||||
|   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | ||||
|   transition: box-shadow 0.3s; | ||||
| @@ -80,16 +82,22 @@ export default { | ||||
| } | ||||
|  | ||||
| .info-section { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   gap: 10px; /* 调整信息项间距 */ | ||||
|   display: grid; /* 使用grid布局创建两列 */ | ||||
|   grid-template-columns: 1fr 1fr; /* 两列等宽 */ | ||||
|   gap: 8px 10px; /* 行间距 8px, 列间距 10px */ | ||||
|   margin-bottom: 10px; | ||||
|   flex-grow: 1; /* 允许信息部分填充可用空间 */ | ||||
| } | ||||
|  | ||||
| .info-section .title { | ||||
|   font-weight: bold; | ||||
|   font-size: 1.1em; | ||||
|   color: #303133; | ||||
|   grid-column: 1 / -1; /* 标题横跨两列 */ | ||||
|   margin-bottom: 5px; /* 标题下方增加一点间距 */ | ||||
|   display: flex; /* Add flexbox for alignment */ | ||||
|   align-items: center; /* Vertically align items */ | ||||
|   gap: 8px; /* Space between title text and tag */ | ||||
| } | ||||
|  | ||||
| .info-section .info-item { | ||||
| @@ -97,6 +105,11 @@ export default { | ||||
|   color: #606266; | ||||
| } | ||||
|  | ||||
| .info-item.border-left { | ||||
|   border-left: 1px solid #eee; /* 添加左边框作为分隔线 */ | ||||
|   padding-left: 10px; /* 增加左内边距,使内容不紧贴边框 */ | ||||
| } | ||||
|  | ||||
| .actions-section { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   | ||||
| @@ -39,8 +39,9 @@ | ||||
|           @edit-batch="handleEditBatch"  | ||||
|           @delete-batch="handleDeleteBatch"  | ||||
|           @add-pen="handleAddPen" | ||||
|           @edit-pen="handleEditPen" | ||||
|           @delete-pen="handleDeletePen" | ||||
|           @modify-pig-count-pen="handleModifyPigCountPen" | ||||
|           @remove-pen="handleRemovePen" | ||||
|           @assign-pen-to-batch="handleAssignPenToBatch" | ||||
|         /> | ||||
|         <el-empty v-else description="暂无数据" /> | ||||
|       </div> | ||||
| @@ -68,12 +69,12 @@ | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { getPigBatches, deletePigBatch } from '@/api/pigBatch.js'; | ||||
| import { getPigBatches, deletePigBatch, assignPensToBatch } from '@/api/pigBatch.js'; | ||||
| import { getPens, deletePen } from '@/api/pen.js'; | ||||
| import { getPigHouses } from '@/api/pigHouse.js'; | ||||
| import PigBatchList from '@/components/PigBatchList.vue'; | ||||
| import PigBatchForm from '@/components/PigBatchForm.vue'; | ||||
| import PenForm from '@/components/PenForm.vue'; // 引入 PenForm | ||||
| import PenForm from '@/components/PenForm.vue'; | ||||
| import { Refresh } from '@element-plus/icons-vue'; | ||||
|  | ||||
| export default { | ||||
| @@ -119,8 +120,9 @@ export default { | ||||
|         const pens = Array.isArray(pensResponse.data) ? pensResponse.data : []; | ||||
|         const houses = Array.isArray(housesResponse.data) ? housesResponse.data : []; | ||||
|  | ||||
|         // 更新 houseMap | ||||
|         // 更新 batchMap 和 houseMap | ||||
|         this.houseMap = new Map(houses.map(h => [h.id, h.name])); | ||||
|         this.batchMap = new Map(batches.map(batch => [batch.id, batch.batch_number])); | ||||
|         this.pigBatchesData = this.assembleData(batches, pens); | ||||
|  | ||||
|       } catch (err) { | ||||
| @@ -141,12 +143,19 @@ export default { | ||||
|         if (pen.pig_batch_id && batchMap.has(pen.pig_batch_id)) { | ||||
|           const penWithDetails = { | ||||
|             ...pen, | ||||
|             house_name: this.houseMap.get(pen.house_id) || '未知猪舍' | ||||
|             house_name: this.houseMap.get(pen.house_id) || '未知猪舍', | ||||
|             batch_number: batchMap.get(pen.pig_batch_id)?.batch_number || null | ||||
|           }; | ||||
|           batchMap.get(pen.pig_batch_id).pens.push(penWithDetails); | ||||
|         } | ||||
|       } | ||||
|       return Array.from(batchMap.values()); | ||||
|       // Calculate unassigned_pig_count for each batch using currentTotalQuantity and currentTotalPigsInPens | ||||
|       const assembledBatches = Array.from(batchMap.values()); | ||||
|       assembledBatches.forEach(batch => { | ||||
|         // Use currentTotalQuantity and currentTotalPigsInPens directly from the batch object | ||||
|         batch.unassigned_pig_count = (batch.currentTotalQuantity || 0) - (batch.currentTotalPigsInPens || 0); | ||||
|       }); | ||||
|       return assembledBatches; | ||||
|     }, | ||||
|     // --- 猪群操作 --- | ||||
|     handleAddBatch() { | ||||
| @@ -198,17 +207,12 @@ export default { | ||||
|       } | ||||
|     }, | ||||
|     // --- 猪栏操作 (在猪群管理中) --- | ||||
|     handleAddPen(batch) { | ||||
|       this.currentPen = { pig_batch_id: batch.id }; // 预设猪栏所属批次 | ||||
|       this.isEditPen = false; | ||||
|       this.penDialogVisible = true; | ||||
|     }, | ||||
|     handleEditPen(pen) { | ||||
|     handleModifyPigCountPen(pen) { | ||||
|       this.currentPen = { ...pen }; | ||||
|       this.isEditPen = true; | ||||
|       this.penDialogVisible = true; | ||||
|     }, | ||||
|     async handleDeletePen(pen) { | ||||
|     async handleRemovePen(pen) { | ||||
|       try { | ||||
|         await this.$confirm(`确认删除猪栏 "${pen.pen_number}" 吗?`, '提示', { | ||||
|           confirmButtonText: '确定', | ||||
| @@ -253,6 +257,16 @@ export default { | ||||
|           this.$message.success('猪栏添加成功'); | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     async handleAssignPenToBatch({ batchId, penId }) { | ||||
|       try { | ||||
|         await assignPensToBatch(batchId, { penIds: [penId] }); | ||||
|         this.$message.success('猪栏分配成功'); | ||||
|         await this.loadData(); // Refresh data to show assigned pen | ||||
|       } catch (error) { | ||||
|         this.$message.error('分配猪栏失败: ' + (error.response?.data?.message || error.message || '未知错误')); | ||||
|         console.error('Failed to assign pen to batch:', error); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,9 @@ | ||||
|           <div class="title-container"> | ||||
|             <h2 class="page-title">栏舍管理</h2> | ||||
|             <el-button type="text" @click="loadData" class="refresh-btn" title="刷新列表"> | ||||
|               <el-icon :size="20"><Refresh /></el-icon> | ||||
|               <el-icon :size="20"> | ||||
|                 <Refresh/> | ||||
|               </el-icon> | ||||
|             </el-button> | ||||
|           </div> | ||||
|           <el-button type="primary" @click="handleAddHouse">添加猪舍</el-button> | ||||
| @@ -15,66 +17,67 @@ | ||||
|  | ||||
|       <!-- 加载状态 --> | ||||
|       <div v-if="loading" class="loading"> | ||||
|         <el-skeleton animated /> | ||||
|         <el-skeleton animated/> | ||||
|       </div> | ||||
|  | ||||
|       <!-- 错误状态 --> | ||||
|       <div v-else-if="error" class="error"> | ||||
|         <el-alert | ||||
|           title="获取栏舍数据失败" | ||||
|           :description="error" | ||||
|           type="error" | ||||
|           show-icon | ||||
|           closable | ||||
|           @close="error = null" | ||||
|             title="获取栏舍数据失败" | ||||
|             :description="error" | ||||
|             type="error" | ||||
|             show-icon | ||||
|             closable | ||||
|             @close="error = null" | ||||
|         /> | ||||
|         <el-button type="primary" @click="loadData" class="retry-btn">重新加载</el-button> | ||||
|       </div> | ||||
|  | ||||
|       <!-- 数据展示或空状态 --> | ||||
|       <div v-else> | ||||
|         <PigHouseList  | ||||
|           v-if="pigHousesData.length > 0"  | ||||
|           :pigHouses="pigHousesData"  | ||||
|           @edit-house="handleEditHouse"  | ||||
|           @delete-house="handleDeleteHouse"  | ||||
|           @add-pen="handleAddPen" | ||||
|           @edit-pen="handleEditPen" | ||||
|           @delete-pen="handleDeletePen" | ||||
|         <PigHouseList | ||||
|             v-if="pigHousesData.length > 0" | ||||
|             :pigHouses="pigHousesData" | ||||
|             @edit-house="handleEditHouse" | ||||
|             @delete-house="handleDeleteHouse" | ||||
|             @add-pen="handleAddPen" | ||||
|             @edit-pen="handleEditPen" | ||||
|             @delete-pen="handleDeletePen" | ||||
|             @toggle-house-expand="handleToggleHouseExpand" | ||||
|         /> | ||||
|         <el-empty v-else description="暂无数据" /> | ||||
|         <el-empty v-else description="暂无数据"/> | ||||
|       </div> | ||||
|  | ||||
|     </el-card> | ||||
|  | ||||
|     <!-- 猪舍表单对话框 --> | ||||
|     <PigHouseForm | ||||
|       v-model:visible="houseDialogVisible" | ||||
|       :house-data="currentHouse" | ||||
|       :is-edit="isEditHouse" | ||||
|       @success="handleHouseSuccess" | ||||
|       @cancel="houseDialogVisible = false" | ||||
|         v-model:visible="houseDialogVisible" | ||||
|         :house-data="currentHouse" | ||||
|         :is-edit="isEditHouse" | ||||
|         @success="handleHouseSuccess" | ||||
|         @cancel="houseDialogVisible = false" | ||||
|     /> | ||||
|  | ||||
|     <!-- 猪栏表单对话框 --> | ||||
|     <PenForm  | ||||
|       v-model:visible="penDialogVisible" | ||||
|       :pen-data="currentPen" | ||||
|       :is-edit="isEditPen" | ||||
|       @success="handlePenSuccess" | ||||
|       @cancel="penDialogVisible = false" | ||||
|     <PenForm | ||||
|         v-model:visible="penDialogVisible" | ||||
|         :pen-data="currentPen" | ||||
|         :is-edit="isEditPen" | ||||
|         @success="handlePenSuccess" | ||||
|         @cancel="penDialogVisible = false" | ||||
|     /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { getPigHouses, deletePigHouse } from '@/api/pigHouse.js'; | ||||
| import { getPens, deletePen } from '@/api/pen.js'; | ||||
| import { getPigBatches } from '@/api/pigBatch.js'; | ||||
| import {getPigHouses, deletePigHouse} from '@/api/pigHouse.js'; | ||||
| import {getPens, deletePen} from '@/api/pen.js'; | ||||
| import {getPigBatches} from '@/api/pigBatch.js'; | ||||
| import PigHouseList from '@/components/PigHouseList.vue'; | ||||
| import PigHouseForm from '@/components/PigHouseForm.vue'; | ||||
| import PenForm from '@/components/PenForm.vue'; | ||||
| import { Refresh } from '@element-plus/icons-vue'; | ||||
| import {Refresh} from '@element-plus/icons-vue'; | ||||
|  | ||||
| export default { | ||||
|   name: 'PigFarmManagementView', | ||||
| @@ -114,7 +117,7 @@ export default { | ||||
|           getPens(), | ||||
|           getPigBatches() | ||||
|         ]); | ||||
|          | ||||
|  | ||||
|         const houses = Array.isArray(pigHousesResponse.data) ? pigHousesResponse.data : []; | ||||
|         const pens = Array.isArray(pensResponse.data) ? pensResponse.data : []; | ||||
|         const batches = Array.isArray(batchesResponse.data) ? batchesResponse.data : []; | ||||
| @@ -136,9 +139,9 @@ export default { | ||||
|       houses.forEach(house => { | ||||
|         // 确保保留 isExpanded 状态 | ||||
|         const existingHouse = this.pigHousesData.find(h => h.id === house.id); | ||||
|         houseMap.set(house.id, { ...house, pens: [], isExpanded: existingHouse ? existingHouse.isExpanded : false }); | ||||
|         houseMap.set(house.id, {...house, pens: [], isExpanded: existingHouse ? existingHouse.isExpanded : false}); | ||||
|       }); | ||||
|        | ||||
|  | ||||
|       for (const pen of pens) { | ||||
|         if (houseMap.has(pen.house_id)) { | ||||
|           const penWithBatch = { | ||||
| @@ -157,7 +160,7 @@ export default { | ||||
|       this.houseDialogVisible = true; | ||||
|     }, | ||||
|     handleEditHouse(house) { | ||||
|       this.currentHouse = { ...house }; | ||||
|       this.currentHouse = {...house}; | ||||
|       this.isEditHouse = true; | ||||
|       this.houseDialogVisible = true; | ||||
|     }, | ||||
| @@ -187,23 +190,23 @@ export default { | ||||
|         if (index !== -1) { | ||||
|           // 保留 pens 和 isExpanded 状态 | ||||
|           const existingHouse = this.pigHousesData[index]; | ||||
|           this.pigHousesData[index] = { ...newHouseData, pens: existingHouse.pens, isExpanded: existingHouse.isExpanded }; | ||||
|           this.pigHousesData[index] = {...newHouseData, pens: existingHouse.pens, isExpanded: existingHouse.isExpanded}; | ||||
|         } | ||||
|         this.$message.success('猪舍更新成功'); | ||||
|       } else { | ||||
|         // 添加新猪舍 | ||||
|         this.pigHousesData.push({ ...newHouseData, pens: [], isExpanded: false }); | ||||
|         this.pigHousesData.push({...newHouseData, pens: [], isExpanded: false}); | ||||
|         this.$message.success('猪舍添加成功'); | ||||
|       } | ||||
|     }, | ||||
|     // --- 猪栏操作 --- | ||||
|     handleAddPen(house) { | ||||
|       this.currentPen = { house_id: house.id }; | ||||
|       this.currentPen = {house_id: house.id}; | ||||
|       this.isEditPen = false; | ||||
|       this.penDialogVisible = true; | ||||
|     }, | ||||
|     handleEditPen(pen) { | ||||
|       this.currentPen = { ...pen }; | ||||
|       this.currentPen = {...pen}; | ||||
|       this.isEditPen = true; | ||||
|       this.penDialogVisible = true; | ||||
|     }, | ||||
| @@ -251,6 +254,12 @@ export default { | ||||
|           this.$message.success('猪栏添加成功'); | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     handleToggleHouseExpand(houseId) { | ||||
|       const house = this.pigHousesData.find(h => h.id === houseId); | ||||
|       if (house) { | ||||
|         house.isExpanded = !house.isExpanded; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -312,6 +321,7 @@ export default { | ||||
|   .pig-farm-management { | ||||
|     padding: 10px; | ||||
|   } | ||||
|  | ||||
|   .card-header { | ||||
|     flex-direction: column; | ||||
|     gap: 15px; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user