338 lines
10 KiB
Vue
338 lines
10 KiB
Vue
<template>
|
|
<div class="pig-batch-management">
|
|
<el-card>
|
|
<template #header>
|
|
<div class="card-header">
|
|
<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-button>
|
|
</div>
|
|
<el-button type="primary" @click="handleAddBatch">添加猪群</el-button>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- 加载状态 -->
|
|
<div v-if="loading" class="loading">
|
|
<el-skeleton animated />
|
|
</div>
|
|
|
|
<!-- 错误状态 -->
|
|
<div v-else-if="error" class="error">
|
|
<el-alert
|
|
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>
|
|
<PigBatchList
|
|
v-if="pigBatchesData.length > 0"
|
|
:pigBatches="pigBatchesData"
|
|
@edit-batch="handleEditBatch"
|
|
@delete-batch="handleDeleteBatch"
|
|
@add-pen="handleAddPen"
|
|
@modify-pig-count-pen="handleModifyPigCountPen"
|
|
@remove-pen="handleRemovePen"
|
|
@assign-pen-to-batch="handleAssignPenToBatch"
|
|
/>
|
|
<el-empty v-else description="暂无数据" />
|
|
</div>
|
|
|
|
</el-card>
|
|
|
|
<!-- 猪群表单对话框 -->
|
|
<PigBatchForm
|
|
v-model:visible="batchDialogVisible"
|
|
:batch-data="currentBatch"
|
|
:is-edit="isEditBatch"
|
|
@success="handleBatchSuccess"
|
|
@cancel="batchDialogVisible = false"
|
|
/>
|
|
|
|
<!-- 猪栏表单对话框 (用于在猪群管理中添加/编辑猪栏) -->
|
|
<PenForm
|
|
v-model:visible="penDialogVisible"
|
|
:pen-data="currentPen"
|
|
:is-edit="isEditPen"
|
|
@success="handlePenSuccess"
|
|
@cancel="penDialogVisible = false"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
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';
|
|
import { Refresh } from '@element-plus/icons-vue';
|
|
|
|
export default {
|
|
name: 'PigBatchManagementView',
|
|
components: {
|
|
PigBatchList,
|
|
PigBatchForm,
|
|
PenForm,
|
|
Refresh
|
|
},
|
|
data() {
|
|
return {
|
|
pigBatchesData: [],
|
|
loading: false,
|
|
error: null,
|
|
// 猪群表单状态
|
|
batchDialogVisible: false,
|
|
isEditBatch: false,
|
|
currentBatch: {},
|
|
// 猪栏表单状态
|
|
penDialogVisible: false,
|
|
isEditPen: false,
|
|
currentPen: {},
|
|
// 辅助映射
|
|
houseMap: new Map(), // 用于猪栏显示猪舍名称
|
|
};
|
|
},
|
|
async mounted() {
|
|
await this.loadData();
|
|
},
|
|
methods: {
|
|
async loadData() {
|
|
this.loading = true;
|
|
this.error = null;
|
|
try {
|
|
const [batchesResponse, pensResponse, housesResponse] = await Promise.all([
|
|
getPigBatches(),
|
|
getPens(),
|
|
getPigHouses(),
|
|
]);
|
|
|
|
const batches = Array.isArray(batchesResponse.data) ? batchesResponse.data : [];
|
|
const pens = Array.isArray(pensResponse.data) ? pensResponse.data : [];
|
|
const houses = Array.isArray(housesResponse.data) ? housesResponse.data : [];
|
|
|
|
// 更新 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) {
|
|
this.error = err.message || '无法获取数据';
|
|
console.error('Failed to fetch pig batch data:', err);
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
assembleData(batches, pens) {
|
|
const batchMap = new Map();
|
|
batches.forEach(batch => {
|
|
const existingBatch = this.pigBatchesData.find(b => b.id === batch.id);
|
|
batchMap.set(batch.id, { ...batch, pens: [], isExpanded: existingBatch ? existingBatch.isExpanded : false });
|
|
});
|
|
|
|
for (const pen of pens) {
|
|
if (pen.pig_batch_id && batchMap.has(pen.pig_batch_id)) {
|
|
const penWithDetails = {
|
|
...pen,
|
|
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);
|
|
}
|
|
}
|
|
// 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() {
|
|
this.currentBatch = {};
|
|
this.isEditBatch = false;
|
|
this.batchDialogVisible = true;
|
|
},
|
|
handleEditBatch(batch) {
|
|
this.currentBatch = { ...batch };
|
|
this.isEditBatch = true;
|
|
this.batchDialogVisible = true;
|
|
},
|
|
async handleDeleteBatch(batch) {
|
|
try {
|
|
await this.$confirm(`确认删除猪群 "${batch.batch_number}" 吗?`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
});
|
|
await deletePigBatch(batch.id);
|
|
this.$message.success('删除成功');
|
|
// 本地更新数据
|
|
this.pigBatchesData = this.pigBatchesData.filter(b => b.id !== batch.id);
|
|
} catch (err) {
|
|
if (err !== 'cancel') {
|
|
this.$message.error('删除失败: ' + (err.message || '未知错误'));
|
|
console.error('Failed to delete pig batch:', err);
|
|
}
|
|
}
|
|
},
|
|
handleBatchSuccess(newBatchData) {
|
|
this.batchDialogVisible = false;
|
|
// 为新批次数据添加 pens 和 isExpanded 状态
|
|
const processedBatchData = { ...newBatchData, pens: [], isExpanded: false };
|
|
|
|
if (this.isEditBatch) {
|
|
// 更新现有猪群
|
|
const index = this.pigBatchesData.findIndex(b => b.id === processedBatchData.id);
|
|
if (index !== -1) {
|
|
// 保留 pens 和 isExpanded 状态
|
|
const existingBatch = this.pigBatchesData[index];
|
|
this.pigBatchesData[index] = { ...processedBatchData, pens: existingBatch.pens, isExpanded: existingBatch.isExpanded };
|
|
}
|
|
this.$message.success('猪群更新成功');
|
|
} else {
|
|
// 添加新猪群
|
|
this.pigBatchesData.push(processedBatchData);
|
|
this.$message.success('猪群添加成功');
|
|
}
|
|
},
|
|
// --- 猪栏操作 (在猪群管理中) ---
|
|
handleModifyPigCountPen(pen) {
|
|
this.currentPen = { ...pen };
|
|
this.isEditPen = true;
|
|
this.penDialogVisible = true;
|
|
},
|
|
async handleRemovePen(pen) {
|
|
try {
|
|
await this.$confirm(`确认删除猪栏 "${pen.pen_number}" 吗?`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
});
|
|
await deletePen(pen.id);
|
|
this.$message.success('删除成功');
|
|
// 本地更新数据
|
|
const batch = this.pigBatchesData.find(b => b.id === pen.pig_batch_id);
|
|
if (batch) {
|
|
batch.pens = batch.pens.filter(p => p.id !== pen.id);
|
|
}
|
|
} catch (err) {
|
|
if (err !== 'cancel') {
|
|
this.$message.error('删除失败: ' + (err.message || '未知错误'));
|
|
console.error('Failed to delete pen:', err);
|
|
}
|
|
}
|
|
},
|
|
handlePenSuccess(newPenData) {
|
|
this.penDialogVisible = false;
|
|
// 为新猪栏数据添加 house_name 和 batch_number
|
|
const penWithDetails = {
|
|
...newPenData,
|
|
house_name: this.houseMap.get(newPenData.house_id) || '未知猪舍',
|
|
batch_number: this.pigBatchesData.find(b => b.id === newPenData.pig_batch_id)?.batch_number || null
|
|
};
|
|
|
|
const batch = this.pigBatchesData.find(b => b.id === penWithDetails.pig_batch_id);
|
|
if (batch) {
|
|
if (this.isEditPen) {
|
|
// 更新现有猪栏
|
|
const index = batch.pens.findIndex(p => p.id === penWithDetails.id);
|
|
if (index !== -1) {
|
|
batch.pens[index] = penWithDetails;
|
|
}
|
|
this.$message.success('猪栏更新成功');
|
|
} else {
|
|
// 添加新猪栏
|
|
batch.pens.push(penWithDetails);
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 样式与 PigFarmManagementView 保持一致 */
|
|
.pig-batch-management {
|
|
padding: 20px;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 15px 0;
|
|
}
|
|
|
|
.title-container {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.page-title {
|
|
margin: 0;
|
|
font-size: 1.5rem;
|
|
font-weight: bold;
|
|
line-height: 1;
|
|
}
|
|
|
|
.refresh-btn {
|
|
color: black;
|
|
background-color: transparent;
|
|
padding: 0;
|
|
width: 24px;
|
|
height: 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: none;
|
|
}
|
|
|
|
.loading {
|
|
padding: 20px 0;
|
|
}
|
|
|
|
.error {
|
|
padding: 20px 0;
|
|
text-align: center;
|
|
}
|
|
|
|
.retry-btn {
|
|
margin-top: 15px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.pig-batch-management {
|
|
padding: 10px;
|
|
}
|
|
.card-header {
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
}
|
|
</style>
|