Merge remote-tracking branch 'origin/main'

This commit is contained in:
zyk 2025-08-06 15:37:55 +08:00
commit 1fe616abf0
38 changed files with 6020 additions and 1458 deletions

View File

@ -31,7 +31,7 @@
"nprogress": "0.2.0",
"pinia": "2.1.7",
"splitpanes": "3.1.5",
"vue": "3.4.31",
"vue": "^3.4.31",
"vue-cropper": "1.1.1",
"vue-router": "4.4.0",
"vuedraggable": "4.1.0",

View File

@ -0,0 +1,33 @@
import request from '@/utils/request'
export function getList(params) {
return request({
url: '/milkInOutStore/list',
method: 'get',
params
})
}
export function importExcel(file) {
const data = new FormData()
data.append('file', file)
return request({
url: '/milkInOutStore/import',
method: 'post',
data,
headers: { 'Content-Type': 'multipart/form-data' }
})
}
export function exportExcel(params) {
return request({
url: '/milkInOutStore/export',
method: 'post',
params,
responseType: 'blob'
})
}
export function getColumns() {
return request({ url: '/milkInOutStore/columns', method: 'get' })
}

View File

@ -0,0 +1,33 @@
import request from '@/utils/request'
export function listMilkProdclasses(query) {
return request({
url: '/milkProdclasses/milkProdclasses/list',
method: 'get',
params: query
})
}
export function importMilkProdclasses(data) {
return request({
url: '/milkProdclasses/milkProdclasses/import',
method: 'post',
data: data,
headers: { 'Content-Type': 'multipart/form-data' }
})
}
export function exportMilkProdclasses(query) {
return request({
url: '/milkProdclasses/milkProdclasses/export',
method: 'post',
responseType: 'blob',
params: query
})
}
export function getRanchList() {
return request({
url: '/system/ranch/list',
method: 'get'
})
}

View File

@ -43,4 +43,14 @@
// })
// }
// 可以保留空文件或删除此文件
// 因为前端不再需要调用后端API
// 因为前端不再需要调用后端API
import request from '@/utils/request'
// 查询胎次校正列表
export function listParityCorrection(query) {
return request({
url: '/parityCorrection/parityCorrection/listAll',
method: 'get',
params: query
})
}

View File

