331 lines
9.2 KiB
Vue
331 lines
9.2 KiB
Vue
<template>
|
||
<div class="pig-farm-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="handleAddHouse">添加猪舍</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>
|
||
<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="暂无数据"/>
|
||
</div>
|
||
|
||
</el-card>
|
||
|
||
<!-- 猪舍表单对话框 -->
|
||
<PigHouseForm
|
||
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"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
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';
|
||
|
||
export default {
|
||
name: 'PigFarmManagementView',
|
||
components: {
|
||
PigHouseList,
|
||
PigHouseForm,
|
||
PenForm,
|
||
Refresh
|
||
},
|
||
data() {
|
||
return {
|
||
pigHousesData: [],
|
||
loading: false,
|
||
error: null,
|
||
// 猪舍表单状态
|
||
houseDialogVisible: false,
|
||
isEditHouse: false,
|
||
currentHouse: {},
|
||
// 猪栏表单状态
|
||
penDialogVisible: false,
|
||
isEditPen: false,
|
||
currentPen: {},
|
||
// 批次映射,用于本地组装猪栏的批次名称
|
||
batchMap: new Map(),
|
||
};
|
||
},
|
||
async mounted() {
|
||
await this.loadData();
|
||
},
|
||
methods: {
|
||
async loadData() {
|
||
this.loading = true;
|
||
this.error = null;
|
||
try {
|
||
const [pigHousesResponse, pensResponse, batchesResponse] = await Promise.all([
|
||
getPigHouses(),
|
||
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 : [];
|
||
|
||
// 更新 batchMap
|
||
this.batchMap = new Map(batches.map(batch => [batch.id, batch.batch_number]));
|
||
|
||
this.pigHousesData = this.assembleData(houses, pens, batches);
|
||
} catch (err) {
|
||
this.error = err.message || '无法获取数据';
|
||
console.error('Failed to fetch pig farm data:', err);
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
assembleData(houses, pens) {
|
||
// 此时 houses 和 pens 已确保是数组,batches 已经更新到 this.batchMap
|
||
const houseMap = new Map();
|
||
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});
|
||
});
|
||
|
||
for (const pen of pens) {
|
||
if (houseMap.has(pen.house_id)) {
|
||
const penWithBatch = {
|
||
...pen,
|
||
batch_number: this.batchMap.get(pen.pig_batch_id) || null
|
||
};
|
||
houseMap.get(pen.house_id).pens.push(penWithBatch);
|
||
}
|
||
}
|
||
return Array.from(houseMap.values());
|
||
},
|
||
// --- 猪舍操作 ---
|
||
handleAddHouse() {
|
||
this.currentHouse = {};
|
||
this.isEditHouse = false;
|
||
this.houseDialogVisible = true;
|
||
},
|
||
handleEditHouse(house) {
|
||
this.currentHouse = {...house};
|
||
this.isEditHouse = true;
|
||
this.houseDialogVisible = true;
|
||
},
|
||
async handleDeleteHouse(house) {
|
||
try {
|
||
await this.$confirm(`确认删除猪舍 "${house.name}" 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
});
|
||
await deletePigHouse(house.id);
|
||
this.$message.success('删除成功');
|
||
// 本地更新数据,不重新加载全部
|
||
this.pigHousesData = this.pigHousesData.filter(h => h.id !== house.id);
|
||
} catch (err) {
|
||
if (err !== 'cancel') {
|
||
this.$message.error('删除失败: ' + (err.message || '未知错误'));
|
||
console.error('Failed to delete pig house:', err);
|
||
}
|
||
}
|
||
},
|
||
handleHouseSuccess(newHouseData) {
|
||
this.houseDialogVisible = false;
|
||
if (this.isEditHouse) {
|
||
// 更新现有猪舍
|
||
const index = this.pigHousesData.findIndex(h => h.id === newHouseData.id);
|
||
if (index !== -1) {
|
||
// 保留 pens 和 isExpanded 状态
|
||
const existingHouse = this.pigHousesData[index];
|
||
this.pigHousesData[index] = {...newHouseData, pens: existingHouse.pens, isExpanded: existingHouse.isExpanded};
|
||
}
|
||
this.$message.success('猪舍更新成功');
|
||
} else {
|
||
// 添加新猪舍
|
||
this.pigHousesData.push({...newHouseData, pens: [], isExpanded: false});
|
||
this.$message.success('猪舍添加成功');
|
||
}
|
||
},
|
||
// --- 猪栏操作 ---
|
||
handleAddPen(house) {
|
||
this.currentPen = {house_id: house.id};
|
||
this.isEditPen = false;
|
||
this.penDialogVisible = true;
|
||
},
|
||
handleEditPen(pen) {
|
||
this.currentPen = {...pen};
|
||
this.isEditPen = true;
|
||
this.penDialogVisible = true;
|
||
},
|
||
async handleDeletePen(pen) {
|
||
try {
|
||
await this.$confirm(`确认删除猪栏 "${pen.pen_number}" 吗?`, '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
});
|
||
await deletePen(pen.id);
|
||
this.$message.success('删除成功');
|
||
// 本地更新数据,不重新加载全部
|
||
const house = this.pigHousesData.find(h => h.id === pen.house_id);
|
||
if (house) {
|
||
house.pens = house.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;
|
||
// 为新猪栏数据添加 batch_number
|
||
const penWithBatch = {
|
||
...newPenData,
|
||
batch_number: this.batchMap.get(newPenData.pig_batch_id) || null
|
||
};
|
||
|
||
const house = this.pigHousesData.find(h => h.id === penWithBatch.house_id);
|
||
if (house) {
|
||
if (this.isEditPen) {
|
||
// 更新现有猪栏
|
||
const index = house.pens.findIndex(p => p.id === penWithBatch.id);
|
||
if (index !== -1) {
|
||
house.pens[index] = penWithBatch;
|
||
}
|
||
this.$message.success('猪栏更新成功');
|
||
} else {
|
||
// 添加新猪栏
|
||
house.pens.push(penWithBatch);
|
||
this.$message.success('猪栏添加成功');
|
||
}
|
||
}
|
||
},
|
||
handleToggleHouseExpand(houseId) {
|
||
const house = this.pigHousesData.find(h => h.id === houseId);
|
||
if (house) {
|
||
house.isExpanded = !house.isExpanded;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.pig-farm-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-farm-management {
|
||
padding: 10px;
|
||
}
|
||
|
||
.card-header {
|
||
flex-direction: column;
|
||
gap: 15px;
|
||
}
|
||
}
|
||
</style>
|