Files
zhyc-sheep-ui/src/views/biosafety/health/index.vue
2025-08-01 16:19:43 +08:00

535 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="app-container">
<!-- 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 />
</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>
<!-- 2. 按钮 -->
<el-row :gutter="10" class="mb8">
<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="羊只耳号" 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">
<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">{{ 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" width="200">
<template #default="scope">
<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" />
<!-- 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-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" 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="addForm.comment" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<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 { 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 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)
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]
}
listHealth(qp).then(res => {
dewormList.value = res.rows
total.value = res.total
loading.value = false
})
}
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id)
single.value = selection.length !== 1
multiple.value = !selection.length
}
function handleQuery() {
queryParams.pageNum = 1
getList()
}
function resetQuery() {
daterangeDatetime.value = []
proxy.resetForm('queryRef')
handleQuery()
}
/* ------------------ 新增 ------------------ */
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 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 id = row.id || ids.value
proxy.$modal.confirm('确认删除?')
.then(() => delHealth(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()
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>