@ -0,0 +1,8 @@
import request from '@/utils/request'
export function getRanchList() {
return request({
url: '/dairyProducts/ranch/list',
method: 'get'
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询羊奶出入库列表
export function listMilkInOutStore(query) {
return request({
url: '/milkInOutStore/milkInOutStore/list',
method: 'get',
params: query
})
}
// 查询羊奶出入库详细
export function getMilkInOutStore(id) {
return request({
url: '/milkInOutStore/milkInOutStore/' + id,
method: 'get'
})
}
// 新增羊奶出入库
export function addMilkInOutStore(data) {
return request({
url: '/milkInOutStore/milkInOutStore',
method: 'post',
data: data
})
}
// 修改羊奶出入库
export function updateMilkInOutStore(data) {
return request({
url: '/milkInOutStore/milkInOutStore',
method: 'put',
data: data
})
}
// 删除羊奶出入库
export function delMilkInOutStore(id) {
return request({
url: '/milkInOutStore/milkInOutStore/' + id,
method: 'delete'
})
}

View File

@ -25,3 +25,25 @@ export function delSheep_file(id) {
method: 'delete'
})
}
// 在群总数
export const getInGroupCount = () =>
request({ url: '/sheep_file/sheep_file/stat/inGroupCount', method: 'get' })
export function getSheepTypeStat() {
return request({ url: '/sheep_file/sheep_file/stat/sheepType', method: 'get' })
}
export function getBreedStatusStat() {
return request({ url: '/sheep_file/sheep_file/stat/breedStatus', method: 'get' })
}
export function getVarietyStat() {
return request({ url: '/sheep_file/sheep_file/stat/variety', method: 'get' })
}
export function getLactationParityStat() {
return request({ url: '/sheep_file/sheep_file/stat/lactationParity', method: 'get' })
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询体尺测量列表
export function listBody_measure(query) {
return request({
url: '/body_measure/body_measure/list',
method: 'get',
params: query
})
}
// 查询体尺测量详细
export function getBody_measure(id) {
return request({
url: '/body_measure/body_measure/' + id,
method: 'get'
})
}
// 新增体尺测量
export function addBody_measure(data) {
return request({
url: '/body_measure/body_measure',
method: 'post',
data: data
})
}
// 修改体尺测量
export function updateBody_measure(data) {
return request({
url: '/body_measure/body_measure',
method: 'put',
data: data
})
}
// 删除体尺测量
export function delBody_measure(id) {
return request({
url: '/body_measure/body_measure/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询体况评分列表
export function listBody_score(query) {
return request({
url: '/body_score/body_score/list',
method: 'get',
params: query
})
}
// 查询体况评分详细
export function getBody_score(id) {
return request({
url: '/body_score/body_score/' + id,
method: 'get'
})
}
// 新增体况评分
export function addBody_score(data) {
return request({
url: '/body_score/body_score',
method: 'post',
data: data
})
}
// 修改体况评分
export function updateBody_score(data) {
return request({
url: '/body_score/body_score',
method: 'put',
data: data
})
}
// 删除体况评分
export function delBody_score(id) {
return request({
url: '/body_score/body_score/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询乳房评分列表
export function listBreast_rating(query) {
return request({
url: '/breast_rating/breast_rating/list',
method: 'get',
params: query
})
}
// 查询乳房评分详细
export function getBreast_rating(id) {
return request({
url: '/breast_rating/breast_rating/' + id,
method: 'get'
})
}
// 新增乳房评分
export function addBreast_rating(data) {
return request({
url: '/breast_rating/breast_rating',
method: 'post',
data: data
})
}
// 修改乳房评分
export function updateBreast_rating(data) {
return request({
url: '/breast_rating/breast_rating',
method: 'put',
data: data
})
}
// 删除乳房评分
export function delBreast_rating(id) {
return request({
url: '/breast_rating/breast_rating/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询改备注列表
export function listChangeComment(query) {
return request({
url: '/changeComment/changeComment/list',
method: 'get',
params: query
})
}
// 查询改备注详细
export function getChangeComment(id) {
return request({
url: '/changeComment/changeComment/' + id,
method: 'get'
})
}
// 新增改备注
export function addChangeComment(data) {
return request({
url: '/changeComment/changeComment',
method: 'post',
data: data
})
}
// 修改改备注
export function updateChangeComment(data) {
return request({
url: '/changeComment/changeComment',
method: 'put',
data: data
})
}
// 删除改备注
export function delChangeComment(id) {
return request({
url: '/changeComment/changeComment/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,71 @@
import request from '@/utils/request'
// 查询修改电子耳号记录列表
export function listChangeEar(query) {
return request({
url: '/changeEar/changeEar/list',
method: 'get',
params: query
})
}
// 查询修改电子耳号记录详细
export function getChangeEar(id) {
return request({
url: '/changeEar/changeEar/' + id,
method: 'get'
})
}
// 新增修改电子耳号记录
export function addChangeEar(data) {
return request({
url: '/changeEar/changeEar',
method: 'post',
data: data
})
}
// 修改修改电子耳号记录
export function updateChangeEar(data) {
return request({
url: '/changeEar/changeEar',
method: 'put',
data: data
})
}
// 删除修改电子耳号记录
export function delChangeEar(id) {
return request({
url: '/changeEar/changeEar/' + id,
method: 'delete'
})
}
// 根据羊只ID查询基本信息
export function getSheepById(id) {
return request({
url: '/sheep/sheep/' + id,
method: 'get'
});
}
//根据耳号(管理耳号或电子耳号)查询羊只信息
export function getSheepByEarNumber(earNumber, earType) {
return request({
url: '/sheep/sheep/byEarNumber',
method: 'get',
params: { earNumber, earType }
});
}
//校验新管理/电子耳号
export function checkTagExists(tag, earType) {
return request({
url: '/sheep/sheep/existsByTag',
method: 'get',
params: { tag, earType }
});
}

View File

@ -0,0 +1,52 @@
import request from '@/utils/request'
// 查询改品种记录列表
export function listChangeVariety(query) {
return request({
url: '/changeVariety/changeVariety/list',
method: 'get',
params: query
})
}
// 查询改品种记录详细
export function getChangeVariety(id) {
return request({
url: '/changeVariety/changeVariety/' + id,
method: 'get'
})
}
// 新增改品种记录
export function addChangeVariety(data) {
return request({
url: '/changeVariety/changeVariety',
method: 'post',
data: data
})
}
// 修改改品种记录
export function updateChangeVariety(data) {
return request({
url: '/changeVariety/changeVariety',
method: 'put',
data: data
})
}
// 删除改品种记录
export function delChangeVariety(id) {
return request({
url: '/changeVariety/changeVariety/' + id,
method: 'delete'
})
}
//通过管理耳号获取羊只信息
export function getSheepByManageTags(manageTags) {
return request({
url: `/sheep/sheep/byManageTags/${manageTags}`,
method: 'get'
});
}

View File

@ -51,3 +51,21 @@ export function listSheepfold() {
});
}
//审批转群记录
export function approveScTransGroup(data) {
return request({
url: '/produce/manage_sheep/trans_group/approve',
method: 'put',
data
})
}
// 获取所有牧场列表
export function listRanch() {
return request({
url: '/ranch/ranch/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 }
});
}

View File

@ -9,6 +9,23 @@ export function listTransition_info(query) {
})
}
// 查询牧场列表(用于下拉框)
export function listRanch() {
return request({
url: '/ranch/ranch/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 }
});
}
// 查询指定牧场下的所有羊只耳号
export function getSheepByRanchId(ranchId) {
return request({
url: `/ranch/ranch/getSheepByRanchId/${ranchId}`,
method: 'get'
});
}
// 查询转场详细
export function getTransition_info(id) {
return request({
@ -17,15 +34,15 @@ export function getTransition_info(id) {
})
}
// 新增转场
export function addTransition_info(data) {
return request({
url: 'produce/manage_sheep/transition_info',
url: '/produce/manage_sheep/transition_info/batch',
method: 'post',
data: data
data: data
})
}
// 修改转场
export function updateTransition_info(data) {
return request({
@ -42,3 +59,14 @@ export function delTransition_info(id) {
method: 'delete'
})
}
/**
* 审批转场记录
*/
export function approveTransitionInfo(data) {
return request({
url: '/produce/manage_sheep/transition_info/approve',
method: 'put',
data
})
}

View File

@ -45,7 +45,7 @@ export function exportFixHoof(query) {
url: '/produce/other/fixHoof/export',
method: 'post',
params: query,
responseType: 'blob' // 导出功能需要设置响应类型为blob
responseType: 'blob'
})
}
@ -70,7 +70,7 @@ export function getVarietyOptions(query){
//通过羊舍获取羊只
export function getSheepBySheepfoldId(id) {
return request({
url: `/sheepfold_management/sheepfold_management/getSheepById`, // 使用你已有的接口路径
url: `/sheepfold_management/sheepfold_management/getSheepById`,
method: 'get',
params:{ id: String(id) }
})

View File

@ -50,3 +50,6 @@ export function delData(dictCode) {
method: 'delete'
})
}
// 兼容旧写法
export { getDicts as listDictDataByType }

View File

@ -3,7 +3,7 @@ import request from '@/utils/request'
// 查询羊只品种列表
export function listVariety(query) {
return request({
url: '/variety/variety/list',
url: '/base/variety/list',
method: 'get',
params: query
})
@ -12,7 +12,7 @@ export function listVariety(query) {
// 查询羊只品种详细
export function getVariety(id) {
return request({
url: '/variety/variety/' + id,
url: '/base/variety/' + id,
method: 'get'
})
}
@ -20,7 +20,7 @@ export function getVariety(id) {
// 新增羊只品种
export function addVariety(data) {
return request({
url: '/variety/variety',
url: '/base/variety',
method: 'post',
data: data
})
@ -29,7 +29,7 @@ export function addVariety(data) {
// 修改羊只品种
export function updateVariety(data) {
return request({
url: '/variety/variety',
url: '/base/variety',
method: 'put',
data: data
})
@ -38,7 +38,7 @@ export function updateVariety(data) {
// 删除羊只品种
export function delVariety(id) {
return request({
url: '/variety/variety/' + id,
url: '/base/variety/' + id,
method: 'delete'
})
}

View File

@ -1,31 +1,16 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="羊只id" prop="sheepId">
<el-input
v-model="queryParams.sheepId"
placeholder="请输入羊只id"
clearable
@keyup.enter="handleQuery"
/>
<!-- 1. 搜索 -->
<el-form :model="queryParams" ref="queryRef" inline v-show="showSearch" label-width="68px">
<el-form-item label="羊只耳号" prop="sheepNo">
<el-input v-model="queryParams.sheepNo" placeholder="请输入羊只耳号" clearable @keyup.enter="getList" />
</el-form-item>
<el-form-item label="驱虫日期" style="width: 308px">
<el-date-picker
v-model="daterangeDatetime"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-form-item label="驱虫日期">
<el-date-picker v-model="daterangeDatetime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item label="技术员" prop="technical">
<el-input
v-model="queryParams.technical"
placeholder="请输入技术员"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.technical" placeholder="请输入技术员" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@ -33,277 +18,518 @@
</el-form-item>
</el-form>
<!-- 2. 按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['biosafety:deworm:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['biosafety:deworm:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['biosafety:deworm:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['biosafety:deworm:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
<el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-row>
<!-- 3. 列表 -->
<el-table v-loading="loading" :data="dewormList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="${comment}" align="center" prop="id" />
<el-table-column label="羊只id" align="center" prop="sheepId" />
<el-table-column label="药品使用记录" align="center" prop="usageId" />
<el-table-column label="羊只耳号" align="center" prop="sheepNo" />
<el-table-column label="品种" align="center" prop="variety" />
<el-table-column label="羊只类别" align="center" prop="sheepType" />
<el-table-column label="性别" align="center" prop="gender" />
<el-table-column label="性别" align="center" prop="gender">
<template #default="scope">
<dict-tag :options="sheep_gender" :value="scope.row.gender" />
</template>
</el-table-column>
<el-table-column label="月龄" align="center" prop="monthAge" />
<el-table-column label="胎次" align="center" prop="parity" />
<el-table-column label="繁殖状态" align="center" prop="breed" />
<el-table-column label="驱虫日期" align="center" prop="datetime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
<template #default="scope">{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</template>
</el-table-column>
<el-table-column label="技术员" align="center" prop="technical" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" width="200">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['biosafety:deworm:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['biosafety:deworm:remove']">删除</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">删除</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="500px" append-to-body>
<el-form ref="dewormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 4. 新增弹窗羊舍多选 + 无卡片 + 自动剔除 -->
<el-dialog title="新增驱虫记录" v-model="addOpen" width="60%" top="5vh" append-to-body>
<el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<!-- 耳号追加 -->
<el-form-item label="耳号">
<el-input v-model="sheepInput" placeholder="输入耳号回车添加" style="width: 220px" @keyup.enter="validateSheep" />
</el-form-item>
</el-col>
<el-col :span="12">
<!-- 羊舍多选 -->
<el-form-item label="羊舍" prop="barnIds">
<el-select v-model="selectedBarnIds" multiple collapse-tags placeholder="请选择羊舍" style="width: 100%"
@change="handleBarnChange">
<el-option v-for="b in barns" :key="b.id" :label="b.sheepfoldName" :value="b.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 已选耳号 -->
<el-form-item label="已选耳号">
<el-tag v-for="(tag, idx) in selectedSheepList" :key="tag.sheepId" closable @close="removeSheep(idx)"
style="margin-right: 6px">
{{ tag.sheepNo }}
</el-tag>
</el-form-item>
<el-form-item label="药品使用记录" prop="usageId">
<el-input v-model="form.usageId" placeholder="请输入药品使用记录" />
</el-form-item>
<el-form-item label="品种" prop="variety">
<el-input v-model="form.variety" placeholder="请输入品种" />
</el-form-item>
<el-form-item label="性别" prop="gender">
<el-input v-model="form.gender" placeholder="请输入性别" />
</el-form-item>
<el-form-item label="月龄" prop="monthAge">
<el-input v-model="form.monthAge" placeholder="请输入月龄" />
</el-form-item>
<el-form-item label="胎次" prop="parity">
<el-input v-model="form.parity" placeholder="请输入胎次" />
</el-form-item>
<el-form-item label="驱虫日期" prop="datetime">
<el-date-picker clearable
v-model="form.datetime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择驱虫日期">
</el-date-picker>
</el-form-item>
<el-form-item label="技术员" prop="technical">
<el-input v-model="form.technical" placeholder="请输入技术员" />
</el-form-item>
<el-form-item label="备注" prop="comment">
<el-input v-model="form.comment" placeholder="请输入备注" />
<!-- 驱虫信息 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="驱虫日期" prop="datetime">
<el-date-picker v-model="addForm.datetime" type="date" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="处方">
<el-select v-model="addForm.prescriptionId" filterable clearable placeholder="请选择处方" style="width: 100%"
@change="handleSelectPrescription">
<el-option v-for="p in presOptions" :key="p.id" :label="p.label" :value="p.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="addForm.technical" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<div style="margin: 8px 5px;">
<!-- 药品明细 -->
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetail">添加药品</el-button>
<el-table :data="usageDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" />
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="usageDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</div>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="addForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
<el-button @click="addOpen = false"> </el-button>
<el-button type="primary" @click="submitAddForm"> </el-button>
</template>
</el-dialog>
<!-- 5. 修改弹窗羊舍只读下拉 -->
<el-dialog title="修改驱虫记录" v-model="editOpen" width="60%" top="5vh" append-to-body>
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="羊只耳号">
<span>{{ editForm.sheepNo }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="品种">
<span>{{ editForm.variety }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="羊只类别">
<span>{{ editForm.sheepType }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别">
<span> <dict-tag :options="sheep_gender" :value="editForm.gender" /></span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="繁殖状态">
<span>{{ editForm.breed }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="驱虫日期" prop="datetime">
<el-date-picker v-model="editForm.datetime" type="date" style="width: 100%" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="editForm.technical" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<div style="margin: 10px 10px;">
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetail">添加药品</el-button>
<el-table :data="usageDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" style="width: 120px;"/>
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value+''" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value+''" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="usageDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</div>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="editForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editOpen = false"> </el-button>
<el-button type="primary" @click="submitEditForm"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script setup name="Deworm">
import { listDeworm, getDeworm, delDeworm, addDeworm, updateDeworm } from "@/api/biosafety/deworm"
<script setup name="Deworm">
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { listDeworm, getDeworm, delDeworm, addDeworm, updateDeworm } from '@/api/biosafety/deworm'
import { listPrescription, getPrescription } from '@/api/biosafety/prescription'
import { listUnit } from '@/api/biosafety/unit'
import { listUsage } from '@/api/biosafety/usage'
import { listMedicine } from '@/api/biosafety/medicine'
import request from '@/utils/request'
import { parseTime } from '@/utils/ruoyi'
const { proxy } = getCurrentInstance()
const { proxy } = getCurrentInstance()
const { sheep_gender } = proxy.useDict('sheep_gender')
const dewormList = 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 daterangeDatetime = ref([])
/* ------------------ 列表 ------------------ */
const loading = ref(true)
const showSearch = ref(true)
const total = ref(0)
const dewormList = ref([])
const daterangeDatetime = ref([])
const data = reactive({
form: {},
queryParams: {
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sheepId: null,
datetime: null,
technical: null,
},
rules: {
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询驱虫列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
if (null != daterangeDatetime && '' != daterangeDatetime) {
queryParams.value.params["beginDatetime"] = daterangeDatetime.value[0]
queryParams.value.params["endDatetime"] = daterangeDatetime.value[1]
}
listDeworm(queryParams.value).then(response => {
dewormList.value = response.rows
total.value = response.total
loading.value = false
sheepNo: null,
technical: null
})
}
//
function cancel() {
open.value = false
reset()
}
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
//
function reset() {
form.value = {
id: null,
sheepId: null,
usageId: null,
variety: null,
sheepType: null,
gender: null,
monthAge: null,
parity: null,
datetime: null,
technical: null,
comment: null,
updateBy: null,
updateTime: null,
createBy: null,
createTime: null
function getList() {
loading.value = true
const qp = { ...queryParams }
qp.params = {}
if (daterangeDatetime.value?.length) {
qp.params.beginDatetime = daterangeDatetime.value[0]
qp.params.endDatetime = daterangeDatetime.value[1]
}
listDeworm(qp).then(res => {
dewormList.value = res.rows
total.value = res.total
loading.value = false
})
}
proxy.resetForm("dewormRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id)
single.value = selection.length !== 1
multiple.value = !selection.length
}
/** 重置按钮操作 */
function resetQuery() {
daterangeDatetime.value = []
proxy.resetForm("queryRef")
handleQuery()
}
function handleQuery() {
queryParams.pageNum = 1
getList()
}
function resetQuery() {
daterangeDatetime.value = []
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
title.value = "添加驱虫"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
getDeworm(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改驱虫"
/* ------------------ 新增 ------------------ */
const addOpen = ref(false)
const addForm = reactive({
datetime: new Date(),
technical: '',
comment: '',
prescriptionId: null
})
}
const addRules = {
datetime: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
const selectedBarnIds = ref([])
const selectedSheepList = ref([])
const barns = ref([])
const sheepInput = ref('')
/** 提交按钮 */
function submitForm() {
proxy.$refs["dewormRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateDeworm(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
function getBarns() {
request({ url: '/sheepfold_management/sheepfold_management/list', method: 'get' })
.then(res => (barns.value = res.rows))
}
function handleBarnChange(barnIds) {
// 1. id
const currentIds = new Set(barnIds || [])
// 2.
selectedSheepList.value = selectedSheepList.value.filter(
s => currentIds.has(s.barnId)
)
// 3.
const taskArr = [...currentIds].filter(id =>
!selectedSheepList.value.some(s => s.barnId === id)
)
if (!taskArr.length) return
Promise.all(
taskArr.map(id =>
request({ url: `/sheepfold_management/sheepfold_management/getSheepById`, params: { id } })
)
).then(resArr => {
const list = resArr.flatMap(r => (r.data || []).map(s => ({
sheepNo: s.manageTags,
sheepId: s.id,
barnId: s.barnId
})))
const map = new Map(selectedSheepList.value.map(s => [s.sheepId, s]))
list.forEach(item => map.set(item.sheepId, item))
selectedSheepList.value = [...map.values()]
})
}
function validateSheep() {
const no = sheepInput.value.trim()
if (!no) return
if (selectedSheepList.value.some(s => s.sheepNo === no)) {
proxy.$modal.msgWarning('该耳号已存在')
sheepInput.value = ''
return
}
request.get(`/sheep_file/sheep_file/byNo/${no}`).then(res => {
if (!res.data) {
proxy.$modal.msgError('羊只耳号不存在')
} else {
addDeworm(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
selectedSheepList.value.push({
sheepNo: res.data.sheepNo || res.data.bsManageTags,
sheepId: res.data.id
})
}
}
})
}
sheepInput.value = ''
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除驱虫编号为"' + _ids + '"的数据项?').then(function() {
return delDeworm(_ids)
}).then(() => {
function removeSheep(index) {
selectedSheepList.value.splice(index, 1)
}
function handleAdd() {
Object.assign(addForm, {
datetime: new Date(),
technical: '',
comment: '',
prescriptionId: null
})
selectedBarnIds.value = []
selectedSheepList.value = []
usageDetails.value = [{ mediId: null, dosage: 0, unit: null, usageId: null,manufacturer:null,batchNumber:null }]
getBarns()
addOpen.value = true
}
function submitAddForm() {
proxy.$refs.addFormRef.validate(valid => {
if (!valid || !selectedSheepList.value.length) {
proxy.$modal.msgError('请完善表单并至少选择一只羊')
return
}
addDeworm({
...addForm,
datetime: new Date(addForm.datetime).getTime(),
sheepIds: selectedSheepList.value.map(s => s.sheepId),
usageDetails: usageDetails.value
}).then(() => {
proxy.$modal.msgSuccess('新增成功')
addOpen.value = false
getList()
})
})
}
/* ------------------ 修改 ------------------ */
const editOpen = ref(false)
const editForm = reactive({})
const editRules = {
datetime: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
function handleUpdate(row) {
getDeworm(row.id).then(res => {
Object.assign(editForm, res.data)
selectedSheepList.value = [{ sheepNo: res.data.sheepNo, sheepId: res.data.sheepId }]
usageDetails.value = res.data.usageDetails || []
editOpen.value = true
})
}
function submitEditForm() {
proxy.$refs.editFormRef.validate(valid => {
if (!valid) return
updateDeworm({
...editForm,
datetime: new Date(editForm.datetime).getTime(),
usageDetails: usageDetails.value
}).then(() => {
proxy.$modal.msgSuccess('修改成功')
editOpen.value = false
getList()
})
})
}
/* ------------------ 功能函数 ------------------ */
function handleDelete(row) {
const id = row.id || ids.value
proxy.$modal.confirm('确认删除?')
.then(() => delDeworm(id))
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
}
function handleExport() {
proxy.download('biosafety/deworm/export', { ...queryParams }, `deworm_${Date.now()}.xlsx`)
}
/* ------------------ 药品/处方/下拉 ------------------ */
const usageDetails = ref([])
const presOptions = ref([])
const units = ref([])
const usages = ref([])
const medicines = ref([])
function handleSelectPrescription(id) {
if (!id) return
getPrescription(id).then(res => {
usageDetails.value = res.data?.swPresDetailList?.map(i => ({
mediId: i.mediId,
dosage: i.dosage,
unit: i.unitId,
usageId: i.usageId
})) || []
})
}
function handleAddDetail() {
usageDetails.value.push({ mediId: null, dosage: 0, unit: null, usageId: null,manufacturer:null,batchNumber:null })
}
/* ------------------ 初始化 ------------------ */
onMounted(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('biosafety/deworm/export', {
...queryParams.value
}, `deworm_${new Date().getTime()}.xlsx`)
}
getList()
</script>
getBarns()
listPrescription({ status: 1, persType: 1 }).then(res => {
presOptions.value = res.rows.map(item => ({ id: item.id, label: item.name }))
})
listUnit().then(res => {
units.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listUsage().then(res => {
usages.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listMedicine().then(res => {
medicines.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
})
</script>

View File

@ -1,324 +1,516 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="羊舍id" prop="sheepfoldId">
<el-input
v-model="queryParams.sheepfoldId"
placeholder="请输入羊舍id"
clearable
@keyup.enter="handleQuery"
/>
<!-- 搜索栏 -->
<el-form :model="queryParams" ref="queryRef" inline v-show="showSearch" label-width="80px">
<el-form-item label="羊舍" prop="sheepfoldId">
<el-select v-model="queryParams.sheepfoldId" clearable placeholder="请选择羊舍" filterable style="width: 200px">
<el-option v-for="b in barns" :key="b.id" :label="b.sheepfoldName" :value="b.id" />
</el-select>
</el-form-item>
<el-form-item label="消毒日期" prop="datetime">
<el-date-picker clearable
v-model="queryParams.datetime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择消毒日期">
</el-date-picker>
<el-form-item label="消毒日期">
<el-date-picker v-model="daterangeDatetime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-input
v-model="queryParams.technician"
placeholder="请输入技术员"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="消毒方式" prop="way">
<el-input
v-model="queryParams.way"
placeholder="请输入消毒方式"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="药品使用记录id" prop="usageId">
<el-input
v-model="queryParams.usageId"
placeholder="请输入药品使用记录id"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="比例" prop="ratio">
<el-input
v-model="queryParams.ratio"
placeholder="请输入比例"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="备注" prop="comment">
<el-input
v-model="queryParams.comment"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.technician" placeholder="请输入技术员" clearable />
</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="['biosafety:disinfect:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['biosafety:disinfect:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['biosafety:disinfect:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['biosafety:disinfect:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
<el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-row>
<!-- 列表 -->
<el-table v-loading="loading" :data="disinfectList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="id" align="center" prop="id" />
<el-table-column label="羊舍id" align="center" prop="sheepfoldId" />
<el-table-column label="羊舍" align="center" prop="sheepfoldName"/>
<el-table-column label="消毒日期" align="center" prop="datetime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
<template #default="scope">{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</template>
</el-table-column>
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="消毒方式" align="center" prop="way" />
<el-table-column label="药品使用记录id" align="center" prop="usageId" />
<el-table-column label="比例" align="center" prop="ratio" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" width="200">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['biosafety:disinfect:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['biosafety:disinfect:remove']">删除</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">删除</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="500px" append-to-body>
<el-form ref="disinfectRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="羊舍id" prop="sheepfoldId">
<el-input v-model="form.sheepfoldId" placeholder="请输入羊舍id" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- ==================== 新增弹窗 ==================== -->
<el-dialog :title="titleAdd" v-model="openAdd" width="60%" top="5vh" append-to-body>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="羊舍" prop="sheepfoldIds">
<el-select v-model="form.sheepfoldIds" multiple collapse-tags placeholder="请选择羊舍" filterable
style="width: 100%">
<el-option v-for="b in barns" :key="b.id" :label="b.sheepfoldName" :value="b.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="消毒日期" prop="datetime">
<el-date-picker v-model="form.datetime" type="date" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="处方">
<el-select v-model="form.prescriptionId" filterable clearable placeholder="请选择处方"
@change="handleSelectPrescription">
<el-option v-for="p in presOptions" :key="p.id" :label="p.label" :value="p.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="form.technician" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="消毒方式">
<el-input v-model="form.way" placeholder="请输入消毒方式" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="比例">
<el-input v-model="form.ratio" placeholder="请输入比例" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="药品明细">
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetail">添加药品</el-button>
<el-table :data="usageDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" />
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="usageDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="消毒日期" prop="datetime">
<el-date-picker clearable
v-model="form.datetime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择消毒日期">
</el-date-picker>
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-input v-model="form.technician" placeholder="请输入技术员" />
</el-form-item>
<el-form-item label="消毒方式" prop="way">
<el-input v-model="form.way" placeholder="请输入消毒方式" />
</el-form-item>
<el-form-item label="药品使用记录id" prop="usageId">
<el-input v-model="form.usageId" placeholder="请输入药品使用记录id" />
</el-form-item>
<el-form-item label="比例" prop="ratio">
<el-input v-model="form.ratio" placeholder="请输入比例" />
</el-form-item>
<el-form-item label="备注" prop="comment">
<el-input v-model="form.comment" placeholder="请输入备注" />
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="form.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
<el-button @click="cancelAdd"> </el-button>
<el-button type="primary" @click="submitAdd"> </el-button>
</template>
</el-dialog>
<!-- ==================== 修改弹窗 ==================== -->
<el-dialog :title="titleEdit" v-model="openEdit" width="60%" top="5vh" append-to-body>
<el-form ref="editFormRef" :model="editForm" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="羊舍" >
<span>{{ editForm.sheepfoldName }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="消毒日期" prop="datetime">
<el-date-picker v-model="editForm.datetime" type="date" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="editForm.technician" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="消毒方式">
<el-input v-model="editForm.way" placeholder="请输入消毒方式" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="比例">
<el-input v-model="editForm.ratio" placeholder="请输入比例" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="药品明细">
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetailEdit">添加药品</el-button>
<el-table :data="editDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" />
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="editDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="editForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="cancelEdit"> </el-button>
<el-button type="primary" @click="submitEdit"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script setup name="Disinfect">
import { listDisinfect, getDisinfect, delDisinfect, addDisinfect, updateDisinfect } from "@/api/biosafety/disinfect"
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { listDisinfect, getDisinfect, delDisinfect, addDisinfect, updateDisinfect } from '@/api/biosafety/disinfect'
import { listPrescription, getPrescription } from '@/api/biosafety/prescription'
import { listUnit } from '@/api/biosafety/unit'
import { listUsage } from '@/api/biosafety/usage'
import { listMedicine } from '@/api/biosafety/medicine'
import request from '@/utils/request'
import { parseTime } from '@/utils/ruoyi'
const { proxy } = getCurrentInstance()
const disinfectList = ref([])
const open = ref(false)
/* ------------------ 列表 ------------------ */
const loading = ref(true)
const showSearch = ref(true)
const total = ref(0)
const disinfectList = ref([])
const daterangeDatetime = ref([])
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sheepfoldId: null,
technician: null
})
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,
sheepfoldId: null,
datetime: null,
technician: null,
way: null,
usageId: null,
ratio: null,
comment: null,
},
rules: {
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询消毒记录列表 */
function getList() {
loading.value = true
listDisinfect(queryParams.value).then(response => {
disinfectList.value = response.rows
total.value = response.total
const qp = { ...queryParams }
qp.params = {}
if (daterangeDatetime.value?.length) {
qp.params.beginDatetime = daterangeDatetime.value[0]
qp.params.endDatetime = daterangeDatetime.value[1]
}
listDisinfect(qp).then(res => {
disinfectList.value = res.rows
total.value = res.total
loading.value = false
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
sheepfoldId: null,
datetime: null,
technician: null,
way: null,
usageId: null,
ratio: null,
comment: null,
updateBy: null,
updateTime: null,
createBy: null,
createTime: null
}
proxy.resetForm("disinfectRef")
}
/** 搜索按钮操作 */
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
single.value = selection.length !== 1
multiple.value = !selection.length
}
/** 新增按钮操作 */
function handleQuery() {
queryParams.pageNum = 1
getList()
}
function resetQuery() {
daterangeDatetime.value = []
proxy.resetForm('queryRef')
handleQuery()
}
/* ------------------ 新增弹窗 ------------------ */
const openAdd = ref(false)
const titleAdd = ref('新增消毒记录')
const form = reactive({
id: null,
technician: '',
datetime: new Date().toISOString().split('T')[0],
way: '',
ratio: '',
comment: '',
prescriptionId: null,
sheepfoldIds: []
})
const usageDetails = ref([])
function resetAdd() {
Object.assign(form, {
id: null,
technician: '',
datetime: new Date().toISOString().split('T')[0],
way: '',
ratio: '',
comment: '',
prescriptionId: null,
sheepfoldIds: []
})
usageDetails.value = []
}
function handleAdd() {
reset()
open.value = true
title.value = "添加消毒记录"
resetAdd()
openAdd.value = true
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
getDisinfect(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改消毒记录"
})
function cancelAdd() {
openAdd.value = false
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["disinfectRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateDisinfect(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addDisinfect(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
function submitAdd() {
proxy.$refs.formRef.validate(valid => {
if (!valid) return
const data = {
...form,
datetime: new Date(form.datetime).getTime(),
usageDetails: usageDetails.value
}
addDisinfect(data).then(() => {
proxy.$modal.msgSuccess('新增成功')
openAdd.value = false
getList()
})
})
}
/** 删除按钮操作 */
/* ------------------ 修改弹窗 ------------------ */
const openEdit = ref(false)
const titleEdit = ref('修改消毒记录')
const editForm = reactive({
id: null,
technician: '',
datetime: new Date().toISOString().split('T')[0],
way: '',
ratio: '',
comment: '',
prescriptionId: null,
sheepfoldIds: []
})
const editDetails = ref([])
function resetEdit() {
Object.assign(editForm, {
id: null,
technician: '',
datetime: new Date().toISOString().split('T')[0],
way: '',
ratio: '',
comment: '',
prescriptionId: null,
sheepfoldIds: []
})
editDetails.value = []
}
function handleUpdate(row) {
resetEdit()
const id = row.id || ids.value[0]
getDisinfect(id).then(res => {
Object.assign(editForm, res.data)
editDetails.value = res.data.usageDetails || []
openEdit.value = true
})
}
function cancelEdit() {
openEdit.value = false
}
function submitEdit() {
proxy.$refs.editFormRef.validate(valid => {
if (!valid) return
const data = {
...editForm,
datetime: new Date(editForm.datetime).getTime(),
usageDetails: editDetails.value
}
updateDisinfect(data).then(() => {
proxy.$modal.msgSuccess('修改成功')
openEdit.value = false
getList()
})
})
}
/* ------------------ 功能 ------------------ */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除消毒记录编号为"' + _ids + '"的数据项?').then(function() {
return delDisinfect(_ids)
}).then(() => {
proxy.$modal.confirm('是否确认删除选中的数据?').then(() => delDisinfect(_ids)).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
proxy.$modal.msgSuccess('删除成功')
})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('biosafety/disinfect/export', {
...queryParams.value
}, `disinfect_${new Date().getTime()}.xlsx`)
proxy.download('biosafety/disinfect/export', { ...queryParams }, `disinfect_${Date.now()}.xlsx`)
}
getList()
</script>
/* ------------------ 下拉数据 ------------------ */
const barns = ref([])
const presOptions = ref([])
const units = ref([])
const usages = ref([])
const medicines = ref([])
/* 校验规则 */
const rules = {
sheepfoldIds: [{ required: true, message: '请选择羊舍', trigger: 'change' }],
datetime: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
/* 处方选择事件 - 新增 */
function handleSelectPrescription(id) {
if (!id) return
getPrescription(id).then(res => {
usageDetails.value = res.data?.swPresDetailList?.map(i => ({
mediId: i.mediId,
dosage: i.dosage,
unit: i.unitId,
usageId: i.usageId
})) || []
})
}
/* 处方选择事件 - 修改 */
function handleSelectPrescriptionEdit(id) {
if (!id) return
getPrescription(id).then(res => {
editDetails.value = res.data?.swPresDetailList?.map(i => ({
mediId: i.mediId,
dosage: i.dosage,
unit: i.unitId,
usageId: i.usageId
})) || []
})
}
/* 明细添加行 - 新增 */
function handleAddDetail() {
usageDetails.value.push({ mediId: null, dosage: 0, unit: null, usageId: null, manufacturer: null, batchNumber: null })
}
/* 明细添加行 - 修改 */
function handleAddDetailEdit() {
editDetails.value.push({ mediId: null, dosage: 0, unit: null, usageId: null, manufacturer: null, batchNumber: null })
}
/* ------------------ 初始加载 ------------------ */
onMounted(() => {
getList()
/* 加载本地羊舍 */
request({ url: '/sheepfold_management/sheepfold_management/list', method: 'get' }).then(res => {
barns.value = res.rows
})
listPrescription({ status: 1, persType: 1 }).then(res => {
presOptions.value = res.rows.map(item => ({ id: item.id, label: item.name }))
})
listUnit().then(res => {
units.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listUsage().then(res => {
usages.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listMedicine().then(res => {
medicines.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
})
</script>

View File

@ -1,21 +1,16 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="保健日期" prop="datetime">
<el-date-picker clearable
v-model="queryParams.datetime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择保健日期">
</el-date-picker>
<!-- 1. 搜索 -->
<el-form :model="queryParams" ref="queryRef" inline v-show="showSearch" label-width="68px">
<el-form-item label="羊只耳号" prop="sheepNo">
<el-input v-model="queryParams.sheepNo" placeholder="请输入羊只耳号" clearable @keyup.enter="getList" />
</el-form-item>
<el-form-item label="保健日期">
<el-date-picker v-model="daterangeDatetime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item label="技术员" prop="technical">
<el-input
v-model="queryParams.technical"
placeholder="请输入技术员"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.technical" placeholder="请输入技术员" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@ -23,274 +18,518 @@
</el-form-item>
</el-form>
<!-- 2. 按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['biosafety:health:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['biosafety:health:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['biosafety:health:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['biosafety:health:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
<el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-row>
<el-table v-loading="loading" :data="healthList" @selection-change="handleSelectionChange">
<!-- 3. 列表 -->
<el-table v-loading="loading" :data="dewormList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="${comment}" align="center" prop="id" />
<el-table-column label="保健日期" align="center" prop="datetime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="羊只id" align="center" prop="sheepId" />
<el-table-column label="用药记录" align="center" prop="usageId" />
<el-table-column label="羊只耳号" align="center" prop="sheepNo" />
<el-table-column label="品种" align="center" prop="variety" />
<el-table-column label="羊只类别" align="center" prop="sheepType" />
<el-table-column label="性别" align="center" prop="gender" />
<el-table-column label="性别" align="center" prop="gender">
<template #default="scope">
<dict-tag :options="sheep_gender" :value="scope.row.gender" />
</template>
</el-table-column>
<el-table-column label="月龄" align="center" prop="monthAge" />
<el-table-column label="胎次" align="center" prop="parity" />
<el-table-column label="羊舍id" align="center" prop="sheepfoldId" />
<el-table-column label="繁殖状态" align="center" prop="breed" />
<el-table-column label="保健日期" align="center" prop="datetime" width="180">
<template #default="scope">{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</template>
</el-table-column>
<el-table-column label="技术员" align="center" prop="technical" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" width="200">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['biosafety:health:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['biosafety:health:remove']">删除</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">删除</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="500px" append-to-body>
<el-form ref="healthRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="保健日期" prop="datetime">
<el-date-picker clearable
v-model="form.datetime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择保健日期">
</el-date-picker>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 4. 新增弹窗羊舍多选 + 无卡片 + 自动剔除 -->
<el-dialog title="新增保健记录" v-model="addOpen" width="60%" top="5vh" append-to-body>
<el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<!-- 耳号追加 -->
<el-form-item label="耳号">
<el-input v-model="sheepInput" placeholder="输入耳号回车添加" style="width: 220px" @keyup.enter="validateSheep" />
</el-form-item>
</el-col>
<el-col :span="12">
<!-- 羊舍多选 -->
<el-form-item label="羊舍" prop="barnIds">
<el-select v-model="selectedBarnIds" multiple collapse-tags placeholder="请选择羊舍" style="width: 100%"
@change="handleBarnChange">
<el-option v-for="b in barns" :key="b.id" :label="b.sheepfoldName" :value="b.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 已选耳号 -->
<el-form-item label="已选耳号">
<el-tag v-for="(tag, idx) in selectedSheepList" :key="tag.sheepId" closable @close="removeSheep(idx)"
style="margin-right: 6px">
{{ tag.sheepNo }}
</el-tag>
</el-form-item>
<el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item>
<el-form-item label="用药记录" prop="usageId">
<el-input v-model="form.usageId" placeholder="请输入用药记录" />
</el-form-item>
<el-form-item label="品种" prop="variety">
<el-input v-model="form.variety" placeholder="请输入品种" />
</el-form-item>
<el-form-item label="性别" prop="gender">
<el-input v-model="form.gender" placeholder="请输入性别" />
</el-form-item>
<el-form-item label="月龄" prop="monthAge">
<el-input v-model="form.monthAge" placeholder="请输入月龄" />
</el-form-item>
<el-form-item label="胎次" prop="parity">
<el-input v-model="form.parity" placeholder="请输入胎次" />
</el-form-item>
<el-form-item label="羊舍id" prop="sheepfoldId">
<el-input v-model="form.sheepfoldId" placeholder="请输入羊舍id" />
</el-form-item>
<el-form-item label="技术员" prop="technical">
<el-input v-model="form.technical" placeholder="请输入技术员" />
</el-form-item>
<el-form-item label="备注" prop="comment">
<el-input v-model="form.comment" placeholder="请输入备注" />
<!-- 保健信息 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="保健日期" prop="datetime">
<el-date-picker v-model="addForm.datetime" type="date" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="处方">
<el-select v-model="addForm.prescriptionId" filterable clearable placeholder="请选择处方" style="width: 100%"
@change="handleSelectPrescription">
<el-option v-for="p in presOptions" :key="p.id" :label="p.label" :value="p.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="addForm.technical" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<div style="margin: 8px 5px;">
<!-- 药品明细 -->
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetail">添加药品</el-button>
<el-table :data="usageDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" />
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="usageDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</div>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="addForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
<el-button @click="addOpen = false"> </el-button>
<el-button type="primary" @click="submitAddForm"> </el-button>
</template>
</el-dialog>
<!-- 5. 修改弹窗羊舍只读下拉 -->
<el-dialog title="修改保健记录" v-model="editOpen" width="60%" top="5vh" append-to-body>
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="羊只耳号">
<span>{{ editForm.sheepNo }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="品种">
<span>{{ editForm.variety }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="羊只类别">
<span>{{ editForm.sheepType }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别">
<span> <dict-tag :options="sheep_gender" :value="editForm.gender" /></span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="繁殖状态">
<span>{{ editForm.breed }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="保健日期" prop="datetime">
<el-date-picker v-model="editForm.datetime" type="date" style="width: 100%" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="editForm.technical" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<div style="margin: 10px 10px;">
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetail">添加药品</el-button>
<el-table :data="usageDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" style="width: 120px;" />
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value + ''" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value + ''" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="usageDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</div>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="editForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editOpen = false"> </el-button>
<el-button type="primary" @click="submitEditForm"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script setup name="Health">
import { listHealth, getHealth, delHealth, addHealth, updateHealth } from "@/api/biosafety/health"
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { listHealth, getHealth, delHealth, addHealth, updateHealth } from '@/api/biosafety/health'
import { listPrescription, getPrescription } from '@/api/biosafety/prescription'
import { listUnit } from '@/api/biosafety/unit'
import { listUsage } from '@/api/biosafety/usage'
import { listMedicine } from '@/api/biosafety/medicine'
import request from '@/utils/request'
import { parseTime } from '@/utils/ruoyi'
const { proxy } = getCurrentInstance()
const { sheep_gender } = proxy.useDict('sheep_gender')
const healthList = ref([])
const open = ref(false)
/* ------------------ 列表 ------------------ */
const loading = ref(true)
const showSearch = ref(true)
const total = ref(0)
const dewormList = ref([])
const daterangeDatetime = ref([])
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sheepNo: null,
technical: null
})
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,
datetime: null,
technical: null,
},
rules: {
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询保健列表 */
function getList() {
loading.value = true
listHealth(queryParams.value).then(response => {
healthList.value = response.rows
total.value = response.total
const qp = { ...queryParams }
qp.params = {}
if (daterangeDatetime.value?.length) {
qp.params.beginDatetime = daterangeDatetime.value[0]
qp.params.endDatetime = daterangeDatetime.value[1]
}
listHealth(qp).then(res => {
dewormList.value = res.rows
total.value = res.total
loading.value = false
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
datetime: null,
sheepId: null,
usageId: null,
variety: null,
sheepType: null,
gender: null,
monthAge: null,
parity: null,
sheepfoldId: null,
technical: null,
comment: null,
updateBy: null,
updateTime: null,
createBy: null,
createTime: null
}
proxy.resetForm("healthRef")
}
/** 搜索按钮操作 */
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
single.value = selection.length !== 1
multiple.value = !selection.length
}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = "添加保健"
function handleQuery() {
queryParams.pageNum = 1
getList()
}
function resetQuery() {
daterangeDatetime.value = []
proxy.resetForm('queryRef')
handleQuery()
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
getHealth(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改保健"
/* ------------------ 新增 ------------------ */
const addOpen = ref(false)
const addForm = reactive({
datetime: new Date(),
technical: '',
comment: '',
prescriptionId: null
})
const addRules = {
datetime: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
const selectedBarnIds = ref([])
const selectedSheepList = ref([])
const barns = ref([])
const sheepInput = ref('')
function getBarns() {
request({ url: '/sheepfold_management/sheepfold_management/list', method: 'get' })
.then(res => (barns.value = res.rows))
}
function handleBarnChange(barnIds) {
// 1. id
const currentIds = new Set(barnIds || [])
// 2.
selectedSheepList.value = selectedSheepList.value.filter(
s => currentIds.has(s.barnId)
)
// 3.
const taskArr = [...currentIds].filter(id =>
!selectedSheepList.value.some(s => s.barnId === id)
)
if (!taskArr.length) return
Promise.all(
taskArr.map(id =>
request({ url: `/sheepfold_management/sheepfold_management/getSheepById`, params: { id } })
)
).then(resArr => {
const list = resArr.flatMap(r => (r.data || []).map(s => ({
sheepNo: s.manageTags,
sheepId: s.id,
barnId: s.barnId
})))
const map = new Map(selectedSheepList.value.map(s => [s.sheepId, s]))
list.forEach(item => map.set(item.sheepId, item))
selectedSheepList.value = [...map.values()]
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["healthRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateHealth(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addHealth(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
function validateSheep() {
const no = sheepInput.value.trim()
if (!no) return
if (selectedSheepList.value.some(s => s.sheepNo === no)) {
proxy.$modal.msgWarning('该耳号已存在')
sheepInput.value = ''
return
}
request.get(`/sheep_file/sheep_file/byNo/${no}`).then(res => {
if (!res.data) {
proxy.$modal.msgError('羊只耳号不存在')
} else {
selectedSheepList.value.push({
sheepNo: res.data.sheepNo || res.data.bsManageTags,
sheepId: res.data.id
})
}
sheepInput.value = ''
})
}
/** 删除按钮操作 */
function removeSheep(index) {
selectedSheepList.value.splice(index, 1)
}
function handleAdd() {
Object.assign(addForm, {
datetime: new Date(),
technical: '',
comment: '',
prescriptionId: null
})
selectedBarnIds.value = []
selectedSheepList.value = []
usageDetails.value = [{ mediId: null, dosage: 0, unit: null, usageId: null, manufacturer: null, batchNumber: null }]
getBarns()
addOpen.value = true
}
function submitAddForm() {
proxy.$refs.addFormRef.validate(valid => {
if (!valid || !selectedSheepList.value.length) {
proxy.$modal.msgError('请完善表单并至少选择一只羊')
return
}
addHealth({
...addForm,
datetime: new Date(addForm.datetime).getTime(),
sheepIds: selectedSheepList.value.map(s => s.sheepId),
usageDetails: usageDetails.value
}).then(() => {
proxy.$modal.msgSuccess('新增成功')
addOpen.value = false
getList()
})
})
}
/* ------------------ 修改 ------------------ */
const editOpen = ref(false)
const editForm = reactive({})
const editRules = {
datetime: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
function handleUpdate(row) {
getHealth(row.id).then(res => {
Object.assign(editForm, res.data)
selectedSheepList.value = [{ sheepNo: res.data.sheepNo, sheepId: res.data.sheepId }]
usageDetails.value = res.data.usageDetails || []
editOpen.value = true
})
}
function submitEditForm() {
proxy.$refs.editFormRef.validate(valid => {
if (!valid) return
updateHealth({
...editForm,
datetime: new Date(editForm.datetime).getTime(),
usageDetails: usageDetails.value
}).then(() => {
proxy.$modal.msgSuccess('修改成功')
editOpen.value = false
getList()
})
})
}
/* ------------------ 功能函数 ------------------ */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除保健编号为"' + _ids + '"的数据项?').then(function() {
return delHealth(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
const id = row.id || ids.value
proxy.$modal.confirm('确认删除?')
.then(() => delHealth(id))
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('biosafety/health/export', {
...queryParams.value
}, `health_${new Date().getTime()}.xlsx`)
proxy.download('biosafety/deworm/export', { ...queryParams }, `deworm_${Date.now()}.xlsx`)
}
getList()
</script>
/* ------------------ 药品/处方/下拉 ------------------ */
const usageDetails = ref([])
const presOptions = ref([])
const units = ref([])
const usages = ref([])
const medicines = ref([])
function handleSelectPrescription(id) {
if (!id) return
getPrescription(id).then(res => {
usageDetails.value = res.data?.swPresDetailList?.map(i => ({
mediId: i.mediId,
dosage: i.dosage,
unit: i.unitId,
usageId: i.usageId
})) || []
})
}
function handleAddDetail() {
usageDetails.value.push({ mediId: null, dosage: 0, unit: null, usageId: null, manufacturer: null, batchNumber: null })
}
/* ------------------ 初始化 ------------------ */
onMounted(() => {
getList()
getBarns()
listPrescription({ status: 1, persType: 2 }).then(res => {
presOptions.value = res.rows.map(item => ({ id: item.id, label: item.name }))
})
listUnit().then(res => {
units.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listUsage().then(res => {
usages.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listMedicine().then(res => {
medicines.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
})
</script>

View File

@ -1,31 +1,16 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="羊只id" prop="sheepId">
<el-input
v-model="queryParams.sheepId"
placeholder="请输入羊只id"
clearable
@keyup.enter="handleQuery"
/>
<!-- 1. 搜索 -->
<el-form :model="queryParams" ref="queryRef" inline v-show="showSearch" label-width="68px">
<el-form-item label="羊只耳号" prop="sheepNo">
<el-input v-model="queryParams.sheepNo" placeholder="请输入羊只耳号" clearable @keyup.enter="getList" />
</el-form-item>
<el-form-item label="免疫日期" style="width: 308px">
<el-date-picker
v-model="daterangeDatetime"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-form-item label="免疫日期">
<el-date-picker v-model="daterangeDatetime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item label="技术员" prop="technical">
<el-input
v-model="queryParams.technical"
placeholder="请输入技术员"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.technical" placeholder="请输入技术员" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@ -33,280 +18,518 @@
</el-form-item>
</el-form>
<!-- 2. 按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['biosafety:immunity:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['biosafety:immunity:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['biosafety:immunity:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['biosafety:immunity:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
<el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-row>
<el-table v-loading="loading" :data="immunityList" @selection-change="handleSelectionChange">
<!-- 3. 列表 -->
<el-table v-loading="loading" :data="dewormList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="${comment}" align="center" prop="id" />
<el-table-column label="羊只id" align="center" prop="sheepId" />
<el-table-column label="使用记录" align="center" prop="usageId" />
<el-table-column label="羊只耳号" align="center" prop="sheepNo" />
<el-table-column label="品种" align="center" prop="variety" />
<el-table-column label="羊只类型" align="center" prop="sheepType" />
<el-table-column label="羊只性别" align="center" prop="gender" />
<el-table-column label="羊只类别" align="center" prop="sheepType" />
<el-table-column label="性别" align="center" prop="gender">
<template #default="scope">
<dict-tag :options="sheep_gender" :value="scope.row.gender" />
</template>
</el-table-column>
<el-table-column label="月龄" align="center" prop="monthAge" />
<el-table-column label="胎次" align="center" prop="parity" />
<el-table-column label="羊舍id" align="center" prop="sheepfoldId" />
<el-table-column label="繁殖状态" align="center" prop="breed" />
<el-table-column label="免疫日期" align="center" prop="datetime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
<template #default="scope">{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</template>
</el-table-column>
<el-table-column label="技术员" align="center" prop="technical" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" width="200">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['biosafety:immunity:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['biosafety:immunity:remove']">删除</el-button>
<el-button link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">删除</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="500px" append-to-body>
<el-form ref="immunityRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 4. 新增弹窗羊舍多选 + 无卡片 + 自动剔除 -->
<el-dialog title="新增免疫记录" v-model="addOpen" width="60%" top="5vh" append-to-body>
<el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<!-- 耳号追加 -->
<el-form-item label="耳号">
<el-input v-model="sheepInput" placeholder="输入耳号回车添加" style="width: 220px" @keyup.enter="validateSheep" />
</el-form-item>
</el-col>
<el-col :span="12">
<!-- 羊舍多选 -->
<el-form-item label="羊舍" prop="barnIds">
<el-select v-model="selectedBarnIds" multiple collapse-tags placeholder="请选择羊舍" style="width: 100%"
@change="handleBarnChange">
<el-option v-for="b in barns" :key="b.id" :label="b.sheepfoldName" :value="b.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 已选耳号 -->
<el-form-item label="已选耳号">
<el-tag v-for="(tag, idx) in selectedSheepList" :key="tag.sheepId" closable @close="removeSheep(idx)"
style="margin-right: 6px">
{{ tag.sheepNo }}
</el-tag>
</el-form-item>
<el-form-item label="品种" prop="variety">
<el-input v-model="form.variety" placeholder="请输入品种" />
</el-form-item>
<el-form-item label="羊只性别" prop="gender">
<el-input v-model="form.gender" placeholder="请输入羊只性别" />
</el-form-item>
<el-form-item label="月龄" prop="monthAge">
<el-input v-model="form.monthAge" placeholder="请输入月龄" />
</el-form-item>
<el-form-item label="胎次" prop="parity">
<el-input v-model="form.parity" placeholder="请输入胎次" />
</el-form-item>
<el-form-item label="羊舍id" prop="sheepfoldId">
<el-input v-model="form.sheepfoldId" placeholder="请输入羊舍id" />
</el-form-item>
<el-form-item label="免疫日期" prop="datetime">
<el-date-picker clearable
v-model="form.datetime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择免疫日期">
</el-date-picker>
</el-form-item>
<el-form-item label="技术员" prop="technical">
<el-input v-model="form.technical" placeholder="请输入技术员" />
</el-form-item>
<el-form-item label="备注" prop="comment">
<el-input v-model="form.comment" placeholder="请输入备注" />
<!-- 免疫信息 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="免疫日期" prop="datetime">
<el-date-picker v-model="addForm.datetime" type="date" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="处方">
<el-select v-model="addForm.prescriptionId" filterable clearable placeholder="请选择处方" style="width: 100%"
@change="handleSelectPrescription">
<el-option v-for="p in presOptions" :key="p.id" :label="p.label" :value="p.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="addForm.technical" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<div style="margin: 8px 5px;">
<!-- 药品明细 -->
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetail">添加药品</el-button>
<el-table :data="usageDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" />
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="usageDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</div>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="addForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
<el-button @click="addOpen = false"> </el-button>
<el-button type="primary" @click="submitAddForm"> </el-button>
</template>
</el-dialog>
<!-- 5. 修改弹窗羊舍只读下拉 -->
<el-dialog title="修改免疫记录" v-model="editOpen" width="60%" top="5vh" append-to-body>
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="羊只耳号">
<span>{{ editForm.sheepNo }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="品种">
<span>{{ editForm.variety }}</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="羊只类别">
<span>{{ editForm.sheepType }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别">
<span> <dict-tag :options="sheep_gender" :value="editForm.gender" /></span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="繁殖状态">
<span>{{ editForm.breed }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="免疫日期" prop="datetime">
<el-date-picker v-model="editForm.datetime" type="date" style="width: 100%" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员">
<el-input v-model="editForm.technical" placeholder="请输入技术员姓名" />
</el-form-item>
</el-col>
</el-row>
<div style="margin: 10px 10px;">
<el-button type="primary" icon="Plus" size="small" @click="handleAddDetail">添加药品</el-button>
<el-table :data="usageDetails" border stripe style="margin-top: 8px">
<el-table-column label="药品">
<template #default="scope">
<el-select v-model="scope.row.mediId" filterable placeholder="请选择药品">
<el-option v-for="m in medicines" :key="m.value" :label="m.label" :value="m.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用量" width="160">
<template #default="scope">
<el-input-number v-model="scope.row.dosage" :min="0" :precision="1" style="width: 120px;" />
</template>
</el-table-column>
<el-table-column label="单位" width="120">
<template #default="scope">
<el-select v-model="scope.row.unit" placeholder="单位">
<el-option v-for="u in units" :key="u.value" :label="u.label" :value="u.value + ''" />
</el-select>
</template>
</el-table-column>
<el-table-column label="用法" width="120">
<template #default="scope">
<el-select v-model="scope.row.usageId" placeholder="用法">
<el-option v-for="u in usages" :key="u.value" :label="u.label" :value="u.value + ''" />
</el-select>
</template>
</el-table-column>
<el-table-column label="生产厂家">
<template #default="scope">
<el-input v-model="scope.row.manufacturer" placeholder="生产厂家" />
</template>
</el-table-column>
<el-table-column label="生产批号">
<template #default="scope">
<el-input v-model="scope.row.batchNumber" placeholder="批号" />
</template>
</el-table-column>
<el-table-column label="操作" width="60">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="usageDetails.splice(scope.$index, 1)" />
</template>
</el-table-column>
</el-table>
</div>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" v-model="editForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editOpen = false"> </el-button>
<el-button type="primary" @click="submitEditForm"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script setup name="Immunity">
import { listImmunity, getImmunity, delImmunity, addImmunity, updateImmunity } from "@/api/biosafety/immunity"
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { listImmunity, getImmunity, delImmunity, addImmunity, updateImmunity } from '@/api/biosafety/immunity'
import { listPrescription, getPrescription } from '@/api/biosafety/prescription'
import { listUnit } from '@/api/biosafety/unit'
import { listUsage } from '@/api/biosafety/usage'
import { listMedicine } from '@/api/biosafety/medicine'
import request from '@/utils/request'
import { parseTime } from '@/utils/ruoyi'
const { proxy } = getCurrentInstance()
const { sheep_gender } = proxy.useDict('sheep_gender')
const immunityList = ref([])
const open = ref(false)
/* ------------------ 列表 ------------------ */
const loading = ref(true)
const showSearch = ref(true)
const total = ref(0)
const dewormList = ref([])
const daterangeDatetime = ref([])
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sheepNo: null,
technical: null
})
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")
const daterangeDatetime = ref([])
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
sheepId: null,
sheepType: null,
datetime: null,
technical: null,
},
rules: {
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询免疫列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
if (null != daterangeDatetime && '' != daterangeDatetime) {
queryParams.value.params["beginDatetime"] = daterangeDatetime.value[0]
queryParams.value.params["endDatetime"] = daterangeDatetime.value[1]
const qp = { ...queryParams }
qp.params = {}
if (daterangeDatetime.value?.length) {
qp.params.beginDatetime = daterangeDatetime.value[0]
qp.params.endDatetime = daterangeDatetime.value[1]
}
listImmunity(queryParams.value).then(response => {
immunityList.value = response.rows
total.value = response.total
listImmunity(qp).then(res => {
dewormList.value = res.rows
total.value = res.total
loading.value = false
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
sheepId: null,
usageId: null,
variety: null,
sheepType: null,
gender: null,
monthAge: null,
parity: null,
sheepfoldId: null,
datetime: null,
technical: null,
comment: null,
updateBy: null,
updateTime: null,
createBy: null,
createTime: null
}
proxy.resetForm("immunityRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
daterangeDatetime.value = []
proxy.resetForm("queryRef")
handleQuery()
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id)
single.value = selection.length != 1
single.value = selection.length !== 1
multiple.value = !selection.length
}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = "添加免疫"
function handleQuery() {
queryParams.pageNum = 1
getList()
}
function resetQuery() {
daterangeDatetime.value = []
proxy.resetForm('queryRef')
handleQuery()
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
getImmunity(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改免疫"
/* ------------------ 新增 ------------------ */
const addOpen = ref(false)
const addForm = reactive({
datetime: new Date(),
technical: '',
comment: '',
prescriptionId: null
})
const addRules = {
datetime: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
const selectedBarnIds = ref([])
const selectedSheepList = ref([])
const barns = ref([])
const sheepInput = ref('')
function getBarns() {
request({ url: '/sheepfold_management/sheepfold_management/list', method: 'get' })
.then(res => (barns.value = res.rows))
}
function handleBarnChange(barnIds) {
// 1. id
const currentIds = new Set(barnIds || [])
// 2.
selectedSheepList.value = selectedSheepList.value.filter(
s => currentIds.has(s.barnId)
)
// 3.
const taskArr = [...currentIds].filter(id =>
!selectedSheepList.value.some(s => s.barnId === id)
)
if (!taskArr.length) return
Promise.all(
taskArr.map(id =>
request({ url: `/sheepfold_management/sheepfold_management/getSheepById`, params: { id } })
)
).then(resArr => {
const list = resArr.flatMap(r => (r.data || []).map(s => ({
sheepNo: s.manageTags,
sheepId: s.id,
barnId: s.barnId
})))
const map = new Map(selectedSheepList.value.map(s => [s.sheepId, s]))
list.forEach(item => map.set(item.sheepId, item))
selectedSheepList.value = [...map.values()]
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["immunityRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateImmunity(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addImmunity(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
function validateSheep() {
const no = sheepInput.value.trim()
if (!no) return
if (selectedSheepList.value.some(s => s.sheepNo === no)) {
proxy.$modal.msgWarning('该耳号已存在')
sheepInput.value = ''
return
}
request.get(`/sheep_file/sheep_file/byNo/${no}`).then(res => {
if (!res.data) {
proxy.$modal.msgError('羊只耳号不存在')
} else {
selectedSheepList.value.push({
sheepNo: res.data.sheepNo || res.data.bsManageTags,
sheepId: res.data.id
})
}
sheepInput.value = ''
})
}
/** 删除按钮操作 */
function removeSheep(index) {
selectedSheepList.value.splice(index, 1)
}
function handleAdd() {
Object.assign(addForm, {
datetime: new Date(),
technical: '',
comment: '',
prescriptionId: null
})
selectedBarnIds.value = []
selectedSheepList.value = []
usageDetails.value = [{ mediId: null, dosage: 0, unit: null, usageId: null, manufacturer: null, batchNumber: null }]
getBarns()
addOpen.value = true
}
function submitAddForm() {
proxy.$refs.addFormRef.validate(valid => {
if (!valid || !selectedSheepList.value.length) {
proxy.$modal.msgError('请完善表单并至少选择一只羊')
return
}
addImmunity({
...addForm,
datetime: new Date(addForm.datetime).getTime(),
sheepIds: selectedSheepList.value.map(s => s.sheepId),
usageDetails: usageDetails.value
}).then(() => {
proxy.$modal.msgSuccess('新增成功')
addOpen.value = false
getList()
})
})
}
/* ------------------ 修改 ------------------ */
const editOpen = ref(false)
const editForm = reactive({})
const editRules = {
datetime: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
function handleUpdate(row) {
getImmunity(row.id).then(res => {
Object.assign(editForm, res.data)
selectedSheepList.value = [{ sheepNo: res.data.sheepNo, sheepId: res.data.sheepId }]
usageDetails.value = res.data.usageDetails || []
editOpen.value = true
})
}
function submitEditForm() {
proxy.$refs.editFormRef.validate(valid => {
if (!valid) return
updateImmunity({
...editForm,
datetime: new Date(editForm.datetime).getTime(),
usageDetails: usageDetails.value
}).then(() => {
proxy.$modal.msgSuccess('修改成功')
editOpen.value = false
getList()
})
})
}
/* ------------------ 功能函数 ------------------ */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除免疫编号为"' + _ids + '"的数据项?').then(function() {
return delImmunity(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
const id = row.id || ids.value
proxy.$modal.confirm('确认删除?')
.then(() => delImmunity(id))
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('biosafety/immunity/export', {
...queryParams.value
}, `immunity_${new Date().getTime()}.xlsx`)
proxy.download('biosafety/deworm/export', { ...queryParams }, `deworm_${Date.now()}.xlsx`)
}
getList()
</script>
/* ------------------ 药品/处方/下拉 ------------------ */
const usageDetails = ref([])
const presOptions = ref([])
const units = ref([])
const usages = ref([])
const medicines = ref([])
function handleSelectPrescription(id) {
if (!id) return
getPrescription(id).then(res => {
usageDetails.value = res.data?.swPresDetailList?.map(i => ({
mediId: i.mediId,
dosage: i.dosage,
unit: i.unitId,
usageId: i.usageId
})) || []
})
}
function handleAddDetail() {
usageDetails.value.push({ mediId: null, dosage: 0, unit: null, usageId: null, manufacturer: null, batchNumber: null })
}
/* ------------------ 初始化 ------------------ */
onMounted(() => {
getList()
getBarns()
listPrescription({ status: 1, persType: 0 }).then(res => {
presOptions.value = res.rows.map(item => ({ id: item.id, label: item.name }))
})
listUnit().then(res => {
units.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listUsage().then(res => {
usages.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
listMedicine().then(res => {
medicines.value = res.rows.map(item => ({ value: item.id, label: item.name }))
})
})
</script>

View File

@ -0,0 +1,157 @@
<template>
<div>
<el-form :inline="true" :model="queryParams" class="mb-4">
<el-form-item label="开始日期">
<el-date-picker v-model="queryParams.datetimeStart" type="date" value-format="YYYY-MM-DD"/>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker v-model="queryParams.datetimeEnd" type="date" value-format="YYYY-MM-DD"/>
</el-form-item>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</el-form>
<el-row :gutter="10" style="margin-bottom: 16px;">
<el-col :span="24">
<el-upload :before-upload="beforeUpload" :show-file-list="false" style="display: inline-block; margin: 0 8px;">
<el-button type="primary">导入</el-button>
</el-upload>
<el-button type="success" @click="handleExport">导出</el-button>
<el-button @click="openColDialog">列设置</el-button>
</el-col>
</el-row>
<el-dialog v-model="colDialog" title="选择展示列">
<div>
<strong>饲喂来源</strong>
<el-checkbox-group v-model="selectedFeed">
<el-checkbox v-for="f in allCols.feed" :key="f" :label="f">{{ f }}</el-checkbox>
</el-checkbox-group>
</div>
<div style="margin-top:1em">
<strong>销售去向</strong>
<el-checkbox-group v-model="selectedSale">
<el-checkbox v-for="s in allCols.sale" :key="s" :label="s">{{ s }}</el-checkbox>
</el-checkbox-group>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="applyCols">确认</el-button>
<el-button @click="colDialog = false">取消</el-button>
</div>
</template>
</el-dialog>
<el-table :data="rows" border style="margin-top:16px">
<!-- 前面的固定列 -->
<el-table-column prop="datetime" label="日期"/>
<el-table-column prop="num" label="羊数"/>
<el-table-column prop="colostSheep" label="初乳羊"/>
<el-table-column prop="commercialIntake" label="商乳入库"/>
<el-table-column prop="antiIntake" label="抗乳入库"/>
<el-table-column prop="colostIntake" label="初乳入库"/>
<el-table-column prop="intakeTotal" label="入库小计"/>
<el-table-column prop="commercialTest" label="商乳实验用奶"/>
<el-table-column prop="colostTest" label="初乳实验用奶"/>
<el-table-column prop="transferCommercial" label="商乳调拨出库"/>
<el-table-column prop="transferAnti" label="抗乳调拨出库"/>
<el-table-column prop="transferColost" label="初乳调拨出库"/>
<el-table-column prop="transferTotal" label="调拨小计"/>
<el-table-column prop="loss" label="损耗"/>
<!-- 动态饲喂来源列插入到这里 -->
<el-table-column v-for="f in selectedFeed" :key="'feed-'+f" :prop="f" :label="f"/>
<!-- 动态销售去向列 -->
<el-table-column v-for="s in selectedSale" :key="'sale-'+s" :prop="s" :label="s"/>
<!-- 后面的固定列 -->
<el-table-column prop="stockCommercial" label="商乳库存"/>
<el-table-column prop="stockAnti" label="抗乳库存"/>
<el-table-column prop="colost" label="初乳库存"/>
<el-table-column prop="returnFresh" label="爱特退回鲜奶"/>
<el-table-column prop="returnYogurt" label="爱特退回酸奶"/>
</el-table>
<el-pagination
style="margin-top:16px; text-align:right"
:total="total"
v-model:page-size="queryParams.pageSize"
v-model:current-page="queryParams.pageNum"
@current-change="getList">
</el-pagination>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { getList as fetchList, importExcel, exportExcel, getColumns } from '@/api/dairyProducts/milkInOutStore/milkInOutStore.js'
import { ElMessage } from 'element-plus'
const queryParams = reactive({
datetimeStart: null,
datetimeEnd: null,
pageNum: 1,
pageSize: 10
})
const rows = ref([])
const total = ref(0)
const allCols = reactive({ feed: [], sale: [] })
const selectedFeed = ref([])
const selectedSale = ref([])
const colDialog = ref(false)
function getList() {
fetchList(queryParams).then(res => {
rows.value = res.rows
total.value = res.total
})
}
function resetQuery() {
queryParams.datetimeStart = null
queryParams.datetimeEnd = null
queryParams.pageNum = 1
getList()
}
function openColDialog() {
getColumns().then(res => {
const d = res.data[0]
allCols.feed = d.feed || []
allCols.sale = d.sale || []
// /
selectedFeed.value = [...allCols.feed]
selectedSale.value = [...allCols.sale]
colDialog.value = true
})
}
function applyCols() {
colDialog.value = false
getList()
}
function beforeUpload(file) {
importExcel(file).then(() => {
ElMessage.success('导入成功')
getList()
}).catch(err => {
ElMessage.error('导入失败:' + (err.message || err))
})
return false
}
function handleExport() {
exportExcel(queryParams).then(blob => {
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = `milk_in_out_store_${Date.now()}.xlsx`
link.click()
}).catch(err => {
ElMessage.error('导出失败:' + (err.message || err))
})
}
onMounted(() => getList())
</script>

View File

@ -0,0 +1,161 @@
<!-- index.vue (前端视图修改 resetQuery 以匹配正确字段) -->
<template>
<div class="app-container">
<el-form ref="queryRef" :model="queryParams" inline label-width="80px">
<el-form-item label="日期范围">
<el-date-picker v-model="dateRange" type="daterange" range-separator=""
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" />
</el-form-item>
<!-- 管理耳号变成输入框 -->
<el-form-item label="管理耳号">
<el-input v-model="queryParams.manageEarNo" placeholder="请输入管理耳号" clearable />
</el-form-item>
<!-- 厂区下拉框数据源来自字典 da_ranch -->
<el-form-item label="厂区">
<el-select v-model="queryParams.factory" clearable placeholder="请选择">
<el-option
v-for="d in ranchOptions"
:key="d.value"
:label="d.label"
:value="d.value" />
</el-select>
</el-form-item>
<!-- 班次只有 12 -->
<el-form-item label="班次">
<el-select v-model="queryParams.classes" clearable placeholder="请选择">
<el-option :value="1" label="1" />
<el-option :value="2" label="2" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row>
<el-button type="info" plain @click="handleImport" v-hasPermi="['milkProdclasses:milkProdclasses:import']">
<el-icon><Upload /></el-icon> 导入
</el-button>
<el-button type="warning" plain @click="handleExport" v-hasPermi="['milkProdclasses:milkProdclasses:export']">
<el-icon><Download /></el-icon> 导出
</el-button>
</el-row>
<el-table :data="tableData" v-loading="loading">
<el-table-column prop="datetime" label="日期" width="110" />
<el-table-column prop="manageEarNo" label="管理耳号" />
<el-table-column prop="electronicEarNo" label="电子耳号" />
<el-table-column prop="parity" label="胎次" />
<el-table-column prop="factory" label="厂区" />
<el-table-column prop="classes" label="班次" />
<el-table-column prop="milk" label="班次产奶量" />
<el-table-column prop="correctedMilk" label="班次校正奶量" />
</el-table>
<pagination v-show="total>0" :total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList" />
<!-- 导入弹窗 -->
<el-dialog title="Excel导入" v-model="openImport" width="400px">
<el-upload drag :action="uploadUrl" :headers="headers"
accept=".xls,.xlsx" :on-success="uploadSuccess" :on-error="uploadError">
<el-icon class="el-icon--upload"><UploadFilled /></el-icon>
<div>将文件拖到此处或<em>点击上传</em></div>
</el-upload>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { listMilkProdclasses, importMilkProdclasses, exportMilkProdclasses } from '@/api/dairyProducts/milkProdclasses/milkProdclasses'
import { getToken } from '@/utils/auth'
import { getRanchList } from '@/api/dairyProducts/ranch/ranch.js'
import { Upload, Download, UploadFilled } from '@element-plus/icons-vue';
const ranchOptions = ref([])
onMounted(() => {
getRanchList().then(res => {
ranchOptions.value = res.data.map(item => ({
label: item.ranchName,
value: item.ranchCode
}))
}).catch(err => {
console.error('获取厂区列表失败:', err)
})
})
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
manageEarNo: '', //
factory: null,
classes: null
})
const dateRange = ref([])
const tableData = ref([])
const total = ref(0)
const loading = ref(false)
const openImport = ref(false)
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/milkProdclasses/milkProdclasses/import';
const headers = { Authorization: 'Bearer ' + getToken() };
function getList() {
loading.value = true
const [start, end] = dateRange.value || []
listMilkProdclasses({
datetimeStart: start,
datetimeEnd: end,
manageEarNo: queryParams.manageEarNo,
factory: queryParams.factory,
classes: queryParams.classes,
pageNum: queryParams.pageNum,
pageSize: queryParams.pageSize
}).then(res => {
tableData.value = res.rows
total.value = res.total
loading.value = false
}).catch(err => {
console.error('查询失败:', err);
loading.value = false;
});
}
function resetQuery() {
Object.assign(queryParams, { pageNum: 1, manageEarNo: '', factory: null, classes: null });
dateRange.value = [];
getList();
}
function handleImport() {
openImport.value = true;
}
function uploadSuccess(response) {
console.log('上传成功:', response);
openImport.value = false;
getList();
}
function uploadError(err) {
console.error('上传失败:', err);
}
function handleExport() {
const [start, end] = dateRange.value || [];
exportMilkProdclasses({
datetimeStart: start,
datetimeEnd: end,
manageEarNo: queryParams.manageEarNo, //
factory: queryParams.factory,
classes: queryParams.classes
});
}
getList();
</script>

View File

@ -1,54 +1,36 @@
<template>
<div class="app-container">
<el-table
v-loading="loading"
:data="parityCorrectionList"
<el-table
v-loading="loading"
:data="parityCorrectionList"
style="width: 100%"
border
stripe
>
<el-table-column
label="胎次"
align="center"
prop="parity"
width="120"
/>
<el-table-column
label="系数"
align="center"
prop="coef"
width="120"
/>
<el-table-column label="胎次" align="center" prop="parity" width="120" />
<el-table-column label="系数" align="center" prop="coef" width="120" />
</el-table>
</div>
</template>
<script setup name="ParityCorrection">
import { listParityCorrection } from '@/api/dairyProducts/parityCorrection/parityCorrection.js'
import { ref, onMounted } from 'vue'
const loading = ref(false)
const parityCorrectionList = ref([])
// 1-8
const fixedParityData = [
{ id: 1, parity: 1, coef: 1.2 },
{ id: 2, parity: 2, coef: 1.0 },
{ id: 3, parity: 3, coef: 0.96 },
{ id: 4, parity: 4, coef: 0.96 },
{ id: 5, parity: 5, coef: 1.0 },
{ id: 6, parity: 6, coef: 1.0 },
{ id: 7, parity: 7, coef: 1.0 },
{ id: 8, parity: 8, coef: 1.0 }
]
//
onMounted(() => {
function getList() {
loading.value = true
//
setTimeout(() => {
parityCorrectionList.value = fixedParityData
listParityCorrection().then(res => {
parityCorrectionList.value = res.rows || res.data || [] //
}).finally(() => {
loading.value = false
}, 500)
})
}
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,194 @@
<template>
<div class="app-container">
<!-- 查询条件 -->
<el-form :inline="true" :model="queryParams" class="filter-form">
<el-form-item label="耳号">
<el-input v-model="queryParams.manageEarTag" placeholder="请输入耳号" />
</el-form-item>
<el-form-item label="筛选天数">
<el-input-number v-model="queryParams.screenDays" :min="0" placeholder="请输入天数" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮行 -->
<div class="button-group">
<el-button type="success" @click="handleExport">导出</el-button>
<el-popover
placement="bottom"
width="400"
trigger="click"
>
<el-checkbox-group v-model="selectedFields" class="checkbox-columns">
<el-checkbox
v-for="col in allColumns"
:key="col.prop"
:label="col.prop"
>{{ col.label }}</el-checkbox>
</el-checkbox-group>
<template #reference>
<el-button type="info">展示列</el-button>
</template>
</el-popover>
</div>
<!-- 数据表格 -->
<el-table :data="list" border style="width: 100%" v-loading="loading" :row-key="row => row.id">
<el-table-column
v-for="col in visibleColumns"
:key="col.prop"
:label="col.label"
:prop="col.prop"
:min-width="col.minWidth || 120"
/>
</el-table>
<!-- 分页 -->
<el-pagination
v-show="total > 0"
:total="total"
:current-page="queryParams.pageNum"
:page-size="queryParams.pageSize"
@current-change="handlePageChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[10, 20, 50, 100]"
/>
</div>
</template>
<script>
import { listSheepMilkAnalysis, exportSheepMilkAnalysis } from "@/api/dairyProducts/sheepMilkAnalysis/sheepMilkAnalysis.js";
export default {
name: "SheepMilkAnalysis",
data() {
return {
loading: false,
total: 0,
list: [],
queryParams: {
pageNum: 1,
pageSize: 10,
manageEarTag: null,
screenDays: null
},
selectedFields: [],
allColumns: [
{ label: "耳号", prop: "manageEarTag" },
{ label: "品种", prop: "variety" },
{ label: "挤奶时间", prop: "milkingDate" },
{ label: "干奶时间", prop: "dryDate" },
{ label: "筛选天数", prop: "screeningDays" },
{ label: "挤奶天数", prop: "milkingDays" },
{ label: "校正后最大胎次", prop: "maxCorrectedParity" },
{ label: "系统奶量之合计", prop: "systemMilkTotal" },
{ label: "校正奶量之合计", prop: "correctedMilkTotal" },
{ label: "校正日平均奶量", prop: "avgDailyCorrectedMilk" },
{ label: "胎次1的总产奶量", prop: "parity1TotalMilk" },
{ label: "胎次2的总产奶量", prop: "parity2TotalMilk" },
{ label: "胎次3的总产奶量", prop: "parity3TotalMilk" },
{ label: "胎次4的总产奶量", prop: "parity4TotalMilk" },
{ label: "胎次1的日平均产量", prop: "parity1AvgDailyMilk" },
{ label: "胎次2的日平均产量", prop: "parity2AvgDailyMilk" },
{ label: "胎次3的日平均产量", prop: "parity3AvgDailyMilk" },
{ label: "胎次4的日平均产量", prop: "parity4AvgDailyMilk" },
{ label: "泌乳天数", prop: "lactationDays" },
{ label: "过去7日日平均奶量", prop: "past7DaysAvgMilk" },
{ label: "校正过去7日日平均奶量", prop: "past7DaysAvgCorrectedMilk" },
{ label: "过去14日日平均奶量", prop: "past14DaysAvgMilk" },
{ label: "过去30日日平均奶量", prop: "past30DaysAvgMilk" },
{ label: "羊只类型", prop: "sheepType" },
{ label: "生日", prop: "birthDate" },
{ label: "当前胎次", prop: "currentParity" },
{ label: "月龄", prop: "ageMonths" },
{ label: "当前体重", prop: "currentWeight" },
{ label: "繁育状态", prop: "breedStatus" },
{ label: "父号", prop: "fatherTag" },
{ label: "母号", prop: "motherTag" },
{ label: "牧场名称", prop: "ranchName" },
{ label: "家系", prop: "familyLine" },
{ label: "母亲挤奶天数", prop: "motherMilkingDays" },
{ label: "母亲校正奶量之合计", prop: "motherCorrectedMilkTotal" },
{ label: "母亲校正后最大胎次", prop: "motherMaxCorrectedParity" },
{ label: "母亲校正日平均奶量", prop: "motherAvgDailyCorrectedMilk" }
]
};
},
created() {
this.selectedFields = this.allColumns.map(c => c.prop);
this.getList();
},
computed: {
visibleColumns() {
return this.allColumns.filter(col => this.selectedFields.includes(col.prop));
}
},
methods: {
getList() {
this.loading = true;
listSheepMilkAnalysis(this.queryParams).then(response => {
this.list = response.rows;
this.total = response.total;
this.loading = false;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 10,
manageEarTag: null,
screenDays: null
};
this.selectedFields = this.allColumns.map(c => c.prop);
this.getList();
},
handlePageChange(pageNum) {
this.queryParams.pageNum = pageNum;
this.getList();
},
handleSizeChange(pageSize) {
this.queryParams.pageSize = pageSize;
this.getList();
},
handleExport() {
exportSheepMilkAnalysis(this.queryParams).then(response => {
const blob = new Blob([response], { type: 'application/vnd.ms-excel' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', '羊奶分析数据.xlsx');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
}
}
};
</script>
<style scoped>
.filter-form .el-form-item {
margin-right: 15px;
}
.button-group {
margin-bottom: 10px;
}
.checkbox-columns {
display: flex;
flex-wrap: wrap;
gap: 10px;
max-height: 300px;
overflow-y: auto;
}
</style>

View File

@ -0,0 +1,172 @@
<template>
<div class="app-container">
<!-- 顶部存栏总数 -->
<el-row :gutter="20" class="top-summary">
<el-col :span="24">
<el-card shadow="hover" class="summary-card">
<div class="summary-content">
<el-icon size="48" color="#409EFF"><Collection /></el-icon>
<div>
<div class="summary-title">存栏羊只总数</div>
<div class="summary-value">{{ inGroupCount }}</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 图表区域 -->
<el-row :gutter="20" class="chart-row">
<!-- 羊只类别 -->
<el-col :xs="24" :sm="24" :md="12" :lg="12">
<el-card shadow="hover" class="chart-card">
<template #header>
<span class="card-title">羊只类别分布</span>
</template>
<div ref="typePie" class="chart-box"></div>
</el-card>
</el-col>
<!-- 泌乳羊胎次 -->
<el-col :xs="24" :sm="24" :md="12" :lg="12">
<el-card shadow="hover" class="chart-card">
<template #header>
<span class="card-title">泌乳羊胎次分布</span>
</template>
<div ref="parityPie" class="chart-box"></div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="chart-row">
<!-- 繁育状态 -->
<el-col :xs="24" :sm="24" :md="12" :lg="12">
<el-card shadow="hover" class="chart-card">
<template #header>
<span class="card-title">繁育状态分布</span>
</template>
<div ref="breedBar" class="chart-box"></div>
</el-card>
</el-col>
<!-- 品种分布 -->
<el-col :xs="24" :sm="24" :md="12" :lg="12">
<el-card shadow="hover" class="chart-card">
<template #header>
<span class="card-title">品种分布</span>
</template>
<div ref="varietyBar" class="chart-box"></div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import { Collection } from '@element-plus/icons-vue'
import {
getInGroupCount,
getSheepTypeStat,
getBreedStatusStat,
getVarietyStat,
getLactationParityStat
} from '@/api/fileManagement/sheep_file'
const inGroupCount = ref(0)
const typePie = ref(null)
const parityPie = ref(null)
const breedBar = ref(null)
const varietyBar = ref(null)
let chart1, chart2, chart3, chart4
onMounted(() => {
chart1 = echarts.init(typePie.value)
chart2 = echarts.init(parityPie.value)
chart3 = echarts.init(breedBar.value)
chart4 = echarts.init(varietyBar.value)
loadCharts()
window.addEventListener('resize', () => {
chart1.resize(); chart2.resize(); chart3.resize(); chart4.resize()
})
})
function loadCharts() {
const pieOption = (data, title) => ({
title: { text: title, left: 'center', textStyle: { fontWeight: 'bold' } },
tooltip: { trigger: 'item' },
legend: { orient: 'vertical', left: 'left' },
series: [
{
type: 'pie',
radius: '60%',
data,
emphasis: {
itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0,0,0,0.5)' }
}
}
]
})
const barOption = (data, title) => ({
title: { text: title, left: 'center', textStyle: { fontWeight: 'bold' } },
tooltip: {},
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: { type: 'category', data: data.map(i => i.name) },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: data.map(i => i.value), itemStyle: { borderRadius: [4, 4, 0, 0] } }]
})
getInGroupCount().then(res => (inGroupCount.value = res.data))
getSheepTypeStat().then(res => chart1.setOption(pieOption(res.data, '羊只类别分布')))
getLactationParityStat().then(res => chart2.setOption(pieOption(res.data, '泌乳羊胎次分布')))
getBreedStatusStat().then(res => chart3.setOption(barOption(res.data, '繁育状态分布')))
getVarietyStat().then(res => chart4.setOption(barOption(res.data, '品种分布')))
}
</script>
<style scoped>
/* 顶部卡片 */
.top-summary {
margin-bottom: 20px;
}
.summary-card {
border-radius: 12px;
}
.summary-content {
display: flex;
align-items: center;
gap: 16px;
}
.summary-title {
font-size: 16px;
color: #909399;
margin-bottom: 6px;
}
.summary-value {
font-size: 36px;
font-weight: 700;
color: #409EFF;
}
/* 图表卡片 */
.chart-row {
margin-bottom: 20px;
}
.chart-card {
border-radius: 12px;
height: 100%;
}
.card-title {
font-size: 16px;
font-weight: 600;
color: #303133;
}
.chart-box {
height: 300px;
}
</style>

View File

@ -0,0 +1,340 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="queryParams.sheepId" placeholder="请输入羊只id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</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="['body_measure:body_measure:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['body_measure:body_measure:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['body_measure:body_measure:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['body_measure:body_measure:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="body_measureList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="${comment}" align="center" prop="id" /> -->
<!-- <el-table-column label="羊只id" align="center" prop="sheepId" /> -->
<el-table-column label="管理耳号" align="center" prop="manageTags" fixed min-width="100px" />
<el-table-column label="体高" align="center" prop="height" />
<el-table-column label="胸围" align="center" prop="bust" />
<el-table-column label="体斜长" align="center" prop="bodyLength" />
<el-table-column label="管围" align="center" prop="pipeLength" />
<el-table-column label="胸深" align="center" prop="chestDepth" />
<el-table-column label="臀高" align="center" prop="hipHeight" />
<el-table-column label="尻宽" align="center" prop="rumpWidth" />
<el-table-column label="尻高" align="center" prop="rumpHeignt" />
<el-table-column label="腰角宽" align="center" prop="hipWidth" />
<el-table-column label="十字部高" align="center" prop="hipCrossHeight" />
<el-table-column label="备注" align="center" prop="comment" min-width="100px" />
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" min-width="130px">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['body_measure:body_measure:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['body_measure:body_measure: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="700px" append-to-body>
<el-form ref="body_measureRef" :model="form" :rules="rules" label-width="100px" size="medium"
label-position="left">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" :disabled="!isAdd"
clearable />
</el-form-item>
<el-form-item label="体高" prop="height">
<el-input v-model="form.height" placeholder="请输入体高" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="胸围" prop="bust">
<el-input v-model="form.bust" placeholder="请输入胸围" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="体斜长" prop="bodyLength">
<el-input v-model="form.bodyLength" placeholder="请输入体斜长" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="管围" prop="pipeLength">
<el-input v-model="form.pipeLength" placeholder="请输入管围" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="胸深" prop="chestDepth">
<el-input v-model="form.chestDepth" placeholder="请输入胸深" :disabled="!isAdd" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="臀高" prop="hipHeight">
<el-input v-model="form.hipHeight" placeholder="请输入臀高" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="尻宽" prop="rumpWidth">
<el-input v-model="form.rumpWidth" placeholder="请输入尻宽" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="尻高" prop="rumpHeignt">
<el-input v-model="form.rumpHeignt" placeholder="请输入尻高" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="腰角宽" prop="hipWidth">
<el-input v-model="form.hipWidth" placeholder="请输入腰角宽" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="十字部高" prop="hipCrossHeight">
<el-input v-model="form.hipCrossHeight" placeholder="请输入十字部高" :disabled="!isAdd" clearable />
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAdd" clearable />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注" prop="comment" v-if="!isAdd">
<el-input v-model="form.comment" placeholder="请输入备注" :disabled="!isAdd" clearable type="textarea" rows="3" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Body_measure">
import { listBody_measure, getBody_measure, delBody_measure, addBody_measure, updateBody_measure } from "@/api/produce/bodyManage/body_measure"
import { getCurrentInstance } from 'vue'
import { getSheepByManageTags } from "@/api/produce/manage_sheep/changeVariety"
const { proxy } = getCurrentInstance()
const body_measureList = 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 daterangeCreateTime = ref([])
const isAdd = ref(false)
const data = reactive({
form: { manageTags: null, technician: null },
queryParams: {
pageNum: 1,
pageSize: 10,
sheepId: null,
manageTags: null,
createTime: null
},
rules: {
manageTags: [
{ required: true, message: '请输入管理耳号', trigger: 'blur' }
],
technician: [
{ required: true, message: '请输入技术员', trigger: 'blur' }
],
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询体尺测量列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
if (daterangeCreateTime.value.length > 0) {
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0]
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1]
}
listBody_measure(queryParams.value).then(response => {
body_measureList.value = response.rows
total.value = response.total
loading.value = false
})
}
//
function onManageTagsBlur() {
const tag = form.value.manageTags?.trim();
if (!tag) {
form.value.sheepId = null;
return;
}
getSheepByManageTags(tag).then(res => {
if (res.code === 200 && res.data) {
form.value.sheepId = res.data.id;
form.value.comment = res.data.comment || "";
} else {
form.value.sheepId = null;
form.value.comment = null;
proxy.$modal.msgWarning("未找到该管理耳号对应的羊只");
}
}).catch(err => {
console.error("耳号验证失败:", err);
form.value.sheepId = null;
form.value.comment = null;
proxy.$modal.msgError("查询失败,请重试");
});
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
sheepId: null,
height: null,
bust: null,
bodyLength: null,
pipeLength: null,
chestDepth: null,
hipHeight: null,
rumpWidth: null,
rumpHeignt: null,
hipWidth: null,
hipCrossHeight: null,
comment: null,
technician: null,
createBy: null,
createTime: null
}
proxy.resetForm("body_measureRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
daterangeCreateTime.value = []
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()
isAdd.value = true
open.value = true
title.value = "添加体尺测量"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
isAdd.value = false
const _id = row.id || ids.value
getBody_measure(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改体尺测量"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["body_measureRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateBody_measure(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addBody_measure(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除体尺测量编号为"' + _ids + '"的数据项?').then(function () {
return delBody_measure(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => { })
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('body_measure/body_measure/export', {
...queryParams.value
}, `body_measure_${new Date().getTime()}.xlsx`)
}
getList()
</script>

View File

@ -0,0 +1,355 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="queryParams.sheepId" placeholder="请输入羊只id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="事件日期" style="width: 308px">
<el-date-picker v-model="daterangeDatetime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item label="体况评分" prop="score">
<el-input v-model="queryParams.score" placeholder="请输入体况评分" clearable @keyup.enter="handleQuery"
style="max-width: 150px;" />
</el-form-item>
<el-form-item label="羊舍" prop="sheepfold">
<el-select v-model="queryParams.sheepfold" placeholder="请选择羊舍" clearable filterable @keyup.enter="handleQuery">
<el-option v-for="item in sheepfoldList" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
</el-select>
</el-form-item>
<!-- <el-form-item label="羊舍id" prop="sheepfold">
<el-input v-model="queryParams.sheepfold" placeholder="请输入羊舍id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</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="['body_score:body_score:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['body_score:body_score:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['body_score:body_score:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['body_score:body_score:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="body_scoreList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="${comment}" align="center" prop="id" /> -->
<!-- <el-table-column label="羊只id" align="center" prop="sheepId" /> -->
<el-table-column label="管理耳号" align="center" prop="manageTags" fixed />
<el-table-column label="事件日期" align="center" prop="datetime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="体况评分" align="center" prop="score" />
<!-- <el-table-column label="羊舍id" align="center" prop="sheepfold" /> -->
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="150px">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['body_score:body_score:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['body_score:body_score: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="500px" append-to-body>
<el-form ref="body_scoreRef" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" :disabled="!isAdd"
clearable />
</el-form-item>
<el-form-item label="事件日期" prop="datetime">
<el-date-picker clearable v-model="form.datetime" type="date" value-format="YYYY-MM-DD" placeholder="请选择事件日期"
:disabled="!isAdd">
</el-date-picker>
</el-form-item>
<el-form-item label="体况评分" prop="score">
<el-input v-model="form.score" placeholder="请输入体况评分" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="羊舍" v-if="!isAdd">
<el-select v-model="form.sheepfold" disabled>
<el-option v-for="item in sheepfoldList" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
</el-select>
</el-form-item>
<!-- <el-form-item label="羊舍id" prop="sheepfold">
<el-input v-model="form.sheepfold" placeholder="请输入羊舍id" :disabled="!isAdd" />
</el-form-item> -->
<el-form-item label="备注" v-if="!isAdd">
<el-input v-model="form.comment" disabled type="textarea" rows="2" />
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAdd" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Body_score">
import { listBody_score, getBody_score, delBody_score, addBody_score, updateBody_score } from "@/api/produce/bodyManage/body_score"
import { listSheepfold } from "@/api/produce/manage_sheep/trans_group"
import { checkSheepByManageTags } from "@/api/produce/other/fixHoof"
import { getCurrentInstance, ref, reactive, toRefs } from 'vue'
const { proxy } = getCurrentInstance()
const body_scoreList = 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 daterangeDatetime = ref([])
const daterangeCreateTime = ref([])
const sheepfoldList = ref([])
const isAdd = ref(false)
const data = reactive({
form: {
id: null,
sheepId: null,
manageTags: null,
datetime: null,
score: null,
comment: null,
technician: null
},
queryParams: {
pageNum: 1,
pageSize: 10,
manageTags: null,
score: null,
createTime: null
},
rules: {
manageTags: [
{ required: true, message: '请输入管理耳号', trigger: 'blur' }
],
score: [
{ required: true, message: '请输入体况评分', trigger: 'blur' }
],
technician: [
{ required: true, message: '请输入技术员', trigger: 'blur' }
]
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询体况评分列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
if (null != daterangeDatetime && '' != daterangeDatetime) {
queryParams.value.params["beginDatetime"] = daterangeDatetime.value[0]
queryParams.value.params["endDatetime"] = daterangeDatetime.value[1]
}
if (null != daterangeCreateTime && '' != daterangeCreateTime) {
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0]
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1]
}
listBody_score(queryParams.value).then(response => {
body_scoreList.value = response.rows
total.value = response.total
loading.value = false
})
}
function onManageTagsBlur() {
const tag = form.value.manageTags?.trim();
if (!tag) {
form.value.sheepId = null;
form.value.sheepfold = null;
form.value.comment = null;
return;
}
checkSheepByManageTags(tag).then(res => {
if (res.code === 200 && res.data) {
form.value.sheepId = res.data.id;
form.value.sheepfold = res.data.sheepfoldId;
form.value.comment = res.data.comment || '';
} else {
form.value.sheepId = null;
form.value.sheepfold = null;
form.value.comment = null;
proxy.$modal.msgWarning("未找到该管理耳号对应的羊只");
}
}).catch(err => {
console.error("耳号验证失败:", err);
form.value.sheepId = null;
form.value.sheepfold = null;
form.value.comment = null;
proxy.$modal.msgError("查询失败,请重试");
});
}
//
function loadSheepfoldList() {
listSheepfold().then(response => {
sheepfoldList.value = response.rows || [];
}).catch(err => {
console.error("加载羊舍列表失败:", err);
proxy.$modal.msgError("加载羊舍列表失败,请刷新页面重试");
});
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
sheepId: null,
datetime: null,
score: null,
sheepfold: null,
comment: null,
technician: null,
createBy: null,
createTime: null
}
proxy.resetForm("body_scoreRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
daterangeDatetime.value = []
daterangeCreateTime.value = []
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()
isAdd.value = true
open.value = true
title.value = "添加体况评分"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
isAdd.value = false
const _id = row.id || ids.value
getBody_score(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改体况评分"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["body_scoreRef"].validate(valid => {
if (valid) {
if (!form.value.id && !form.value.sheepId) {
proxy.$modal.msgError("请输入有效的管理耳号");
return;
}
if (form.value.id != null) {
updateBody_score(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addBody_score(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除体况评分编号为"' + _ids + '"的数据项?').then(function () {
return delBody_score(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => { })
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('body_score/body_score/export', {
...queryParams.value
}, `body_score_${new Date().getTime()}.xlsx`)
}
getList()
loadSheepfoldList();
</script>

View File

@ -0,0 +1,319 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="queryParams.sheepId" placeholder="请输入羊只id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入耳号搜索" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</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="['breast_rating:breast_rating:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['breast_rating:breast_rating:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['breast_rating:breast_rating:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['breast_rating:breast_rating:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="breast_ratingList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="${comment}" align="center" prop="id" /> -->
<!-- <el-table-column label="羊只id" align="center" prop="sheepId" /> -->
<el-table-column label="管理耳号" align="center" prop="manageTags" />
<el-table-column label="乳房深度" align="center" prop="depth" />
<el-table-column label="乳房长度" align="center" prop="length" />
<el-table-column label="乳房位置" align="center" prop="position" />
<el-table-column label="乳房附着" align="center" prop="adbere" />
<el-table-column label="乳房间隔度" align="center" prop="spacing" />
<el-table-column label="乳房评分" align="center" prop="score" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="150">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="120px">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['breast_rating:breast_rating:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['breast_rating:breast_rating: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="550px" append-to-body>
<el-form ref="breast_ratingRef" :model="form" :rules="rules" label-width="115px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" clearable
:disabled="!isAdd" />
</el-form-item>
<el-form-item label="乳房深度" prop="depth">
<el-input v-model="form.depth" placeholder="请输入乳房深度" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="乳房长度" prop="length">
<el-input v-model="form.length" placeholder="请输入乳房长度" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="乳房位置" prop="position">
<el-input v-model="form.position" placeholder="请输入乳房位置" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="乳房附着" prop="adbere">
<el-input v-model="form.adbere" placeholder="请输入乳房附着" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="乳房间隔度" prop="spacing">
<el-input v-model="form.spacing" placeholder="请输入乳房间隔度" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="乳房评分" prop="score">
<el-input v-model="form.score" placeholder="请输入乳房评分" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="羊只备注" v-if="!isAdd">
<el-input v-model="form.comment" type="textarea" :rows="2" placeholder="羊只备注" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAdd" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Breast_rating">
import { listBreast_rating, getBreast_rating, delBreast_rating, addBreast_rating, updateBreast_rating } from "@/api/produce/bodyManage/breast_rating"
import { checkSheepByManageTags } from "@/api/produce/other/fixHoof"
import { getCurrentInstance, reactive, ref } from "vue"
const { proxy } = getCurrentInstance()
const breast_ratingList = 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 daterangeCreateTime = ref([])
const isAdd = ref(false)
const data = reactive({
form: {
id: null,
manageTags: null,
depth: null,
length: null,
position: null,
adbere: null,
spacing: null,
score: null,
comment: null,
technician: null
},
queryParams: {
pageNum: 1,
pageSize: 10,
manageTags: null
},
rules: {
manageTags: [
{ required: true, message: '请输入管理耳号', trigger: 'blur' }
],
score: [
{ required: true, message: '请输入乳房评分', trigger: 'blur' }
],
technician: [
{ required: true, message: '请输入技术员', trigger: 'blur' }
],
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询乳房评分列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
if (daterangeCreateTime.value.length) {
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0]
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1]
}
listBreast_rating(queryParams.value).then(response => {
breast_ratingList.value = response.rows
total.value = response.total
loading.value = false
})
}
//
function onManageTagsBlur() {
const tag = form.value.manageTags?.trim();
if (!tag) {
form.value.sheepId = null;
form.value.comment = null;
return;
}
checkSheepByManageTags(tag).then(res => {
if (res.code === 200 && res.data) {
form.value.sheepId = res.data.id;
form.value.comment = res.data.comment || '';
} else {
form.value.sheepId = null;
form.value.comment = null;
proxy.$modal.msgWarning("未找到该耳号对应的羊只");
}
}).catch(err => {
console.error("耳号查询失败:", err);
form.value.sheepId = null;
form.value.comment = null;
});
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
manageTags: null,
sheepId: null,
depth: null,
length: null,
position: null,
adbere: null,
spacing: null,
score: null,
comment: null,
technician: null,
createBy: null,
createTime: null
}
proxy.resetForm("breast_ratingRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
daterangeCreateTime.value = []
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()
isAdd.value = true
open.value = true
title.value = "添加乳房评分"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
isAdd.value = false
const _id = row.id || ids.value
getBreast_rating(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改乳房评分"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["breast_ratingRef"].validate(valid => {
if (valid) {
if (!form.value.sheepId) {
proxy.$modal.msgError("请输入有效的管理耳号");
return;
}
if (form.value.id) {
updateBreast_rating(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addBreast_rating(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除乳房评分编号为"' + _ids + '"的数据项?').then(function () {
return delBreast_rating(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => { })
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('breast_rating/breast_rating/export', {
...queryParams.value
}, `breast_rating_${new Date().getTime()}.xlsx`)
}
getList()
</script>

View File

@ -6,11 +6,12 @@
v-hasPermi="['produce:add_sheep:import']">导入</el-button>
<!-- 新增/编辑表单 -->
<el-form :model="form" ref="formRef" label-position="left" label-width="100px" style="margin-top:15px">
<el-form :model="form" ref="formRef" label-position="left" label-width="120px" style="margin-top:15px"
:rules="rules">
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="耳号" prop="earNumber">
<el-input v-model="form.earNumber" placeholder="请输入耳号" />
<el-input v-model="form.earNumber" placeholder="请输入耳号" @blur="handleEarNumberBlur" />
</el-form-item>
</el-col>
<el-col :span="10">
@ -55,7 +56,6 @@
<el-option label="公" :value="2" />
<el-option label="母" :value="1" />
<el-option label="阉羊" :value="3" />
<!-- <el-option label="兼性" :value="3" /> -->
</el-select>
</el-form-item>
</el-col>
@ -127,7 +127,6 @@ import { getToken } from '@/utils/auth'
const { proxy } = getCurrentInstance()
/* -------------------- 表单 -------------------- */
const form = ref({
earNumber: '',
sheepfold: '',
@ -145,24 +144,63 @@ const form = ref({
const formRef = ref(null)
const rules = {
earNumber: [{ required: true, message: '请输入耳号', trigger: 'blur' }],
earNumber: [
{ required: true, message: '请输入耳号', trigger: 'blur' },
{ validator: checkEarNumberExists, trigger: 'blur' }
],
sheepfold: [{ required: true, message: '请选择羊舍', trigger: 'change' }],
bornWeight: [{ required: true, message: '请输入出生体重', trigger: 'blur' }],
birthday: [{ required: true, message: '请选择出生日期', trigger: 'change' }],
gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
varietyId: [{ required: true, message: '请选择品种', trigger: 'change' }]
varietyId: [{ required: true, message: '请选择品种', trigger: 'change' }],
joinDate:[{ required: true, message: '请选择入群日期', trigger: 'change' }],
technician:[{ required: true, message: '请输入技术员', trigger: 'change' }],
}
/* -------------------- 下拉数据 -------------------- */
//
function checkEarNumberExists(rule, value, callback) {
if (!value.trim()) {
return callback(new Error('请输入耳号'))
}
request({
url: `/sheep/sheep/existsByManageTags/${value.trim()}`,
method: 'get'
})
.then(response => {
if (response.data === true) {
callback(new Error('耳号已存在,无法新增'))
} else {
callback()
}
})
.catch(error => {
const status = error.response?.status;
const errorMsg = error.response?.data?.msg || '';
if (status === 404) {
callback();
} else {
callback(new Error('请求异常,请稍后重试'));
}
});
}
function handleEarNumberBlur() {
formRef.value.validateField('earNumber')
}
const sheepfoldOptions = ref([])
const varietyOptions = ref([])
//
function getSheepfoldOptions() {
listSheepfold({ pageNum: 1, pageSize: 9999 }).then(res => {
sheepfoldOptions.value = res.rows || []
})
}
//
function getVarietyOptions() {
request({
url: '/base/variety/list',
@ -173,21 +211,38 @@ function getVarietyOptions() {
})
}
/* -------------------- 功能方法 -------------------- */
//
function formatDate(date) {
if (!date) return null;
const d = new Date(date);
const yyyy = d.getFullYear();
const mm = String(d.getMonth() + 1).padStart(2, '0');
const dd = String(d.getDate()).padStart(2, '0');
return `${yyyy}-${mm}-${dd}`;
}
//
function submitForm() {
formRef.value.validate(valid => {
if (!valid) return
addSheep(form.value).then(res => {
if (!valid) return;
const formData = JSON.parse(JSON.stringify(form.value));
formData.birthday = formatDate(formData.birthday);
formData.joinDate = formatDate(formData.joinDate);
if (formData.bornWeight) {
formData.bornWeight = Number(formData.bornWeight);
}
addSheep(formData).then(res => {
if (res.code === 200) {
proxy.$modal.msgSuccess('新增成功')
resetForm()
proxy.$modal.msgSuccess('新增成功');
resetForm();
} else {
proxy.$modal.msgError(res.msg || '新增失败') //
proxy.$modal.msgError(res.msg || '新增失败');
}
}).catch(() => {
proxy.$modal.msgError('请求异常,请稍后重试')
})
})
});
});
}
function resetForm() {
@ -206,7 +261,7 @@ function resetForm() {
technician: ''
}
}
//
function handleExportForm() {
exportSheepForm(form.value).then(res => {
const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
@ -239,29 +294,27 @@ function submitUpload() {
uploadRef.value?.submit()
}
//
//
function handleImportSuccess(res) {
if (res.code === 200) {
proxy.$modal.msgSuccess(res.msg || '导入成功')
importOpen.value = false
uploadRef.value?.clearFiles()
} else {
//
//
proxy.$modal.msgError('导入失败:' + (res.msg || '未知原因'))
}
}
// /
// /
function handleImportError(err) {
const msg = JSON.parse(err.message || '{}')?.msg || '网络异常'
proxy.$modal.msgError('导入失败:' + msg)
}
/* -------------------- 初始化 -------------------- */
getSheepfoldOptions()
getVarietyOptions()
getSheepfoldOptions()
getVarietyOptions()
</script>

View File

@ -0,0 +1,289 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input
v-model="queryParams.sheepId"
placeholder="请输入羊只id"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="新备注" prop="newComment">
<el-input v-model="queryParams.newComment" placeholder="请输入新备注" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="原备注" prop="oldComment">
<el-input v-model="queryParams.oldComment" placeholder="请输入原备注" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</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="['changeComment:changeComment:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['changeComment:changeComment:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['changeComment:changeComment:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['changeComment:changeComment:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="changeCommentList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="${comment}" align="center" prop="id" /> -->
<!-- <el-table-column label="羊只id" align="center" prop="sheepId" /> -->
<el-table-column label="管理耳号" align="center" prop="manageTags" />
<el-table-column label="新备注" align="center" prop="newComment" />
<el-table-column label="原备注" align="center" prop="oldComment" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</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="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['changeComment:changeComment:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['changeComment:changeComment: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="500px" append-to-body>
<el-form ref="changeCommentRef" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" :disabled="!isAddMode" />
</el-form-item>
<el-form-item label="新备注" prop="newComment">
<el-input v-model="form.newComment" placeholder="请输入新备注" :disabled="!isAddMode" />
</el-form-item>
<el-form-item label="原备注" prop="oldComment">
<el-input v-model="form.oldComment" placeholder="请输入原备注" :disabled="!isAddMode" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ChangeComment">
import { listChangeComment, getChangeComment, delChangeComment, addChangeComment, updateChangeComment } from "@/api/produce/manage_sheep/changeComment"
import { getSheepByManageTags } from "@/api/produce/manage_sheep/changeVariety"
const { proxy } = getCurrentInstance()
const changeCommentList = 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 daterangeCreateTime = ref([])
const isAddMode = ref(true);
const data = reactive({
form: { manageTags: null, },
queryParams: {
pageNum: 1,
pageSize: 10,
sheepId: null,
manageTags: null,
newComment: null,
oldComment: null,
createTime: null
},
rules: {
manageTags: [
{ required: true, message: "请输入管理耳号", trigger: "blur" }
],
newComment: [
{ required: true, message: "请输入新备注", trigger: "blur" }
]
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询改备注列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
if (null != daterangeCreateTime && '' != daterangeCreateTime) {
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0]
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1]
}
listChangeComment(queryParams.value).then(response => {
changeCommentList.value = response.rows
total.value = response.total
loading.value = false
})
}
//
function onManageTagsBlur() {
const tag = form.value.manageTags?.trim();
if (!tag) return;
getSheepByManageTags(tag).then(res => {
const sheep = res.data;
if (sheep) {
form.value.sheepId = sheep.id;
form.value.oldComment = sheep.comment || "";
} else {
proxy.$modal.msgWarning("未找到该管理耳号对应的羊只");
form.value.sheepId = null;
form.value.oldComment = "";
}
}).catch(err => {
console.error("查询羊只失败:", err);
proxy.$modal.msgError("查询失败,请重试");
});
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
sheepId: null,
newComment: null,
oldComment: null,
createBy: null,
createTime: null
}
proxy.resetForm("changeCommentRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
daterangeCreateTime.value = []
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()
isAddMode.value = true;
open.value = true
title.value = "添加改备注"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
isAddMode.value = false
const _id = row.id || ids.value
getChangeComment(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改改备注"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["changeCommentRef"].validate(valid => {
if (valid) {
if (!form.value.id) {
if (!form.value.sheepId) {
proxy.$modal.msgError('未找到对应的羊只,请检查耳号');
return;
}
}
if (form.value.id != null) {
updateChangeComment(form.value).then(() => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addChangeComment(form.value).then(() => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除改备注编号为"' + _ids + '"的数据项?').then(function () {
return delChangeComment(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => { })
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('changeComment/changeComment/export', {
...queryParams.value
}, `changeComment_${new Date().getTime()}.xlsx`)
}
getList()
</script>

View File

@ -0,0 +1,369 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="queryParams.sheepId" placeholder="请输入羊只id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item label="耳号" prop="manageTag">
<el-input v-model="queryParams.manageTags" placeholder="请输入耳号" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="新耳号" prop="newTag">
<el-input v-model="queryParams.newTag" placeholder="请输入新耳号" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="旧耳号" prop="oldTag">
<el-input v-model="queryParams.oldTag" placeholder="请输入旧耳号" clearable @keyup.enter="handleQuery"
style="max-width: 160px;" />
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</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="['changeEar:changeEar:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['changeEar:changeEar:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['changeEar:changeEar:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['changeEar:changeEar:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="changeEarList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="id" align="center" prop="id" />
<el-table-column label="羊只id" align="center" prop="sheepId" /> -->
<el-table-column label="耳号" align="center" prop="manageTags" />
<el-table-column label="耳号类型" align="center" prop="earType">
<template #default="scope">
{{ scope.row.earType === 0 ? '电子耳号' : '管理耳号' }}
</template>
</el-table-column>
<el-table-column label="新耳号" align="center" prop="newTag" />
<el-table-column label="旧耳号" align="center" prop="oldTag" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</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="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['changeEar:changeEar:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['changeEar:changeEar: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="500px" append-to-body>
<el-form ref="changeEarRef" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item> -->
<el-form-item label="耳号" prop="earNumber">
<el-input v-model="form.earNumber" placeholder="请输入管理耳号或电子耳号" @change="fetchOldTag" :disabled="!isAddMode" />
</el-form-item>
<el-form-item label="耳号类型" prop="earType">
<el-select v-model="form.earType" placeholder="请选择耳号类型" @change="fetchOldTag" :disabled="!isAddMode">
<el-option label="电子耳号" :value="0"></el-option>
<el-option label="管理耳号" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="新耳号" prop="newTag" @blur="checkNewTagExists">
<el-input v-model="form.newTag" placeholder="请输入新耳号/电子耳号" @blur="checkNewTagExists" :disabled="!isAddMode" />
</el-form-item>
<el-form-item label="旧耳号" prop="oldTag">
<el-input v-model="form.oldTag" placeholder="请输入旧耳号/电子耳号" :disabled="!isAddMode" />
</el-form-item>
<el-form-item label="备注" prop="comment" v-if="!isAddMode">
<el-input v-model="form.comment" type="textarea" placeholder="请输入内容" :disabled="!isAddMode" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ChangeEar">
import { listChangeEar, getChangeEar, delChangeEar, addChangeEar, updateChangeEar, getSheepByEarNumber,checkTagExists } from "@/api/produce/manage_sheep/changeEar"
const { proxy } = getCurrentInstance()
const changeEarList = 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 daterangeCreateTime = ref([])
const isAddMode = ref(true);
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
manageTags: null,
// sheepId: null,
earType: null,
newTag: null,
oldTag: null,
createTime: null
},
rules: {
earNumber: [
{ required: true, message: "请输入管理耳号或电子耳号", trigger: "blur" }
],
earType: [
{ required: true, message: "请选择耳号类型", trigger: "change" }
],
newTag: [
{ required: true, message: "请输入新耳号", trigger: "blur" }
],
oldTag: [
{ required: true, message: "请输入旧耳号", trigger: "change" }
],
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询修改电子耳号记录列表 */
async function getList() {
loading.value = true;
queryParams.value.params = {};
if (queryParams.value.manageTags) {
queryParams.value.params["manageTags"] = queryParams.value.manageTags;
}
if (daterangeCreateTime.value && daterangeCreateTime.value.length > 0) {
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0];
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1];
}
const response = await listChangeEar(queryParams.value);
changeEarList.value = response.rows.map(item => {
item.earTypeName = item.earType === 0 ? '电子耳号' : '管理耳号';
return item;
});
total.value = response.total;
loading.value = false;
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
// id: null,
// sheepId: null,
manageTags: null,
earType: null,
newTag: null,
oldTag: null,
comment: null,
createBy: null,
createTime: null
}
proxy.resetForm("changeEarRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
daterangeCreateTime.value = []
queryParams.value.manageTags = null
queryParams.value.newTag = null
queryParams.value.oldTag = null
queryParams.value.earType = null
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()
isAddMode.value = true;
open.value = true
title.value = "添加耳号记录"
}
//
function handleUpdate(row) {
reset();
isAddMode.value = false;
const _id = row.id || ids.value;
getChangeEar(_id).then(response => {
response.data.earNumber = response.data.manageTags;
form.value = response.data;
open.value = true;
title.value = "修改电子耳号记录";
});
}
//
function submitForm() {
proxy.$refs["changeEarRef"].validate(valid => {
if (valid) {
if (!form.value.id) {
if (!form.value.sheepId) {
proxy.$modal.msgError('未找到对应的羊只,请检查耳号');
return;
}
}
if (form.value.id) {
updateChangeEar(form.value).then(() => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
addChangeEar(form.value).then(() => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}
//
function checkNewTagExists() {
if (!form.value.newTag || form.value.earType === null) {
console.log("新耳号或耳号类型为空");
return;
}
const tagValue = form.value.newTag.trim();
if (!tagValue) {
console.log("新耳号为空");
return;
}
console.log("调用后端接口,参数:", { tag: tagValue, earType: form.value.earType });
checkTagExists(tagValue, form.value.earType).then(res => {
console.log("后端返回结果:", res);
if (res.data.exists) {
proxy.$modal.msgError('该耳号已存在,请更换');
form.value.newTag = '';
}
}).catch(error => {
console.error('校验耳号失败:', error);
proxy.$modal.msgWarning('校验耳号失败,请重试');
});
}
//
function fetchOldTag() {
const earNumber = form.value.earNumber.trim();
const earType = form.value.earType;
if (!earNumber || earType === null) {
form.value.oldTag = '';
form.value.sheepId = null;
form.value.comment = '';
return;
}
getSheepByEarNumber(earNumber, earType).then(response => {
const data = response.data;
const sheep = data.sheep;
const oldTag = data.oldTag;
if (!sheep || !sheep.id) {
form.value.oldTag = '';
form.value.sheepId = null;
form.value.comment = '';
proxy.$modal.warning("未找到对应的羊只");
return;
}
form.value.oldTag = oldTag;
form.value.sheepId = sheep.id;
form.value.comment = sheep.comment || '';
}).catch(error => {
console.error("查询失败:", error);
form.value.oldTag = '';
form.value.sheepId = null;
form.value.comment = '';
proxy.$modal.error("查询耳号失败,请重试");
});
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除修改电子耳号记录编号为"' + _ids + '"的数据项?').then(function () {
return delChangeEar(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => { })
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('changeEar/changeEar/export', {
...queryParams.value
}, `changeEar_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,320 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input
v-model="queryParams.sheepId"
placeholder="请输入羊只id"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery"
style="width: 150px;" />
</el-form-item>
<el-form-item label="原品种" prop="varietyOld">
<el-select v-model="queryParams.varietyOld" placeholder="请选择原品种" clearable filterable>
<el-option v-for="item in varietyOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="新品种" prop="varietyNew">
<el-select v-model="queryParams.varietyNew" placeholder="请选择新品种" clearable filterable>
<el-option v-for="item in varietyOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="创建日期" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</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="['changeVariety:changeVariety:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['changeVariety:changeVariety:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['changeVariety:changeVariety:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['changeVariety:changeVariety:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="changeVarietyList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="${comment}" align="center" prop="id" />
<el-table-column label="羊只id" align="center" prop="sheepId" /> -->
<el-table-column label="管理耳号" align="center" prop="manageTags" />
<el-table-column label="原品种" align="center" prop="varietyOld" />
<el-table-column label="新品种" align="center" prop="varietyNew" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建日期" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</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="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['changeVariety:changeVariety:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['changeVariety:changeVariety: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="500px" append-to-body>
<el-form ref="changeVarietyRef" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item> -->
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="原品种" prop="varietyOld">
<el-input v-model="form.varietyOld" placeholder="请输入原品种" :disabled="!isAdd" />
</el-form-item>
<el-form-item label="新品种" prop="varietyNew">
<el-select v-model="form.varietyNew" placeholder="请选择新品种" clearable filterable :disabled="!isAdd">
<el-option v-for="item in varietyOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="comment" v-if="!isAdd">
<el-input v-model="form.comment" placeholder="请输入备注" :disabled="!isAdd" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ChangeVariety">
import { listChangeVariety, getChangeVariety, delChangeVariety, addChangeVariety, updateChangeVariety, getSheepByManageTags } from "@/api/produce/manage_sheep/changeVariety"
import { listVariety } from '@/api/variety/variety'
const { proxy } = getCurrentInstance()
const changeVarietyList = 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 daterangeCreateTime = ref([])
const isAdd = ref(false);
const varietyOptions = ref([])
const data = reactive({
form: {
manageTags: null,
},
queryParams: {
pageNum: 1,
pageSize: 10,
// sheepId: null,
manageTags: null,
varietyOld: null,
varietyNew: null,
createTime: null
},
rules: {
manageTags: [
{ required: true, message: "请输入管理耳号", trigger: "blur" }
],
varietyOld: [
{ required: true, message: "请选择原品种", trigger: "blur" }
],
varietyNew: [
{ required: true, message: "请选择新品种", trigger: "blur" }
],
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询改品种记录列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
if (null != daterangeCreateTime && '' != daterangeCreateTime) {
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0]
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1]
}
listChangeVariety(queryParams.value).then(response => {
changeVarietyList.value = response.rows
total.value = response.total
loading.value = false
})
}
function onManageTagsBlur() {
const tag = form.value.manageTags?.trim();
if (!tag) return;
getSheepByManageTags(tag).then(res => {
const sheep = res.data;
if (sheep) {
form.value.varietyOld = sheep.varietyName || "";
form.value.sheepId = sheep.id;
form.value.comment = sheep.comment || "";
} else {
proxy.$modal.msgWarning("未找到该管理耳号对应的羊只");
form.value.varietyOld = "";
form.value.sheepId = null;
form.value.comment = "";
}
}).catch(err => {
console.error("查询羊只失败:", err);
proxy.$modal.msgError("查询失败,请重试");
});
}
function loadVarietyOptions() {
listVariety().then(res => {
varietyOptions.value = res.rows.map(item => ({
label: item.variety,
value: item.variety
}))
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
sheepId: null,
varietyOld: null,
varietyNew: null,
comment: null,
createBy: null,
createTime: null
}
proxy.resetForm("changeVarietyRef")
}
/** 搜索按钮操作 */
function handleQuery() {
loadVarietyOptions()
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
daterangeCreateTime.value = []
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()
isAdd.value = true
loadVarietyOptions()
open.value = true
title.value = "添加改品种记录"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
isAdd.value = false
loadVarietyOptions()
const _id = row.id || ids.value
getChangeVariety(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改改品种记录"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["changeVarietyRef"].validate(valid => {
if (valid) {
if (!form.value.id) {
if (!form.value.sheepId) {
proxy.$modal.msgError('未找到对应的羊只,请检查耳号');
return;
}
}
if (form.value.id != null) {
updateChangeVariety(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addChangeVariety(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除改品种记录编号为"' + _ids + '"的数据项?').then(function () {
return delChangeVariety(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => { })
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('changeVariety/changeVariety/export', {
...queryParams.value
}, `changeVariety_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
loadVarietyOptions();
getList();
});
</script>

View File

@ -1,11 +1,9 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="queryParams.sheepId" placeholder="请输入羊只id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item label="耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入耳号" clearable @keyup.enter="handleQuery" />
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入耳号" clearable @keyup.enter="handleQuery"
style="width: 150px;" />
</el-form-item>
<el-form-item label="转出羊舍" prop="foldFrom">
<el-select v-model="queryParams.foldFrom" placeholder="请选择转出羊舍" style="min-width:150px" clearable>
@ -59,15 +57,17 @@
<el-table v-loading="loading" :data="trans_groupList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="${comment}" align="center" prop="id" /> -->
<!-- <el-table-column label="羊只id" align="center" prop="sheepId" /> -->
<el-table-column label="耳号" align="center" prop="manageTags" />
<el-table-column label="管理耳号" align="center" prop="manageTags" />
<el-table-column label="转出羊舍" align="center" prop="foldFromName" />
<el-table-column label="转入羊舍" align="center" prop="foldToName" />
<el-table-column label="品种" align="center" prop="varietyName" />
<el-table-column label="转群原因" align="center" prop="reasonText" />
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="状态" align="center" prop="statusText" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime">
@ -95,27 +95,37 @@
<!-- 添加或修改转群记录对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="trans_groupRef" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item> -->
<el-form-item label="耳号" prop="manageTags">
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable collapse-tags allow-create
style="width: 100%" @change="loadSheepInfo">
<el-form-item label="管理耳号" prop="manageTags">
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable allow-create
style="width: 100%" @change="loadSheepInfo" :disabled="!isAdd">
<el-option v-for="sheep in sheepOptions" :key="sheep.id" :label="sheep.manageTags"
:value="sheep.manageTags" />
</el-select>
</el-form-item>
<!-- 在el-form中新增牧场选择项 -->
<el-form-item label="牧场" prop="ranchId">
<el-select v-model="form.ranchId" placeholder="请选择牧场" clearable @change="handleRanchChange">
<el-option v-for="ranch in ranchOptions" :key="ranch.id" :label="ranch.ranchName" :value="ranch.id" />
</el-select>
</el-form-item>
<!-- 调整转出羊舍的options为当前牧场的羊舍 -->
<el-form-item label="转出羊舍" prop="foldFrom">
<el-select v-model="form.foldFrom" placeholder="请选择转出羊舍" clearable @change="handleSheepFilter">
<el-option v-for="fold in sheepfoldOptions" :key="fold.id" :label="fold.sheepfoldName" :value="fold.id" />
<el-select v-model="form.foldFrom" placeholder="请选择转出羊舍" clearable :disabled="!form.ranchId"
@change="handleSheepFilter">
<el-option v-for="fold in currentRanchSheepfolds" :key="fold.id" :label="fold.sheepfoldName"
:value="fold.id" />
</el-select>
</el-form-item>
<!-- 调整转入羊舍的options为当前牧场的羊舍 -->
<el-form-item label="转入羊舍" prop="foldTo">
<el-select v-model="form.foldTo" placeholder="请选择转入羊舍" clearable>
<el-option v-for="fold in sheepfoldOptions" :key="fold.id" :label="fold.sheepfoldName" :value="fold.id" />
<el-select v-model="form.foldTo" placeholder="请选择转入羊舍" clearable :disabled="!form.ranchId">
<el-option v-for="fold in currentRanchSheepfolds" :key="fold.id" :label="fold.sheepfoldName"
:value="fold.id" />
</el-select>
</el-form-item>
<el-form-item label="羊只类型" prop="sheepTypeId">
<el-form-item v-if="isAdd" label="羊只类型" prop="sheepTypeId">
<el-select v-model="form.sheepTypeId" placeholder="请选择羊只类型" clearable @change="handleSheepFilter">
<el-option v-for="type in sheepTypeOptions" :key="type.id" :label="type.name" :value="type.id" />
</el-select>
@ -142,9 +152,6 @@
<!-- 审批对话框 -->
<el-dialog :title="'审批转群记录'" v-model="approveDialog" width="500px" append-to-body>
<el-form ref="approveFormRef" :model="approveForm" label-width="120px">
<!-- <el-form-item label="羊只id">
<el-input v-model="approveForm.sheepId" disabled />
</el-form-item> -->
<el-form-item label="耳号">
<el-input v-model="displayManageTags" disabled />
</el-form-item>
@ -180,33 +187,36 @@
</template>
<script setup name="Trans_group">
import { listTrans_group, getTrans_group, delTrans_group, addTrans_group, updateTrans_group } from '@/api/produce/manage_sheep/trans_group'
import { listTrans_group, getTrans_group, delTrans_group, addTrans_group, updateTrans_group, approveScTransGroup, listRanch } from '@/api/produce/manage_sheep/trans_group'
import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/sheepfold_management'
import { checkSheepByManageTags, getSheepBySheepfoldId } from '@/api/produce/other/fixHoof/fixHoof'
import { checkSheepByManageTags, getSheepBySheepfoldId } from '@/api/produce/other/fixHoof'
import request from '@/utils/request'
const { proxy } = getCurrentInstance()
const { trans_group_reason, status } = proxy.useDict('trans_group_reason', 'status')
const { proxy } = getCurrentInstance();
const { trans_group_reason, status } = proxy.useDict('trans_group_reason', 'status');
const trans_groupList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(false)
const total = ref(0)
const title = ref('')
const daterangeCreateTime = ref([])
const trans_groupList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(false);
const total = ref(0);
const title = ref('');
const daterangeCreateTime = ref([]);
const approveDialog = ref(false)
const approveForm = ref({})
const displayManageTags = ref('')
const sheepOptions = ref([])
const sheepfoldOptions = ref([])
const sheepfoldNameMap = ref({})
const varietyOptions = ref([])
const approveDialog = ref(false);
const approveForm = ref({});
const displayManageTags = ref('');
const sheepOptions = ref([]);
const sheepfoldOptions = ref([]);
const sheepfoldNameMap = ref({});
const varietyOptions = ref([]);
const sheepTypeOptions = ref([]);
const isAdd = ref(false);
const ranchOptions = ref([]);
const currentRanchSheepfolds = ref([]);
const data = reactive({
form: {
@ -218,43 +228,45 @@ const data = reactive({
pageSize: 10,
sheepId: null,
manageTags: null,
ranchId: null,
foldTo: null,
foldFrom: null,
varietyId: null,
status: null,
createTime: null
createTime: null,
},
rules: {
// sheepId: [{ required: true, message: 'id', trigger: 'blur' }],
manageTags: [{ required: true, message: '耳号不能为空', trigger: 'blue' }],
// foldFrom: [{ required: true, message: '', trigger: 'change' }],
foldTo: [{ required: true, message: '转入羊舍不能为空', trigger: 'change' }],
varietyId: [{ required: true, message: '品种不能为空', trigger: 'change' }],
reason: [{ required: true, message: '转群原因不能为空', trigger: 'change' }],
technician: [{ required: true, message: '技术员不能为空', trigger: 'blur' }]
}
})
const { queryParams, form, rules } = toRefs(data)
manageTags: [{ required: true, message: '请输入耳号', trigger: 'blur' }],
ranchId: [{ required: true, message: '请选择牧场', trigger: 'change' }],
foldTo: [{ required: true, message: '请选择转入羊舍', trigger: 'change' }],
varietyId: [{ required: true, message: '请选择品种', trigger: 'change' }],
reason: [{ required: true, message: '请选择转群原因', trigger: 'change' }],
technician: [{ required: true, message: '请输入技术员', trigger: 'blur' }],
},
});
const { queryParams, form, rules } = toRefs(data);
/** 查询转群记录列表 */
function getList() {
loading.value = true
queryParams.value.params = {}
loading.value = true;
queryParams.value.params = {};
if (daterangeCreateTime.value?.length) {
queryParams.value.params.beginCreateTime = daterangeCreateTime.value[0]
queryParams.value.params.endCreateTime = daterangeCreateTime.value[1]
queryParams.value.params.beginCreateTime = daterangeCreateTime.value[0];
queryParams.value.params.endCreateTime = daterangeCreateTime.value[1];
}
listTrans_group(queryParams.value).then(res => {
trans_groupList.value = res.rows
total.value = res.total
loading.value = false
})
listTrans_group(queryParams.value).then((res) => {
trans_groupList.value = res.rows;
total.value = res.total;
loading.value = false;
});
}
//
function reset() {
form.value = {
id: null,
sheepId: null,
ranchId: null,
foldFrom: null,
foldTo: null,
varietyId: null,
@ -263,213 +275,343 @@ function reset() {
status: null,
comment: null,
createBy: null,
createTime: null
}
proxy.resetForm('trans_groupRef')
createTime: null,
manageTags: [],
tagDetails: {},
sheepTypeId: null,
};
proxy.resetForm('trans_groupRef');
}
//
async function handleSheepFilter() {
const { foldFrom, sheepTypeId } = form.value;
sheepOptions.value = [];
let loadedSheep = [];
const { foldFrom, sheepTypeId, ranchId } = form.value;
let isOnlySheepfold = false;
let isOnlyTypeOrCombined = false;
if (!foldFrom && !sheepTypeId) return;
if (foldFrom && sheepTypeId) {
loadedSheep = await loadSheepBySheepfoldAndType(foldFrom, sheepTypeId);
if (loadedSheep.length > 0) {
form.value.manageTags = loadedSheep.map(sheep => sheep.manageTags);
loadSheepInfo();
}
} else if (foldFrom) {
loadedSheep = await loadSheepBySheepfoldOnly(foldFrom);
if (!ranchId) {
form.value.manageTags = [];
} else if (sheepTypeId) {
loadedSheep = await loadSheepByTypeOnly(sheepTypeId);
sheepOptions.value = [];
proxy.$message.warning("请先选择牧场");
return;
}
if (foldFrom && !sheepTypeId) {
isOnlySheepfold = true;
} else if (!foldFrom && sheepTypeId) {
isOnlyTypeOrCombined = true;
} else if (foldFrom && sheepTypeId) {
isOnlyTypeOrCombined = true;
} else {
form.value.manageTags = [];
sheepOptions.value = [];
return;
}
if (isOnlySheepfold) {
await loadSheepBySheepfoldOnly(foldFrom, ranchId);
} else if (isOnlyTypeOrCombined) {
form.value.manageTags = [];
let loadedSheep = [];
if (foldFrom && sheepTypeId) {
loadedSheep = await loadSheepBySheepfoldAndType(foldFrom, sheepTypeId, ranchId);
} else if (sheepTypeId) {
loadedSheep = await loadSheepByTypeOnly(sheepTypeId, ranchId);
}
if (loadedSheep.length > 0) {
form.value.manageTags = loadedSheep.map(sheep => sheep.manageTags);
loadSheepInfo();
form.value.manageTags = loadedSheep.map((sheep) => sheep.manageTags);
await loadSheepInfo();
} else {
proxy.$message.info("未查询到符合条件的耳号");
}
}
}
//
function getSheepTypeList() {
request({
url: '/base/base/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 }
}).then(res => {
sheepTypeOptions.value = res.rows || [];
}).catch(error => {
console.error('获取羊只类型失败', error);
proxy.$modal.msgError('加载羊只类型失败,请重试');
return new Promise((resolve, reject) => {
request({
url: '/base/base/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 },
}).then((res) => {
sheepTypeOptions.value = res.rows.map(item => ({
id: Number(item.id),
name: item.name || item.typeName
})) || [];
resolve();
}).catch((error) => {
console.error('获取羊只类型失败', error);
proxy.$modal.msgError('加载羊只类型失败,请重试');
reject(error);
});
});
}
//
function loadRanchList() {
listRanch().then(res => {
ranchOptions.value = res.rows.map(ranch => ({
id: ranch.id,
ranchName: ranch.ranch
}));
}).catch(error => {
console.error('加载牧场列表失败', error);
proxy.$modal.msgError('获取牧场数据失败');
});
}
//
function handleRanchChange(ranchId) {
form.value.foldFrom = null;
form.value.foldTo = null;
if (!ranchId) {
currentRanchSheepfolds.value = [];
return;
}
request({
url: '/sheepfold_management/sheepfold_management/list',
method: 'get',
params: { ranchId, pageNum: 1, pageSize: 9999 }
}).then(res => {
currentRanchSheepfolds.value = res.rows || [];
if (currentRanchSheepfolds.value.length === 0) {
proxy.$modal.msgWarning(`所选牧场ID:${ranchId})暂无羊舍数据`);
}
}).catch(error => {
console.error('加载牧场羊舍失败', error);
proxy.$modal.msgError('获取羊舍数据失败');
currentRanchSheepfolds.value = [];
});
}
//
async function loadSheepBySheepfoldOnly(sheepfoldId, ranchId) {
if (!sheepfoldId || isNaN(Number(sheepfoldId))) {
proxy.$message.error('请选择有效的羊舍');
sheepOptions.value = [];
return [];
}
if (!ranchId) {
proxy.$message.error('牧场信息异常,请重新选择');
sheepOptions.value = [];
return [];
}
try {
const res = await getSheepBySheepfoldId(Number(sheepfoldId));
const newSheepList = (res.data || []).map((sheep) => ({
id: sheep.id,
manageTags: sheep.manageTags || '未知耳号',
sheepfoldId: Number(sheepfoldId),
})).filter(item => item.manageTags);
if (newSheepList.length === 0) {
proxy.$message.info('当前羊舍下暂无羊只数据');
sheepOptions.value = [];
return [];
}
sheepOptions.value = newSheepList;
return newSheepList;
} catch (error) {
console.error('根据羊舍加载耳号失败:', error);
const errorMsg = error.response?.data?.msg || '加载羊舍耳号失败,请重试';
proxy.$modal.msgError(errorMsg);
sheepOptions.value = [];
return [];
}
}
//
async function loadSheepBySheepfoldAndType(sheepfoldId, typeId) {
try {
const res = await request({
url: '/sheep/sheep/listBySheepfoldAndType',
method: 'get',
params: { sheepfoldId, typeId, _t: Date.now() }
params: { sheepfoldId, typeId, _t: Date.now() },
});
const sheepList = res.rows || [];
const formattedSheep = sheepList.map(sheep => ({
const formattedSheep = sheepList.map((sheep) => ({
id: sheep.id,
manageTags: sheep.manageTags,
sheepfoldId: sheepfoldId
sheepfoldId: sheepfoldId,
}));
sheepOptions.value = formattedSheep;
if (sheepOptions.value.length === 0) {
proxy.$message.error(`该羊舍没有该类型羊只`);
}
return formattedSheep;
} catch (error) {
console.error('根据羊舍+类型加载耳号失败', error);
proxy.$modal.msgError("加载耳号失败,请重试");
return [];
}
}
async function loadSheepBySheepfoldOnly(sheepfoldId) {
try {
const res = await getSheepBySheepfoldId(String(sheepfoldId));
const sheepList = res.data || [];
const formattedSheep = sheepList.map(sheep => ({
id: sheep.id,
manageTags: sheep.manageTags,
sheepfoldId: sheepfoldId
}));
sheepOptions.value = formattedSheep;
if (sheepOptions.value.length === 0) {
proxy.$message.error(`该羊舍下没有羊只数据`);
} else {
proxy.$message.success(`成功加载 ${sheepOptions.value.length} 个耳号`);
}
return formattedSheep;
} catch (error) {
console.error('根据羊舍加载耳号失败', error);
proxy.$modal.msgError("加载羊舍耳号失败,请重试");
proxy.$modal.msgError('加载耳号失败,请重试');
return [];
}
}
//
async function loadSheepByTypeOnly(typeId) {
try {
const res = await request({
url: '/sheep/sheep/listByTypeId',
method: 'get',
params: { typeId }
params: { typeId },
});
const sheepList = res.rows || [];
const formattedSheep = sheepList.map(sheep => ({
const formattedSheep = sheepList.map((sheep) => ({
id: sheep.id,
manageTags: sheep.manageTags,
sheepfoldId: sheep.sheepfoldId
sheepfoldId: sheep.sheepfoldId,
}));
sheepOptions.value = formattedSheep;
if (sheepOptions.value.length === 0) {
proxy.$message.error(`未查询到“${getSheepTypeName(typeId)}”类型的羊只`);
}
return formattedSheep;
} catch (error) {
console.error('根据类型加载耳号失败', error);
proxy.$modal.msgError("加载耳号失败,请重试");
proxy.$modal.msgError('加载耳号失败,请重试');
return [];
}
}
function getSheepTypeName(typeId) {
if (!typeId) return '未知类型';
const type = sheepTypeOptions.value.find(item => item.id === typeId);
return type ? type.name : '未知类型';
}
//
async function loadSheepInfo() {
const tags = form.value.manageTags;
if (!tags || tags.length === 0) return;
const tags = form.value.manageTags;
if (!tags || tags.length === 0) return;
const tagDetails = {};
const validResults = [];
const tagDetails = {};
const validResults = [];
let firstSheepfoldId = null;
let firstRanchId = null;
for (const tag of tags) {
try {
const { data: sheepData } = await checkSheepByManageTags(tag.trim());
if (!sheepData) {
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 不存在或信息异常`);
} else {
validResults.push(true);
tagDetails[tag] = {
comment: sheepData.comment || '',
varietyId: sheepData.varietyId,
sheepId: sheepData.id,
sheepfoldId: sheepData.sheepfoldId
};
}
} catch (error) {
console.error('获取耳号信息失败:', error);
proxy.$modal.msgError(`耳号 ${tag} 验证失败,请重试`);
validResults.push(false);
for (const tag of tags) {
try {
const { data: sheepData } = await checkSheepByManageTags(tag.trim());
if (!sheepData) {
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 不存在或信息异常`);
} else {
validResults.push(true);
tagDetails[tag] = {
comment: sheepData.comment || '',
varietyId: sheepData.varietyId,
sheepId: sheepData.id,
sheepfoldId: sheepData.sheepfoldId,
};
if (!firstSheepfoldId) {
firstSheepfoldId = sheepData.sheepfoldId;
firstRanchId = sheepData.ranchId;
}
}
} catch (error) {
console.error('获取耳号信息失败:', error);
proxy.$modal.msgError(`耳号 ${tag} 验证失败,请重试`);
validResults.push(false);
}
}
}
if (validResults.includes(false)) {
form.value.manageTags = tags.filter((_, index) => validResults[index]);
proxy.$message.warning('部分耳号不合法,已自动过滤');
}
form.value.tagDetails = tagDetails;
if (validResults.includes(false)) {
form.value.manageTags = tags.filter((_, index) => validResults[index]);
proxy.$message.warning('部分耳号不合法,已自动过滤');
}
form.value.tagDetails = tagDetails;
if (firstRanchId && isAdd.value) {
form.value.ranchId = firstRanchId;
handleRanchChange(firstRanchId);
}
if (firstSheepfoldId && isAdd.value) {
form.value.foldFrom = Number(firstSheepfoldId);
}
}
//
function cancel() {
open.value = false
reset()
open.value = false;
reset();
}
//
function handleQuery() {
queryParams.value.pageNum = 1
getList()
queryParams.value.pageNum = 1;
getList();
}
//
function resetQuery() {
daterangeCreateTime.value = []
proxy.resetForm('queryRef')
handleQuery()
daterangeCreateTime.value = [];
proxy.resetForm('queryRef');
handleQuery();
}
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id)
single.value = selection.length !== 1
multiple.value = !selection.length
ids.value = selection.map((item) => item.id);
single.value = selection.length !== 1;
multiple.value = !selection.length;
}
//
function handleAdd() {
reset();
open.value = true;
title.value = '添加转群记录';
isAdd.value = true;
sheepOptions.value = [];
form.value.manageTags = [];
}
function handleUpdate(row) {
//
async function handleUpdate(row) {
reset();
const _id = row.id || ids.value;
loading.value = true;
isAdd.value = false;
const { data: d } = await getTrans_group(_id);
getTrans_group(_id).then(res => {
const d = res.data;
d.foldFrom = Number(d.foldFrom ?? 0);
d.foldTo = Number(d.foldTo ?? 0);
d.reason = Number(d.reason ?? 0);
d.status = Number(d.status ?? 0);
d.varietyId = Number(d.varietyId ?? 0);
try {
await Promise.all([
sheepfoldOptions.value.length === 0 ? loadSheepfold() : Promise.resolve(),
sheepTypeOptions.value.length === 0 ? getSheepTypeList() : Promise.resolve()
]);
form.value = { ...d, manageTags: d.manageTags, isEdit: true };
const { data: d } = await getTrans_group(_id);
handleSheepFilter();
const manageTags = Array.isArray(d.manageTags)
? d.manageTags
: d.manageTags ? [d.manageTags] : [];
const formData = {
...d,
manageTags: manageTags,
foldFrom: Number(d.foldFrom || 0),
foldTo: Number(d.foldTo || 0),
sheepTypeId: Number(d.sheepTypeId || 0),
reason: Number(d.reason || 0),
status: Number(d.status || 0),
varietyId: Number(d.varietyId || 0),
isEdit: true
};
form.value = formData;
form.value.ranchId = row.ranchId;
handleRanchChange(row.ranchId);
isAdd.value = false;
if (manageTags.length > 0) {
await loadSheepInfo();
}
open.value = true;
title.value = '修改转群记录';
});
} catch (error) {
console.error('修改加载失败:', error);
proxy.$modal.msgError('加载数据失败');
} finally {
loading.value = false;
}
}
//
function submitForm() {
proxy.$refs.trans_groupRef.validate(valid => {
proxy.$refs.trans_groupRef.validate((valid) => {
if (!valid) return;
const allTags = form.value.manageTags;
@ -501,78 +643,91 @@ function submitForm() {
open.value = false;
getList();
})
.catch(error => {
.catch((error) => {
proxy.$modal.msgError(`处理失败:${error.message}`);
});
});
}
//
function handleDelete(row) {
const _ids = row.id || ids.value
const _ids = row.id || ids.value;
proxy.$modal.confirm(`是否确认删除转群记录编号为“${_ids}”的数据项?`)
.then(() => delTrans_group(_ids))
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
getList();
proxy.$modal.msgSuccess('删除成功');
});
}
//
function handleExport() {
proxy.download(
'/produce/manage_sheep/trans_group/export',
{ ...queryParams.value },
`trans_group_${Date.now()}.xlsx`
)
);
}
//
//
function handleApprove(row) {
approveForm.value = { ...row }
approveDialog.value = true
approveForm.value = { ...row };
approveDialog.value = true;
displayManageTags.value = row.manageTags;
}
//
function handleApproveAgree() {
approveForm.value.status = 1
updateTrans_group(approveForm.value).then(() => {
approveDialog.value = false
proxy.$modal.msgSuccess('审批成功,状态已更新为同意')
getList()
})
}
function handleApproveReject() {
approveForm.value.status = 2
updateTrans_group(approveForm.value).then(() => {
approveDialog.value = false
proxy.$modal.msgSuccess('审批成功,状态已更新为驳回')
getList()
})
if (typeof approveForm.value.foldTo !== 'number') {
approveForm.value.foldTo = Number(approveForm.value.foldTo);
}
approveForm.value.status = 1;
approveScTransGroup(approveForm.value).then(() => {
approveDialog.value = false;
proxy.$modal.msgSuccess('审批通过,羊只所在羊舍已更新');
getList();
}).catch(error => {
proxy.$modal.msgError(`审批失败:${error.message}`);
});
}
function loadSheepfold() {
listSheepfold({ pageNum: 1, pageSize: 9999 }).then(res => {
sheepfoldOptions.value = res.rows
sheepfoldNameMap.value = res.rows.reduce((acc, item) => {
acc[item.id] = item.sheepfoldName
return acc
}, {})
})
function handleApproveReject() {
approveForm.value.status = 2;
approveScTransGroup(approveForm.value).then(() => {
approveDialog.value = false;
proxy.$modal.msgSuccess('审批已驳回');
getList();
}).catch(error => {
proxy.$modal.msgError(`审批失败:${error.message}`);
});
}
//
function loadSheepfold() {
listSheepfold({ pageNum: 1, pageSize: 9999 }).then((res) => {
sheepfoldOptions.value = res.rows;
sheepfoldNameMap.value = res.rows.reduce((acc, item) => {
acc[item.id] = item.sheepfoldName;
return acc;
}, {});
});
}
//
function getVarietyOptions() {
request({
url: '/base/variety/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 }
}).then(res => {
params: { pageNum: 1, pageSize: 9999 },
}).then((res) => {
varietyOptions.value = res.rows || [];
});
}
onMounted(() => {
loadSheepfold();
loadRanchList();
getVarietyOptions();
getSheepTypeList();
getList();
})
});
</script>

View File

@ -1,36 +1,34 @@
<template>
<div class="app-container">
<!-- 查询表单 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
<el-form-item label="羊只id" prop="sheepId">
<el-input v-model="queryParams.sheepId" placeholder="请输入羊只id" clearable @keyup.enter="handleQuery" />
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery" style="width: 150px;"/>
</el-form-item>
<el-form-item label="品种" prop="varietyId">
<el-select v-model="queryParams.varietyId" placeholder="请选择品种" style="min-width:150px" clearable>
<el-option v-for="item in varietyOptions" :key="item.id" :label="item.variety" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="转入牧场" prop="transTo">
<el-input v-model="queryParams.transTo" placeholder="请输入转入牧场" clearable @keyup.enter="handleQuery" />
<el-select v-model="queryParams.transTo" placeholder="请选择转入牧场" clearable style="min-width:150px">
<el-option v-for="ranch in ranchOptions" :key="ranch.id" :label="ranch.ranchName" :value="ranch.ranchName" />
</el-select>
</el-form-item>
<el-form-item label="当前牧场" prop="transFrom">
<el-input v-model="queryParams.transFrom" placeholder="请输入当前牧场" clearable @keyup.enter="handleQuery" />
<el-select v-model="queryParams.transFrom" placeholder="请选择当前牧场" clearable style="min-width:150px">
<el-option v-for="ranch in ranchOptions" :key="ranch.id" :label="ranch.ranchName" :value="ranch.ranchName" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" style="width: 150px" placeholder="请选择状态" clearable>
<el-option v-for="dict in status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@ -41,19 +39,19 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd"
v-hasPermi="['transition_info:transition_info:add']">新增</el-button>
v-hasPermi="['transition_info:transition_info:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['transition_info:transition_info:edit']">修改</el-button>
v-hasPermi="['transition_info:transition_info:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['transition_info:transition_info:remove']">删除</el-button>
v-hasPermi="['transition_info:transition_info:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['transition_info:transition_info:export']">导出</el-button>
v-hasPermi="['transition_info:transition_info:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</el-row>
@ -61,21 +59,17 @@
<!-- 列表 -->
<el-table v-loading="loading" :data="transition_infoList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="羊只id" align="center" prop="sheepId" />
<el-table-column label="品种" align="center" prop="varietyName" />
<el-table-column label="耳号" align="center" prop="manageTags" />
<el-table-column label="品种" align="center" prop="varietyName" />
<el-table-column label="转入牧场" align="center" prop="transTo" />
<el-table-column label="当前牧场" align="center" prop="transFrom" />
<el-table-column label="转场类型" align="center" prop="transType">
<template #default="scope">
<dict-tag :options="trans_type" :value="scope.row.transType" />
</template>
</el-table-column>
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="状态" align="center" prop="statusText" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
@ -86,52 +80,50 @@
<el-table-column label="操作" align="center" min-width="180">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleApprove(scope.row)"
v-hasPermi="['transition_info:transition_info:approve']">审批</el-button>
v-hasPermi="['transition_info:transition_info:approve']">审批</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['transition_info:transition_info:remove']">删除</el-button>
v-hasPermi="['transition_info:transition_info: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" />
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 新增/修改 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="transition_infoRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="羊只id" prop="sheepId">
<el-input v-model="form.sheepId" placeholder="请输入羊只id" />
</el-form-item>
<el-form-item label="品种" prop="varietyId">
<el-select v-model="form.varietyId" placeholder="请选择品种" clearable>
<el-option v-for="item in varietyOptions" :key="item.id"
:label="item.variety" :value="Number(item.id)" />
<el-form-item label="管理耳号" prop="manageTags">
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" filterable multiple allow-create
@change="loadSheepInfo" :disabled="!isAdd" >
<el-option v-for="sheep in sheepOptions" :key="sheep.id" :label="sheep.manageTags"
:value="sheep.manageTags" />
</el-select>
</el-form-item>
<el-form-item label="转入牧场" prop="transTo">
<el-input v-model="form.transTo" placeholder="请输入转入牧场" />
<el-select v-model="form.transTo" placeholder="请选择转入牧场" clearable :disabled="!isAdd" >
<el-option v-for="ranch in ranchOptions" :key="ranch.id" :label="ranch.ranchName"
:value="ranch.ranchName" />
</el-select>
</el-form-item>
<el-form-item label="当前牧场" prop="transFrom">
<el-input v-model="form.transFrom" placeholder="请输入当前牧场" />
<el-select v-model="form.transFrom" placeholder="请选择当前牧场" clearable @change="handleRanchChange" :disabled="!isAdd" >
<el-option v-for="ranch in ranchOptions" :key="ranch.id" :label="ranch.ranchName"
:value="ranch.ranchName" />
</el-select>
</el-form-item>
<el-form-item label="转场类型" prop="transType">
<el-select v-model="form.transType" placeholder="请选择转场类型">
<el-option v-for="dict in trans_type" :key="dict.value"
:label="dict.label" :value="parseInt(dict.value)" />
<el-option v-for="dict in trans_type" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)" />
</el-select>
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-input v-model="form.technician" placeholder="请输入技术员" />
</el-form-item>
<el-form-item label="备注" prop="comment">
<el-input v-model="form.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
@ -145,15 +137,30 @@
<!-- 审批对话框 -->
<el-dialog :title="'审批转场记录'" v-model="approveDialog" width="500px" append-to-body>
<el-form ref="approveFormRef" :model="approveForm" label-width="120px">
<el-form-item label="羊只id"><el-input v-model="approveForm.sheepId" disabled /></el-form-item>
<el-form-item label="品种"><el-input :value="approveForm.varietyName" disabled /></el-form-item>
<el-form-item label="转入牧场"><el-input v-model="approveForm.transTo" disabled /></el-form-item>
<el-form-item label="当前牧场"><el-input v-model="approveForm.transFrom" disabled /></el-form-item>
<el-form-item label="转场类型">
<el-input :value="getTransTypeLabel(approveForm.transType)" disabled />
<el-form-item label="管理耳号">
<el-input v-model="displayManageTags" disabled />
</el-form-item>
<el-form-item label="品种">
<el-input :value="approveForm.varietyName" disabled />
</el-form-item>
<el-form-item label="转入牧场">
<el-input :value="approveForm.transTo" disabled />
</el-form-item>
<el-form-item label="当前牧场">
<el-input :value="approveForm.transFrom" disabled />
</el-form-item>
<el-form-item label="转场类型">
<el-input :value="approveForm.transTypeText || '未知类型'" disabled />
</el-form-item>
<el-form-item label="技术员">
<el-input v-model="approveForm.technician" disabled />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="approveForm.comment" disabled />
</el-form-item>
<el-form-item label="状态">
<el-input :value="getStatusLabel(approveForm.status)" disabled />
</el-form-item>
<el-form-item label="技术员"><el-input v-model="approveForm.technician" disabled /></el-form-item>
<el-form-item label="备注"><el-input v-model="approveForm.comment" disabled /></el-form-item>
</el-form>
<template #footer>
@ -167,36 +174,47 @@
</template>
<script setup name="Transition_info">
import { listTransition_info, getTransition_info, delTransition_info, addTransition_info, updateTransition_info } from "@/api/produce/manage_sheep/transition_info"
import { listTransition_info, getTransition_info, delTransition_info, addTransition_info, getSheepByRanchId, updateTransition_info, listRanch,approveTransitionInfo } from "@/api/produce/manage_sheep/transition_info"
import { checkSheepByManageTags, getSheepBySheepfoldId } from '@/api/produce/other/fixHoof'
import request from '@/utils/request'
const { proxy } = getCurrentInstance()
const { status, trans_type } = proxy.useDict('status', 'trans_type')
/* -------------------- 响应式数据 -------------------- */
const transition_infoList = 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 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 daterangeCreateTime = ref([])
const approveDialog = ref(false)
const approveForm = ref({})
const approveForm = ref({})
const displayManageTags = ref('')
const varietyOptions = ref([])
const ranchOptions = ref([]);
const sheepOptions = ref([]);
const isAdd = ref(true);
const isEdit = ref(false);
/* -------------------- 查询 / 表单 -------------------- */
const data = reactive({
form: {},
form: {
id: null,
manageTags: [],
transTo: null,
transFrom: null,
transType: null,
technician: null,
tagDetails: {}
},
queryParams: {
pageNum: 1,
pageSize: 10,
sheepId: null,
manageTags: [],
varietyId: null,
transTo: null,
transFrom: null,
@ -204,103 +222,384 @@ const data = reactive({
createTime: null
},
rules: {
sheepId: [
{ required: true, message: "羊只id不能为空", trigger: "blur" }
],
varietyId: [
{ required: true, message: "品种不能为空", trigger: "change" }
manageTags:[
{ required: true, message: "请输入管理耳号", trigger: "blur" }
],
transTo: [
{ required: true, message: "转入牧场不能为空", trigger: "blur" }
{ required: true, message: "请输入转入牧场", trigger: "blur" }
],
transFrom: [
{ required: true, message: "当前牧场不能为空", trigger: "blur" }
{ required: false, message: "请选择当前牧场", trigger: "blur" }
],
transType: [
{ required: true, message: "转场类型不能为空", trigger: "change" }
{ required: true, message: "请选择转场类型", trigger: "change" }
],
technician: [
{ required: true, message: "技术员不能为空", trigger: "blur" }
{ required: true, message: "请输入技术员", trigger: "blur" }
]
}
})
const { queryParams, form, rules } = toRefs(data)
/* -------------------- 基础方法 -------------------- */
//
function getList() {
loading.value = true
queryParams.value.params = {}
if (daterangeCreateTime.value?.length) {
queryParams.value.params.beginCreateTime = daterangeCreateTime.value[0]
queryParams.value.params.endCreateTime = daterangeCreateTime.value[1]
queryParams.value.params.endCreateTime = daterangeCreateTime.value[1]
}
listTransition_info(queryParams.value).then(res => {
transition_infoList.value = res.rows
total.value = res.total
loading.value = false
total.value = res.total
loading.value = false
})
}
//
function reset() {
form.value = {
id: null,
sheepId: null,
varietyId: null,
manageTags: [],
transTo: null,
transFrom: null,
transType: null,
technician: null,
status: null,
comment: null,
createBy: null,
createTime: null
}
proxy.resetForm("transition_infoRef")
createBy:null,
tagDetails: {}
};
sheepOptions.value = [];
proxy.resetForm("transition_infoRef");
isAdd.value = true;
isEdit.value = false;
}
//
function loadRanchOptions() {
return listRanch()
.then((res) => {
if (res.rows && Array.isArray(res.rows)) {
const mapped = res.rows.map((ranch) => ({
id: Number(ranch.id),
ranchName: ranch.ranch || '未知牧场',
}));
ranchOptions.value = mapped;
} else {
}
})
.catch((error) => {
proxy.$modal.msgError('获取牧场数据失败');
});
}
//
function loadSheepOptions() {
getSheepBySheepfoldId().then(res => {
sheepOptions.value = res.data?.map(sheep => ({
id: sheep.id,
manageTags: sheep.manageTags
})) || [];
}).catch(error => {
console.error('加载耳号选项失败', error);
});
}
// ID
async function getRanchNameByRanchId(ranchId) {
if (!ranchId) return '';
try {
if (ranchOptions.value.length === 0) {
await loadRanchOptions();
}
const matchedRanch = ranchOptions.value.find(
(item) => item.id === Number(ranchId)
);
return matchedRanch ? matchedRanch.ranchName : '';
} catch (error) {
console.error('通过 ranchId 查询牧场名称失败:', error);
return '';
}
}
function handleRanchChange(ranchName) {
if (!ranchName) {
sheepOptions.value = [];
form.value.manageTags = [];
return;
}
const matchedRanch = ranchOptions.value.find(
(ranch) => ranch.ranchName === ranchName
);
if (!matchedRanch) {
proxy.$modal.msgError('未找到该牧场信息,请重新选择');
return;
}
const ranchIdNum = matchedRanch.id;
getSheepByRanchId(ranchIdNum)
.then((res) => {
if (res.code === 200) {
if (res.data && res.data.length > 0) {
sheepOptions.value = res.data.map((sheep) => ({
id: sheep.id,
manageTags: sheep.manageTags,
}));
} else {
sheepOptions.value = [];
proxy.$message.error('该牧场暂无羊只数据');
}
} else {
sheepOptions.value = [];
proxy.$modal.msgError('获取羊只数据失败,请重试');
}
})
.catch((error) => {
console.error('羊只列表加载失败:', error);
sheepOptions.value = [];
proxy.$modal.msgError('获取羊只信息失败,请重试');
});
}
async function loadSheepInfo() {
if (isEdit.value) {
return;
}
const tags = form.value.manageTags;
if (!tags || tags.length === 0) return;
const tagDetails = {};
const validResults = [];
for (const tag of tags) {
try {
const { data: sheepData } = await checkSheepByManageTags(tag.trim());
if (!sheepData) {
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 不存在或已删除`);
continue;
}
const ranchName = await getRanchNameByRanchId(sheepData.ranchId);
tagDetails[tag] = {
sheepId: sheepData.id,
varietyId: sheepData.varietyId,
varietyName: sheepData.varietyName || '',
ranchName: ranchName,
comment: sheepData.comment || ''
};
validResults.push(true);
if (!form.value.transFrom && tags.indexOf(tag) === 0) {
form.value.transFrom = ranchName;
}
} catch (error) {
console.error('获取耳号信息失败:', error);
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 验证失败`);
}
}
if (validResults.includes(false)) {
form.value.manageTags = tags.filter((_, index) => validResults[index]);
proxy.$message.warning('部分耳号不合法,已过滤');
}
form.value.tagDetails = tagDetails;
}
//
function handleExport() {
proxy.download(
'/produce/manage_sheep/transition_info/export',
{ ...queryParams.value },
`transition_info_${Date.now()}.xlsx`
);
}
//
function handleApprove(row) {
approveForm.value = { ...row };
approveDialog.value = true;
displayManageTags.value = Array.isArray(row.manageTags)
? row.manageTags.join(',')
: row.manageTags || '';
}
//
function handleApproveAgree() {
if (!approveForm.value.transTo) {
proxy.$modal.msgError('转入牧场不能为空');
return;
}
approveForm.value.status = 1;
approveTransitionInfo(approveForm.value).then(() => {
approveDialog.value = false;
proxy.$modal.msgSuccess('审批通过,已更新羊只所在牧场');
getList();
}).catch(error => {
proxy.$modal.msgError(`审批失败:${error.message}`);
});
}
//
function handleApproveReject() {
approveForm.value.status = 2;
updateTransition_info(approveForm.value).then(() => {
approveDialog.value = false;
proxy.$modal.msgSuccess('审批成功,状态已更新为驳回');
getList();
});
}
//
function getTransTypeLabel(value) {
const transTypeArray = trans_type.value;
if (!Array.isArray(transTypeArray)) {
return '未知类型';
}
const item = transTypeArray.find(item => item.value === value);
return item ? item.label : '未知类型';
}
//
function getStatusLabel(value) {
const statusArray = status.value;
if (!Array.isArray(statusArray)) {
return '未知状态';
}
const item = statusArray.find(item => item.value === value);
return item ? item.label : '未知状态';
}
//
function cancel() {
open.value = false
reset()
}
//
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
//
function resetQuery() {
daterangeCreateTime.value = []
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
title.value = "添加转场"
reset();
open.value = true;
title.value = "添加转场";
isAdd.value = true;
isEdit.value = false;
sheepOptions.value = [];
form.value.manageTags = [];
}
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
//
async function handleUpdate(row) {
reset();
const _id = row.id || ids.value;
getTransition_info(_id).then(response => {
form.value = response.data
open.value = true
title.value = "修改转场"
})
form.value = {
...response.data,
manageTags: [response.data.manageTags]
};
open.value = true;
title.value = "修改转场";
isAdd.value = false;
isEdit.value = true;
}).catch(error => {
console.error('获取转场详情失败:', error);
proxy.$modal.msgError('加载数据失败,请重试');
});
}
function submitForm() {
proxy.$refs["transition_infoRef"].validate(valid => {
if (!valid) return
const api = form.value.id ? updateTransition_info : addTransition_info
api(form.value).then(() => {
proxy.$modal.msgSuccess(form.value.id ? "修改成功" : "新增成功")
open.value = false
getList()
})
})
//
async function submitForm() {
proxy.$refs.transition_infoRef.validate(async (valid) => {
if (!valid) return;
const allTags = form.value.manageTags;
let validTags = [];
if (isAdd.value) {
if (!allTags || allTags.length === 0) {
proxy.$modal.msgError('请选择至少一个耳号');
return;
}
const tagDetails = form.value.tagDetails || {};
validTags = allTags.filter(tag => tagDetails[tag]);
if (validTags.length === 0) {
proxy.$modal.msgError('所有耳号均无效,请重新输入');
return;
}
} else {
validTags = allTags;
}
let submitData = {};
if (isAdd.value) {
submitData = validTags.map(tag => ({
sheepId: form.value.tagDetails[tag].sheepId,
varietyId: form.value.tagDetails[tag].varietyId,
varietyName: form.value.tagDetails[tag].varietyName,
manageTags: tag,
transTo: form.value.transTo,
transFrom: form.value.tagDetails[tag].ranchName,
transType: form.value.transType,
technician: form.value.technician,
comment: form.value.tagDetails[tag].comment,
status: 0,
}));
} else {
submitData = {
...form.value,
manageTags: validTags.join(','),
};
}
try {
if (isAdd.value) {
await addTransition_info(submitData);
} else {
await updateTransition_info(submitData);
}
proxy.$modal.msgSuccess(isAdd.value ? '提交成功' : '修改成功');
open.value = false;
getList();
} catch (error) {
proxy.$modal.msgError(isAdd.value ? '提交失败,请重试' : '修改失败,请重试');
}
});
}
//
function getVarietyOptions() {
request({
url: '/base/variety/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 },
}).then((res) => {
varietyOptions.value = res.rows || [];
});
}
//
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除转场编号为"' + _ids + '"的数据项?')
@ -311,6 +610,11 @@ function handleDelete(row) {
})
}
getList()
</script>
onMounted(() => {
loadRanchOptions();
getVarietyOptions();
loadSheepOptions();
getList();
});
</script>

View File

@ -2,8 +2,8 @@
<div class="app-container">
<!-- 搜索区域 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入耳号" clearable @keyup.enter="handleQuery" />
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery" style="width: 150px;"/>
</el-form-item>
<el-form-item label="羊舍" prop="sheepfold">
@ -60,6 +60,7 @@
<el-table-column label="品种" align="center" prop="varietyName" />
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
@ -82,9 +83,9 @@
<!-- 新增/修改弹窗 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="castrateRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="耳号" prop="manageTags">
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable collapse-tags allow-create
style="width: 100%" @change="loadSheepInfo">
<el-form-item label="管理耳号" prop="manageTags">
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable allow-create
style="width: 100%" @change="loadSheepInfo" @blur="loadSheepInfo">
<el-option v-for="sheep in sheepOptions" :key="sheep.id" :label="sheep.manageTags"
:value="sheep.manageTags" />
</el-select>
@ -134,7 +135,7 @@ const data = reactive({
manageTags: [],
sheepfold: null,
technician: null,
tagDetails: {}
tagDetails: {}
},
queryParams: {
pageNum: 1,
@ -151,18 +152,19 @@ const data = reactive({
// { required: true, message: 'id', trigger: 'blur' }
// ],
manageTags: [
{ required: true, message: '耳号不能为空', trigger: 'blur' }
{ required: true, message: '请输入管理耳号', trigger: 'blur' }
],
sheepfold: [
{ required: true, message: '羊舍不能为空', trigger: 'change' }
{ required: true, message: '请选择羊舍', trigger: 'change' }
],
technician: [
{ required: true, message: '技术员不能为空', trigger: 'blur' }
{ required: true, message: '请输入技术员', trigger: 'blur' }
]
}
})
const { queryParams, form, rules } = toRefs(data)
//
function loadSheepBySheepfold() {
const sheepfoldId = form.value.sheepfold;
if (!sheepfoldId) {
@ -170,23 +172,26 @@ function loadSheepBySheepfold() {
return;
}
//
getSheepBySheepfoldId(sheepfoldId)
.then(res => {
const sheepList = res.data || [];
let sheepList = res.data || [];
sheepList = sheepList.filter(sheep => sheep.gender === 2);
if (sheepList.length === 0) {
proxy.$modal.msgInfo('该羊舍暂无可用耳号');
proxy.$modal.msgInfo('该羊舍下暂无性别为公的羊只');
sheepOptions.value = [];
return;
}
sheepOptions.value = sheepList.map(sheep => ({
id: sheep.id,
manageTags: sheep.manageTags,
sheepfoldId: sheepfoldId
gender: sheep.gender
}));
})
.catch(error => {
console.error('加载羊舍耳号失败', error);
proxy.$modal.msgError(`加载耳号失败: ${error.message}`);
proxy.$modal.msgError('加载耳号失败,请重试');
sheepOptions.value = [];
});
}
@ -196,44 +201,45 @@ async function loadSheepInfo() {
const tags = form.value.manageTags;
if (!tags || tags.length === 0) return;
const tagDetails = {}; //
const tagDetails = {};
const validResults = [];
for (const tag of tags) {
try {
const { data: sheepData } = await checkSheepByManageTags(tag.trim());
if (!sheepData) {
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 不存在`);
} else if (sheepData.gender !== 2) {
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 对应的羊只性别不是公,无法添加`);
} else {
validResults.push(true);
//
tagDetails[tag] = {
comment: sheepData.comment || '', //
varietyId: sheepData.varietyId,
sheepId: sheepData.id,
gender: sheepData.gender,
sheepfoldId: sheepData.sheepfoldId,
sheepId: sheepData.id
varietyId: sheepData.varietyId,
comment: sheepData.comment || ''
};
//
if (validResults.length === 1) {
form.value.sheepfold = sheepData.sheepfoldId;
}
}
} catch (error) {
console.error('获取耳号信息失败:', error);
proxy.$modal.msgError(`耳号 ${tag} 验证失败`);
console.error(`耳号 ${tag} 校验失败`, error);
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 校验异常,请重试`);
}
}
//
if (validResults.includes(false)) {
form.value.manageTags = tags.filter((_, index) => validResults[index]);
proxy.$message.warning('部分耳号不合法,已过滤');
}
//
form.value.manageTags = tags.filter((_, index) => validResults[index]);
form.value.tagDetails = tagDetails;
if (validResults.includes(false)) {
proxy.$message.warning('部分耳号不符合条件(不存在或非公羊),已自动过滤');
}
}
/** 查询列表 */
@ -254,13 +260,19 @@ function getList() {
total.value = res.total;
loading.value = false;
});
getVarietyOptions({ pageNum: 1, pageSize: 9999 }).then(res => {
varietyOptions.value = res.rows || []
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
@ -272,11 +284,13 @@ function reset() {
proxy.resetForm('castrateRef');
}
//
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
//
function resetQuery() {
daterangeCreateTime.value = []
proxy.resetForm('queryRef')
@ -289,12 +303,14 @@ function handleSelectionChange(selection) {
multiple.value = !selection.length
}
//
function handleAdd() {
reset()
open.value = true
title.value = '添加去势'
}
//
function handleUpdate(row) {
reset();
const _id = row.id || ids.value;
@ -320,7 +336,7 @@ function handleUpdate(row) {
});
}
//
//
async function validateAllTags() {
const tags = form.value.manageTags || [];
if (tags.length === 0) return;
@ -339,47 +355,53 @@ async function validateAllTags() {
}
}
//
function submitForm() {
proxy.$refs.castrateRef.validate(valid => {
if (!valid) return;
const allTags = form.value.manageTags;
const tagDetails = form.value.tagDetails || {};
if (!allTags || allTags.length === 0) {
proxy.$modal.msgError('请选择耳号');
proxy.$modal.msgError('请选择有效的公羊耳号');
return;
}
//
const requests = allTags.map(async (tag) => {
const details = tagDetails[tag] || {};
const formData = {
...form.value,
manageTags: tag,
comment: details.comment || '', //
sheepId: details.sheepId,
varietyId: details.varietyId,
sheepfold: details.sheepfoldId || form.value.sheepfold
};
const invalidTags = allTags.filter(tag => {
const details = tagDetails[tag];
return !details || details.gender !== 2;
});
if (invalidTags.length > 0) {
proxy.$modal.msgError(`耳号 ${invalidTags.join(',')} 性别不符合要求,无法提交`);
return;
}
//
return addCastrate(formData);
const requests = allTags.map(tag => {
const details = tagDetails[tag];
return addCastrate({
manageTags: tag,
sheepId: details.sheepId,
sheepfold: details.sheepfoldId || form.value.sheepfold,
technician: form.value.technician,
varietyId: details.varietyId,
comment: details.comment
});
});
//
Promise.all(requests)
.then(() => {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess('新增成功');
open.value = false;
getList();
})
.catch(error => {
proxy.$modal.msgError(`处理失败:${error.message}`);
proxy.$modal.msgError(`新增失败:${error.message}`);
});
});
}
//
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm(`是否确认删除去势编号为"${_ids}"的数据项?`).then(() => {
@ -390,10 +412,12 @@ function handleDelete(row) {
})
}
//
function handleExport() {
proxy.download('/produce/other/castrate/export', { ...queryParams.value }, `castrate_${new Date().getTime()}.xlsx`)
}
//
const sheepfoldOptions = ref([])
function getSheepfoldOptions() {
listSheepfold({ pageNum: 1, pageSize: 9999 }).then(res => {

View File

@ -2,7 +2,8 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.manageTags" placeholder="请输入管理耳号" clearable @keyup.enter="handleQuery"
style="width: 150px;" />
</el-form-item>
<el-form-item label="羊舍" prop="sheepfold">
@ -81,7 +82,7 @@
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="fixHoofRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="耳号" prop="manageTags">
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable collapse-tags allow-create
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable allow-create
style="width: 100%" @change="loadSheepInfo">
<el-option v-for="sheep in sheepOptions" :key="sheep.id" :label="sheep.manageTags"
:value="sheep.manageTags" />
@ -107,7 +108,7 @@
</template>
<script setup name="FixHoof">
import { listFixHoof, getFixHoof, delFixHoof, addFixHoof, updateFixHoof, checkSheepByManageTags, getVarietyOptions } from '@/api/produce/other/fixHoof'
import { listFixHoof, getFixHoof, delFixHoof, addFixHoof, updateFixHoof, checkSheepByManageTags, getVarietyOptions, getSheepBySheepfoldId } from '@/api/produce/other/fixHoof'
import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/sheepfold_management'
const { proxy } = getCurrentInstance()
@ -129,7 +130,7 @@ const data = reactive({
form: {
sheepfold: null,
manageTags: [],
tagDetails: {}
tagDetails: {},
},
queryParams: {
pageNum: 1,
@ -142,19 +143,20 @@ const data = reactive({
},
rules: {
manageTags: [
{ required: true, message: '耳号不能为空', trigger: 'blur' }
{ required: true, message: '请输入管理耳号', trigger: 'blur' }
],
sheepfold: [
{ required: true, message: '请选择羊舍', trigger: 'change' }
],
technician: [
{ required: true, message: '技术员不能为空', trigger: 'blur' }
{ required: true, message: '请输入技术员', trigger: 'blur' }
]
}
})
const { queryParams, form, rules } = toRefs(data)
//
function loadSheepBySheepfold() {
const currentSheepfoldId = form.value.sheepfold;
@ -163,7 +165,6 @@ function loadSheepBySheepfold() {
return;
}
//
getSheepBySheepfoldId(currentSheepfoldId)
.then(res => {
const newSheepList = res.data || [];
@ -184,8 +185,9 @@ async function loadSheepInfo() {
const tags = form.value.manageTags;
if (!tags || tags.length === 0) return;
const tagDetails = {}; //
const tagDetails = {};
const validResults = [];
const validTags = [];
for (const tag of tags) {
try {
@ -195,9 +197,9 @@ async function loadSheepInfo() {
proxy.$modal.msgError(`耳号 ${tag} 不存在`);
} else {
validResults.push(true);
//
validTags.push(tag);
tagDetails[tag] = {
comment: sheepData.comment || '', //
comment: sheepData.comment || '',
varietyId: sheepData.varietyId,
sheepfoldId: sheepData.sheepfoldId,
sheepId: sheepData.id
@ -209,16 +211,21 @@ async function loadSheepInfo() {
validResults.push(false);
}
}
//
if (validResults.includes(false)) {
form.value.manageTags = tags.filter((_, index) => validResults[index]);
proxy.$message.warning('部分耳号不合法,已过滤');
}
//
form.value.tagDetails = tagDetails;
if (validTags.length > 0) {
const firstValidTag = validTags[0]; 耳号
const firstSheepfoldId = tagDetails[firstValidTag].sheepfoldId;
form.value.sheepfold = firstSheepfoldId;
}
}
//
function getList() {
loading.value = true
const q = { ...queryParams.value }
@ -240,11 +247,13 @@ function getList() {
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
@ -257,11 +266,13 @@ function reset() {
proxy.resetForm('fixHoofRef')
}
//
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
//
function resetQuery() {
daterangeCreateTime.value = []
queryParams.value.varietyId = null
@ -275,12 +286,14 @@ function handleSelectionChange(selection) {
multiple.value = !selection.length
}
//
function handleAdd() {
reset()
open.value = true
title.value = '添加修蹄'
}
//
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
@ -293,6 +306,7 @@ function handleUpdate(row) {
})
}
//
function submitForm() {
proxy.$refs.fixHoofRef.validate(valid => {
if (!valid) return;
@ -304,7 +318,6 @@ function submitForm() {
return;
}
// ScFixHoof
const fixHoofList = allTags.map(tag => {
const details = tagDetails[tag] || {};
return {
@ -317,7 +330,6 @@ function submitForm() {
};
});
//
addFixHoof(fixHoofList)
.then(() => {
proxy.$modal.msgSuccess('操作成功');
@ -330,6 +342,7 @@ function submitForm() {
});
}
//
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm(`是否确认删除修蹄编号为"${_ids}"的数据项?`).then(() => {
@ -340,10 +353,12 @@ function handleDelete(row) {
})
}
//
function handleExport() {
proxy.download('/produce/other/fixHoof/export', { ...queryParams.value }, `fixHoof_${new Date().getTime()}.xlsx`)
}
//
const sheepfoldOptions = ref([])
function getSheepfoldOptions() {
listSheepfold({ pageNum: 1, pageSize: 9999 }).then(res => {
@ -351,34 +366,9 @@ function getSheepfoldOptions() {
})
}
//
async function validateSheep() {
if (!form.value.manageTags) return;
try {
const { data } = await checkSheepByManageTags(form.value.manageTags.trim())
if (!data) {
proxy.$modal.msgError('该管理耳号不存在');
//
form.value.manageTags = null;
form.value.sheepId = null;
form.value.sheepfold = null;
form.value.varietyId = null;
} else {
//
form.value.sheepId = data.id;
//
form.value.sheepfold = data.sheepfoldId;
form.value.varietyId = data.varietyId;
}
} catch {
proxy.$modal.msgError('校验失败');
}
}
/* 只保留一个 onMounted */
getList()
onMounted(() => {
getSheepfoldOptions()
getVarietyOptions()
getList()
})
</script>