Files
pig-farm-controller-fe/src/views/pms/PigFarmManagementView.vue
2025-10-23 13:21:27 +08:00

331 lines
9.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>