HashMap e7a0c1d274 feat(views) 饲喂量统计
添加了饲喂量统计功能
完善了其他两个页面的若干逻辑错误
2025-08-24 23:36:58 +08:00

620 lines
22 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="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="配方编号" prop="formulaId">
<el-input v-model="queryParams.formulaId" placeholder="请输入配方编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="配方批号" prop="formulaBatchId">
<el-input v-model="queryParams.formulaBatchId" placeholder="请输入配方批号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd"
v-hasPermi="['feed:FeedStatistic:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['feed:FeedStatistic:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['feed:FeedStatistic:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['feed:FeedStatistic:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="FeedStatisticList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="UUID" align="center" prop="id" />
<el-table-column label="配方编号" align="center" prop="formulaId" />
<el-table-column label="配方批号" align="center" prop="formulaBatchId" />
<el-table-column label="羊只数量" align="center" prop="sheepFoldCount" />
<!-- <el-table-column label="青贮损耗比例" align="center" prop="silageLossRate" /> -->
<el-table-column label="总饲喂量" align="center" prop="feedTotalSize" />
<el-table-column label="日均饲喂量" align="center" prop="feedDailySize" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleMaterialView(scope.row)"
v-hasPermi="['feed:FeedStatistic:edit']">查看</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['feed:FeedStatistic:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 弹框:详情/修改 -->
<el-dialog :title="title" v-model="open" width="60%" append-to-body
v-if="openModel === 'viewMaterial' || openModel === 'add'">
<div>
<el-form ref="FeedStatisticRef" :model="showFeedStatistic" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12" v-if="true">
<el-form-item label="UUID" prop="id">
<el-input v-model="showFeedStatistic.id" :disabled="true" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="true">
<el-form-item label="配方编码" prop="formulaId">
<!-- <el-input v-model="form.formulaId" placeholder="请输入配方编码" /> -->
<el-select v-model="showFeedStatistic.formulaId" filterable placeholder="请选择配方编码" style="width: 100%"
@change="handleFormulaIdChange(showFeedStatistic, $event)" :disabled="isEdit">
<el-option v-for="item in formulaIdDict" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="批号" prop="batchId">
<!-- <el-input v-model="form.batchId" placeholder="请输入批号" /> -->
<el-select v-model="showFeedStatistic.formulaBatchId" filterable placeholder="请选择配方批号"
style="width: 100%" :disabled="isEdit"
@change="handleFormulaBatchIdChange(showFeedStatistic, $event)">
<el-option v-for="item in formulaBatchDict" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="羊只数量" prop="feedStage">
<el-input v-model="showFeedStatistic.sheepFoldCount" placeholder="请输入饲养阶段" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="日期" prop="planDate">
<el-date-picker clearable v-model="showFeedStatistic.feedDate" type="date" value-format="YYYY-MM-DD"
placeholder="请选择时间">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">配方列表</el-divider>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" icon="Plus" @click="handleAddMaterial()">添加</el-button>
</el-col>
</el-row>
<el-table :data="showFeedStatistic.materialList" :rules="rules" :row-class-name="rowSgFormulaListDetailIndex"
@selection-change="handleSgFormulaListDetailSelectionChange" ref="swPresDetail" border stripe>
<el-table-column label="序号" align="center" prop="index" width="60" />
<el-table-column label="原料" prop="materialId" align="center">
<el-table-column label="名称" align="center">
<template #default="scope">
<el-select v-model="scope.row.materialId" filterable placeholder="请选择原料" style="width: 100%"
@change="handleMaterialChange(scope.row, $event)">
<el-option-group v-for="group in groupedMaterials" :key="group.label" :label="group.label">
<el-option v-for="item in group.options" :key="item.value" :label="item.label"
:value="item.value" />
</el-option-group>
</el-select>
</template>
</el-table-column>
<el-table-column label="类型" align="center" prop="isGranular">
<template #default="scope">
<dict-tag :options="material_type" :value="scope.row.isGranular" />
</template>
</el-table-column>
</el-table-column>
<el-table-column label="总量" prop="feedSize" align="center">
<template #default="scope">
<el-input-number v-model="scope.row.feedSize" placeholder="请输入饲喂总量" :min="0" :precision="1"
controls-position="right" />
</template>
</el-table-column>
<el-table-column label="类型" prop="isSupplement" align="center">
<template #default="scope">
<el-select v-model="scope.row.isSupplement" placeholder="请选择类型">
<el-option v-for="item in materialType" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Delete" @click="deleteFormulaListDetail(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-divider content-position="left">羊舍列表</el-divider>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" icon="Plus" @click="handleAddSheep()">添加</el-button>
</el-col>
<el-table :data="showFeedStatistic.sheepFoldList" :rules="rules"
:row-class-name="rowSgFormulaListDetailIndex" @selection-change="handleSgFormulaListDetailSelectionChange"
ref="swPresDetail" border stripe>
<el-table-column label="ID" prop="id" align="center" />
<!-- <el-input v-model="form.sheepHouseId" placeholder="请输入羊舍" /> -->
<el-table-column label="名称" align="center" prop="sheepfoldName">
<template #default="scope">
<el-select v-model="scope.row.id" filterable placeholder="请选择羊舍" style="width: 100%">
<el-option v-for="item in sheepFolderDict" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Delete" @click="deleteSheepItem(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-form>
</div>
<!-- 底部按钮仅修改页显示 -->
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel"> </el-button>
<el-button type="primary" @click="submitFormDetil"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="FeedStatistic">
import { listFeedStatistic, getFeedStatistic, delFeedStatistic, addFeedStatistic, updateFeedStatistic, initFeedStatistic } from "@/api/feed/FeedStatistic"
import { listFormulaManagement } from "@/api/feed/FormulaManagement"
import { listSheepfold } from "@/api/produce/manage_sheep/trans_group.js";
import { listMaterial } from "@/api/feed/Material"
import { ref } from "vue";
const { proxy } = getCurrentInstance()
const FeedStatisticList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
formulaId: null,
formulaBatchId: null,
silageLossRate: null,
},
rules: {
formulaId: [
{ required: true, message: "配方编号不能为空", trigger: "blur" }
],
formulaBatchId: [
{ required: true, message: "配方批号不能为空", trigger: "blur" }
],
}
})
const { queryParams, form, rules } = toRefs(data)
// 打开类型
const openModel = ref('')
// 编辑状态
const isEdit = ref(true)
const showFeedStatistic = ref({})
// 用于存储羊舍名称的字典
const sheepNameDict = ref({})
const sheepFolderDict = ref([]) // 羊舍字典
const formulaIdDict = ref([]) // 配方编码字典
const formulaBatchMap = ref([]) // 配方批号映射包含配方ID
const formulaBatchDict = ref([]) // 配方批号字典(过滤后)
// 原料类型字典
const { material_type } = proxy.useDict('material_type')
// 原料类型
const materialType = [
{ value: '1', label: '补饲原料' },
{ value: '0', label: '原料' }
]
// 原料下拉列表
const materials = ref([])
// 原料列表查询参数
const materialQueryParams = ref({
materialId: null,
materialName: null,
isGranular: null
})
function getMaterials() {
listMaterial(materialQueryParams).then(response => {
console.log("获取原料列表:", response)
materials.value = response.rows.map(item => ({
value: item.materialId,
label: item.materialName,
isGranular: item.isGranular,
isSupplement: "0" // 默认补饲原料为 0
}))
// console.log("原料列表:", materials.value)
})
}
/** ================== 分组下拉列表部分 ======================== */
const groupedMaterials = ref([]) // 存储分组后的原料数据
// 从后端获取数据并按isGranular分组
function getGroupMaterials() {
listMaterial(materialQueryParams).then(response => {
console.log("获取原料列表:", response)
// 根据material_type分组数据
const groups = material_type.value.map(type => ({
label: type.label,
options: []
}))
// 遍历原料数据根据isGranular字段分组
response.rows.forEach(item => {
const group = groups.find(group => group.label === material_type.value.find(type => type.value === item.isGranular).label)
group.options.push({
value: item.materialId,
label: item.materialName
})
})
// 将分组后的数据赋值给groupedMaterials
groupedMaterials.value = groups
console.log("分组后的原料列表:", groupedMaterials.value)
})
}
// 根据id获取羊舍名称
function getSheepHouseName(id) {
const dictItem = sheepFolderDict.value.find(item => item.value === id)
return dictItem ? dictItem.label : id
}
// 羊舍ID与名称转换函数输入可以是 ID 或 羊舍名称
function getSheepHouseId(inputValue, sheepNameDict) {
if (!inputValue) return '';
// 输入是纯数字,直接返回
if (/^\d+$/.test(inputValue)) {
return inputValue;
}
// 输入是名称,返回对应的 id
const match = sheepNameDict.find(item => item.value === inputValue);
return match ? match.label : '';
}
/** ================== 配方字典 & 批号字典 ======================== */
// 获取配方编码 & 配方批号 字典
function getFormulaDict() {
listFormulaManagement().then(response => {
formulaIdDict.value = response.rows.map(item => ({
label: item.formulaId,
value: item.formulaId
}))
// 清空配方批号字典
formulaBatchMap.value = []
// 遍历每个配方列表,提取子配方中的批号
response.rows.forEach(item => {
if (item.subFormulaList) {
item.subFormulaList.forEach(subItem => {
formulaBatchMap.value.push({
label: subItem.batchId,
value: subItem.batchId,
formulaId: item.formulaId // 关联配方ID
})
})
}
})
})
}
// 处理配方编码变化
function handleFormulaIdChange(row, value) {
// 清空配方批号字典
if (!value) {
formulaBatchDict.value = []
} else {
// 根据选择的formulaId筛选batchId
formulaBatchDict.value = formulaBatchMap.value;
formulaBatchDict.value = formulaBatchDict.value.filter(item => item.formulaId === value)
}
// 重新设置批号为第一个
if (formulaBatchDict.value.length > 0) {
row.formulaBatchId = formulaBatchDict.value[0].value;
}
handleFormulaBatchIdChange(row, value);
}
// 处理配方批号变化 & 当确定批号时加载初始数据
function handleFormulaBatchIdChange(row, $event) {
if (row.formulaId && row.formulaBatchId) {
queryParams.value.formulaId = row.formulaId
queryParams.value.formulaBatchId = row.formulaBatchId
queryParams.value.id = null // 清空 ID防止影响查询
// console.log("加载初始数据,查询参数:", queryParams.value)
initFeedStatistic(queryParams.value).then(response => {
Object.assign(showFeedStatistic.value, response.rows[0] || {})
total.value = response.total
loading.value = false
})
}
}
// 查看详情
function handleMaterialView(row) {
showFeedStatistic.value = row
// 反序列化
// showFeedStatistic.value.materialList = JSON.parse(showFeedStatistic.value.materialList || "[]");
// showFeedStatistic.value.sheepFoldList = JSON.parse(showFeedStatistic.value.sheepFoldList || "[]");
queryParams.value.id = row.id
listFeedStatistic(queryParams.value).then(response => {
FeedStatisticList.value = response.rows
total.value = response.total
loading.value = false
})
open.value = true
title.value = "饲喂量统计详情"
isEdit.value = true
openModel.value = 'viewMaterial'
}
function getSheepfoldDict() {
listSheepfold().then(response => {
sheepFolderDict.value = response.rows.map(item => ({
label: item.sheepfoldName,
value: item.id
}))
sheepNameDict.value = response.rows.map(item => ({
label: item.id,
value: item.sheepfoldName
}))
})
}
// 添加原料列表项
function handleAddMaterial() {
showFeedStatistic.value.materialList.push({
materialId: null,
materialName: null,
ratio: null,
isGranular: "0",
isSupplement: "0"
})
}
// 删除原料列表项
function deleteFormulaListDetail(row) {
const index = showFeedStatistic.value.materialList.findIndex(item => item.materialId === row.materialId)
if (index !== -1) {
showFeedStatistic.value.materialList.splice(index, 1)
}
}
// 添加羊舍列表项
function handleAddSheep() {
showFeedStatistic.value.sheepFoldList.push({
id: null,
sheepfoldName: null
})
}
// 删除羊舍列表项
function deleteSheepItem(row) {
const index = showFeedStatistic.value.sheepFoldList.findIndex(item => item.id === row.id)
if (index !== -1) {
showFeedStatistic.value.sheepFoldList.splice(index, 1)
}
}
// 原料下拉选择变化时,更新对应的原料名称
function handleMaterialChange(row, selectedValue) {
const selectedItem = this.materials.find(item => item.value === selectedValue);
if (selectedItem) {
// materialName 也在 row 中
row.materialName = selectedItem.label;
row.isGranular = selectedItem.isGranular; // 更新 isGranular
row.isSupplement = selectedItem.isSupplement; // 更新 isSupplement
}
}
/** 查询饲喂量统计列表 */
function getList() {
loading.value = true
listFeedStatistic(queryParams.value).then(response => {
FeedStatisticList.value = response.rows
total.value = response.total
loading.value = false
})
}
// 取消按钮
function cancel() {
open.value = false
reset()
}
// 表单重置
function reset() {
isEdit.value = true
showFeedStatistic.value = {
id: null,
formulaId: null,
formulaBatchId: null,
sheepFoldCount: null,
silageLossRate: null,
feedTotalSize: null,
feedDailySize: null,
materialList: null,
sheepFoldList: null
}
queryParams.value = {
pageNum: 1,
pageSize: 10,
formulaId: null,
formulaBatchId: null,
silageLossRate: null,
}
proxy.resetForm("FeedStatisticRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef")
handleQuery()
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id)
single.value = selection.length != 1
multiple.value = !selection.length
}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
openModel.value = 'add'
isEdit.value = false
title.value = "添加饲喂量统计"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
getFeedStatistic(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改饲喂量统计"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["FeedStatisticRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateFeedStatistic(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addFeedStatistic(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
function submitFormDetil() {
proxy.$refs["FeedStatisticRef"].validate(valid => {
if (valid) {
if (showFeedStatistic.value.id != null) {
updateFeedStatistic(showFeedStatistic.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
reset()
getList()
})
} else {
addFeedStatistic(showFeedStatistic.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
reset()
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除饲喂量统计编号为"' + _ids + '"的数据项?').then(function () {
return delFeedStatistic(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => { })
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('feed/FeedStatistic/export', {
...queryParams.value
}, `FeedStatistic_${new Date().getTime()}.xlsx`)
}
/**
* 子表行序号计算
* 通过 el-table 的 row-class-name 钩子给每一行写入 index从 1 开始)
*/
function rowSgFormulaListDetailIndex({ row, rowIndex }) {
row.index = rowIndex + 1
}
/**
* 子表多选回调
* 记录被选中的行序号数组
*/
function handleSgFormulaListDetailSelectionChange(selection) {
checkedSwPresDetail.value = selection.map(item => item.index)
}
getList()
getSheepfoldDict()
// 加载原料列表
getMaterials()
// 加载分组原料列表
getGroupMaterials()
// 获取羊舍字典
getSheepfoldDict()
// 获取配方字典
getFormulaDict()
</script>