Compare commits
10 Commits
79ba77c138
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4dbefa9d2 | ||
|
|
14d85c7bbb | ||
| 4ff466b2c7 | |||
| 3bfc2cffce | |||
|
|
191ea111f7 | ||
|
|
5fb6cecde5 | ||
|
|
f5722e4a1b | ||
| da77287c0f | |||
| b9febb4874 | |||
| ca9f7c4a1a |
@@ -82,4 +82,14 @@ export function getBreedRecordsByTimeRange(sheepId, startDate, endDate) {
|
||||
url: `/Breeding_records/Breeding_records/getByTimeRange/${sheepId}/${startDate}/${endDate}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 模糊搜索耳号(用于表单 autocomplete)
|
||||
// gender: 'ewe'=母羊 'ram'=公羊 不传=不限
|
||||
export function searchBreedEarNumbers(query, gender) {
|
||||
return request({
|
||||
url: '/Breeding_records/Breeding_records/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { query, gender }
|
||||
})
|
||||
}
|
||||
@@ -75,4 +75,4 @@ export function exportSperm(query) {
|
||||
data: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,3 +42,11 @@ export function delDeworm(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/deworm/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,3 +42,12 @@ export function delDiagnosis(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/diagnosis/diagnosis/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,3 +42,11 @@ export function delDisinfect(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function searchSheepfold(query) {
|
||||
return request({
|
||||
url: '/biosafety/disinfect/searchSheepfold',
|
||||
method: 'get',
|
||||
params: {sheepfold: query}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,3 +42,12 @@ export function delHealth(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/health/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delImmunity(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/immunity/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delQuarantine(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/quarantine/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delTreatment(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/treatment/treatment/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delUsageInfo(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/usageInfo/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
|
||||
63
src/api/embryodetail/embryodetail.js
Normal file
63
src/api/embryodetail/embryodetail.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询可供移植的胚胎明细
|
||||
// flushId 可选:传则只查该批次,不传则返回所有可移植胚胎
|
||||
export function listAvailableEmbryos(flushId) {
|
||||
return request({
|
||||
url: '/embryo/detail/available',
|
||||
method: 'get',
|
||||
params: flushId ? { flushId } : {}
|
||||
})
|
||||
}
|
||||
|
||||
// 将某枚胚胎标记为已移植,并关联配种记录ID
|
||||
export function markEmbryoTransferred(id, breedRecordId) {
|
||||
return request({
|
||||
url: '/embryo/detail/markTransferred',
|
||||
method: 'post',
|
||||
params: { id, breedRecordId }
|
||||
})
|
||||
}
|
||||
|
||||
// 批量标记胚胎已移植,并同步冲胚表统计字段
|
||||
// data: { ids: [1,2,3], breedRecordId: 100 }
|
||||
export function markBatchEmbryoTransferred(data) {
|
||||
return request({
|
||||
url: '/Breeding_records/Breeding_records/markBatchEmbryoTransferred',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 根据配种记录ID查询已移植的胚胎明细列表(用于"查看胚胎"弹窗)
|
||||
export function getEmbryosByBreedRecord(breedRecordId) {
|
||||
return request({
|
||||
url: '/Breeding_records/Breeding_records/embryosByBreedRecord/' + breedRecordId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据冲胚记录ID查询胚胎明细列表(含父记录字段,供冲胚编辑/查看回显用)
|
||||
export function listEmbryosByFlushId(flushId) {
|
||||
return request({
|
||||
url: `/embryo/detail/byFlush/${flushId}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取单条胚胎明细
|
||||
export function getEmbryoDetail(id) {
|
||||
return request({
|
||||
url: `/embryo/detail/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 修改单条胚胎明细(如修改去向、存储方式)
|
||||
export function updateEmbryoDetail(data) {
|
||||
return request({
|
||||
url: '/embryo/detail',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 增加模糊搜索耳号 API
|
||||
export function searchEarNumbers(query) {
|
||||
// 【修改】增加 sheepfoldId 过滤参数
|
||||
export function searchEarNumbers(query, sheepfoldId) {
|
||||
return request({
|
||||
url: '/saleRecord/saleRecord/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { query }
|
||||
params: { query, sheepfoldId }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -82,3 +82,12 @@ export function getSheepInfo(bsManageTags) {
|
||||
params: { bsManageTags }
|
||||
})
|
||||
}
|
||||
|
||||
// 【新增】查询已销售的羊只耳号(用于查询栏)
|
||||
export function searchSoldEarNumbers(query) {
|
||||
return request({
|
||||
url: '/saleRecord/saleRecord/searchSoldEarNumbers',
|
||||
method: 'get',
|
||||
params: { query }
|
||||
})
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -366,12 +366,11 @@
|
||||
|
||||
<script setup name="Deworm">
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { listDeworm, getDeworm, delDeworm, addDeworm, updateDeworm } from '@/api/biosafety/deworm'
|
||||
import { listDeworm, getDeworm, delDeworm, addDeworm, updateDeworm, searchEarNumbers} 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 { searchEarNumbers } from '@/api/common/sheep'
|
||||
import request from '@/utils/request'
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
@@ -476,29 +475,44 @@
|
||||
pasteInput.value = ''
|
||||
}
|
||||
|
||||
/** 远程搜索耳号 */
|
||||
|
||||
function searchEarNumber(query) {
|
||||
if (query !== '') {
|
||||
earNumberLoading.value = true
|
||||
|
||||
const queries = query.trim().split(/[\s,,]+/).filter(q => q)
|
||||
|
||||
if (queries.length === 1) {
|
||||
// 单个耳号模糊搜索
|
||||
searchEarNumbers(query).then(response => {
|
||||
earNumberOptions.value = response.data || []
|
||||
earNumberLoading.value = false
|
||||
}).catch(() => {
|
||||
earNumberOptions.value = []
|
||||
earNumberLoading.value = false
|
||||
})
|
||||
} else {
|
||||
// 多个耳号直接作为选项
|
||||
earNumberOptions.value = queries
|
||||
earNumberLoading.value = false
|
||||
}
|
||||
} else {
|
||||
if (!query || query.trim() === '') {
|
||||
earNumberOptions.value = []
|
||||
return
|
||||
}
|
||||
|
||||
earNumberLoading.value = true
|
||||
|
||||
// 统一转大写,去重
|
||||
const queries = [...new Set(
|
||||
query.trim().toUpperCase().split(/[\s,,]+/).filter(q => q.length >= 1)
|
||||
)]
|
||||
|
||||
if (queries.length === 0) {
|
||||
earNumberOptions.value = []
|
||||
earNumberLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
if (queries.length === 1) {
|
||||
// 单个耳号模糊搜索
|
||||
searchEarNumbers(queries[0]).then(response => {
|
||||
earNumberOptions.value = response.data || []
|
||||
}).catch(() => {
|
||||
earNumberOptions.value = []
|
||||
}).finally(() => {
|
||||
earNumberLoading.value = false
|
||||
})
|
||||
} else {
|
||||
// 多个耳号:先显示,再后台校验
|
||||
earNumberOptions.value = queries.map(q => ({ label: q, value: q, validating: true }))
|
||||
earNumberLoading.value = false
|
||||
|
||||
// 可选:调用后端批量校验
|
||||
validateEarNumbers(queries).then(validList => {
|
||||
earNumberOptions.value = validList
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -269,16 +269,10 @@
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template><script setup name="Diagnosis">
|
||||
import {
|
||||
listDiagnosis,
|
||||
getDiagnosis,
|
||||
delDiagnosis,
|
||||
updateDiagnosis,
|
||||
} from '@/api/biosafety/diagnosis'
|
||||
import {listDiagnosis,getDiagnosis,delDiagnosis,updateDiagnosis,searchEarNumbers} from '@/api/biosafety/diagnosis'
|
||||
import { listSheepfold_management } from '@/api/fileManagement/sheepfold_management'
|
||||
import { listDisease } from '@/api/biosafety/disease'
|
||||
import { getCurrentInstance, onMounted, ref, watch } from 'vue'
|
||||
import { searchEarNumbers } from '@/api/common/sheep'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
|
||||
const technicalOptions = ref([]) //自定义技术员数组变量
|
||||
|
||||
@@ -11,11 +11,17 @@
|
||||
<el-form-item label="药品名称" prop="mediName">
|
||||
<el-input v-model="queryParams.mediName" placeholder="请输入药品" clearable />
|
||||
</el-form-item>
|
||||
<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="sheepfoldIds">
|
||||
<el-select v-model="queryParams.sheepfoldIds" multiple collapse-tags collapse-tags-tooltip clearable
|
||||
placeholder="全部羊舍" filterable style="width: 240px" @change="handleSheepfoldChange">
|
||||
<el-option v-for="b in barns" :key="b.sheepfoldId"
|
||||
:label="b.sheepfold_name"
|
||||
:value="b.sheepfoldId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="queryParams.technician" filterable clearable placeholder="请输入技术员姓名" style="width: 100%"
|
||||
@@ -296,7 +302,7 @@
|
||||
|
||||
<script setup name="Disinfect">
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { listDisinfect, getDisinfect, delDisinfect, addDisinfect, updateDisinfect } from '@/api/biosafety/disinfect'
|
||||
import { listDisinfect, getDisinfect, delDisinfect, addDisinfect, updateDisinfect,searchSheepfold} from '@/api/biosafety/disinfect'
|
||||
import { listPrescription, getPrescription } from '@/api/biosafety/prescription'
|
||||
import { listUnit } from '@/api/biosafety/unit'
|
||||
import { listUsage } from '@/api/biosafety/usage'
|
||||
@@ -345,6 +351,7 @@ const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
sheepfoldId: null,
|
||||
sheepfoldIds: [], // 新增一个数组属性用于多选羊舍
|
||||
technician: null
|
||||
})
|
||||
|
||||
@@ -567,13 +574,28 @@ function handleAddDetailEdit() {
|
||||
editDetails.value.push({ mediId: null, dosage: 0, unit: null, usageId: null, manufacturer: null, batchNumber: null })
|
||||
}
|
||||
|
||||
// 获取羊舍列表
|
||||
const fetchBarns = async () => {
|
||||
try {
|
||||
const res = await searchSheepfold()
|
||||
barns.value = res.data || []
|
||||
} catch (error) {
|
||||
console.error('获取羊舍失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 羊舍选择变化时自动刷新数据
|
||||
const handleSheepfoldChange = (val) => {
|
||||
getList(queryParams)
|
||||
}
|
||||
|
||||
|
||||
/* ---------- 初始加载 ---------- */
|
||||
onMounted(() => {
|
||||
getList()
|
||||
/* 本地羊舍下拉 */
|
||||
request({ url: '/sheepfold_management/sheepfold_management/list', method: 'get' }).then(res => {
|
||||
barns.value = res.rows
|
||||
})
|
||||
fetchBarns()
|
||||
|
||||
listPrescription({ status: 1, persType: 3 }).then(res => {
|
||||
presOptions.value = res.rows.map(item => ({ id: item.id, label: item.name }))
|
||||
})
|
||||
|
||||
@@ -374,14 +374,13 @@
|
||||
|
||||
<script setup name="Health">
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { listHealth, getHealth, delHealth, addHealth, updateHealth } from '@/api/biosafety/health'
|
||||
import { listHealth, getHealth, delHealth, addHealth, updateHealth,searchEarNumbers } 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'
|
||||
import { searchEarNumbers } from '@/api/common/sheep'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
|
||||
const technicalOptions = ref([]) //自定义技术员数组变量
|
||||
|
||||
@@ -371,14 +371,13 @@
|
||||
|
||||
<script setup name="Immunity">
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { listImmunity, getImmunity, delImmunity, addImmunity, updateImmunity } from '@/api/biosafety/immunity'
|
||||
import { listImmunity, getImmunity, delImmunity, addImmunity, updateImmunity,searchEarNumbers } 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'
|
||||
import { searchEarNumbers } from '@/api/common/sheep'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
|
||||
const technicalOptions = ref([]) //自定义技术员数组变量
|
||||
|
||||
@@ -399,19 +399,12 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Quarantine">
|
||||
import {
|
||||
listQuarantine,
|
||||
getQuarantine,
|
||||
delQuarantine,
|
||||
addQuarantine,
|
||||
updateQuarantine
|
||||
} from '@/api/biosafety/quarantine'
|
||||
import {listQuarantine,getQuarantine,delQuarantine,addQuarantine,updateQuarantine,searchEarNumbers} from '@/api/biosafety/quarantine'
|
||||
import { listItems } from '@/api/biosafety/items'
|
||||
import { listSample } from '@/api/biosafety/sample'
|
||||
import request from '@/utils/request'
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { searchEarNumbers } from '@/api/common/sheep'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
@@ -528,7 +528,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { listTreatment, getTreatment, delTreatment, addTreatment, updateTreatment } from '@/api/biosafety/treatment'
|
||||
import { listTreatment, getTreatment, delTreatment, addTreatment, updateTreatment,searchEarNumbers } from '@/api/biosafety/treatment'
|
||||
import { listDisease } from '@/api/biosafety/disease'
|
||||
import { listSheepfold_management } from "@/api/fileManagement/sheepfold_management"
|
||||
import { listPrescription, getPrescription } from '@/api/biosafety/prescription'
|
||||
@@ -537,7 +537,6 @@ import { listUsage } from '@/api/biosafety/usage'
|
||||
import { listMedicine } from '@/api/biosafety/medicine'
|
||||
import request from '@/utils/request'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { searchEarNumbers } from '@/api/common/sheep'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
|
||||
const technicalOptions = ref([]) //自定义技术员数组变量
|
||||
|
||||
@@ -202,11 +202,10 @@
|
||||
|
||||
<script setup name="Usage">
|
||||
import { listMedicine} from "@/api/biosafety/medicine"
|
||||
import { listUsageInfo, getUsageInfo } from '@/api/biosafety/usageInfo'
|
||||
import { listUsageInfo, getUsageInfo,searchEarNumbers } from '@/api/biosafety/usageInfo'
|
||||
import { listUnit } from '@/api/biosafety/unit'
|
||||
import { listUsage } from '@/api/biosafety/usage'
|
||||
import { getCurrentInstance, reactive, ref, toRefs } from 'vue'
|
||||
import { searchEarNumbers } from '@/api/common/sheep'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { pres_type } = proxy.useDict('pres_type')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
724
src/views/embryodetail/embryodetail/index.vue
Normal file
724
src/views/embryodetail/embryodetail/index.vue
Normal file
@@ -0,0 +1,724 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- ===================== 搜索区域 ===================== -->
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="冲胚时间" style="width: 388px;">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="供体母号" prop="donorFemaleNo">
|
||||
<el-input v-model="queryParams.donorFemaleNo" placeholder="请输入供体母号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="供体父号" prop="donorMaleNo">
|
||||
<el-input v-model="queryParams.donorMaleNo" placeholder="请输入供体父号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- ===================== 操作按钮 ===================== -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['embryo:flush:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['embryo:flush:edit']">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['embryo:flush:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['embryo:flush:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<!-- ===================== 数据表格 ===================== -->
|
||||
<el-table v-loading="loading" :data="flushList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="冲胚时间" align="center" prop="flushTime" width="110">
|
||||
<template #default="scope">{{ parseTime(scope.row.flushTime, '{y}-{m}-{d}') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="胚胎品种" align="center" prop="embryoVariety" width="100" />
|
||||
<el-table-column label="供体母号" align="center" prop="donorFemaleNo" width="110" />
|
||||
<el-table-column label="母羊品种" align="center" prop="donorFemaleVariety" width="100" />
|
||||
<el-table-column label="供体父号" align="center" prop="donorMaleNo" width="110" />
|
||||
<el-table-column label="公羊品种" align="center" prop="donorMaleVariety" width="100" />
|
||||
<el-table-column label="胎龄(天)" align="center" prop="embryoAge" width="80" />
|
||||
<el-table-column label="A级" align="center" prop="gradeA" width="55" />
|
||||
<el-table-column label="B级" align="center" prop="gradeB" width="55" />
|
||||
<el-table-column label="C级" align="center" prop="gradeC" width="55" />
|
||||
<el-table-column label="16细胞" align="center" prop="gradeD" width="70" />
|
||||
<el-table-column label="未受精" align="center" prop="unfertilized" width="70" />
|
||||
<el-table-column label="退化" align="center" prop="degenerated" width="55" />
|
||||
<el-table-column label="冲胚数" align="center" prop="totalEmbryo" width="70" />
|
||||
<el-table-column label="有效胚" align="center" prop="validEmbryo" width="70" />
|
||||
<el-table-column label="移胚数" align="center" prop="transferred" width="70" />
|
||||
<el-table-column label="受体数" align="center" prop="recipientCnt" width="70" />
|
||||
<el-table-column label="胚胎类型" align="center" prop="embryoType" width="100" />
|
||||
<el-table-column label="胚胎来源" align="center" prop="embryoSource" width="80" />
|
||||
<el-table-column label="冲胚人" align="center" prop="flushOperator" width="80" />
|
||||
<el-table-column label="捡胚人" align="center" prop="collectOperator" width="80" />
|
||||
<el-table-column label="所在牧场" align="center" prop="ranchName" width="100" />
|
||||
<el-table-column label="备注" align="center" prop="remark" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['embryo:flush:edit']">修改</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['embryo:flush: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"
|
||||
:page-sizes="[20, 50, 100, 200, 500, 1000, 2000]"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- =====================================================================
|
||||
新增 / 修改 冲胚记录 Dialog
|
||||
===================================================================== -->
|
||||
<el-dialog :title="title" v-model="open" width="1000px" append-to-body>
|
||||
<el-form ref="flushRef" :model="form" :rules="rules" label-width="100px">
|
||||
|
||||
<!-- 基础信息 -->
|
||||
<el-divider content-position="left">基础信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="冲胚时间" prop="flushTime">
|
||||
<el-date-picker clearable v-model="form.flushTime" type="date"
|
||||
value-format="YYYY-MM-DD" placeholder="选择冲胚时间" style="width:100%"
|
||||
@change="handleFlushTimeChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="供体母号" prop="donorFemaleNo">
|
||||
<!-- 输入 + 从配种记录选择按钮 -->
|
||||
<el-input
|
||||
v-model="form.donorFemaleNo"
|
||||
placeholder="输入耳号或从配种记录选择"
|
||||
clearable
|
||||
style="width: calc(100% - 88px)"
|
||||
@change="handleDonorFemaleInputChange"
|
||||
/>
|
||||
<el-button
|
||||
type="primary" link style="margin-left:6px; white-space:nowrap"
|
||||
@click="openBreedRecordPicker">
|
||||
从配种记录选
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="母羊品种">
|
||||
<el-input v-model="form.donorFemaleVariety" disabled placeholder="自动填充" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="供体父号" prop="donorMaleNo">
|
||||
<el-select v-model="form.donorMaleNo" filterable clearable
|
||||
placeholder="请选择供体公羊" @change="handleDonorMaleChange" style="width:100%">
|
||||
<el-option v-for="item in donorMaleOptions" :key="item.manageTag"
|
||||
:label="item.manageTag" :value="item.manageTag">
|
||||
<span>{{ item.manageTag }}</span>
|
||||
<span style="float:right;color:#8492a6;font-size:12px">{{ item.variety }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="公羊品种">
|
||||
<el-input v-model="form.donorMaleVariety" disabled placeholder="自动填充" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="胚胎品种">
|
||||
<el-input v-model="form.embryoVariety" placeholder="自动计算/可修改" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="胎龄(天)">
|
||||
<el-input-number v-model="form.embryoAge" :min="0" controls-position="right"
|
||||
placeholder="自动计算" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="所在牧场">
|
||||
<el-input v-model="form.ranchName" disabled placeholder="自动填充" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 胚胎明细(替换原"胚胎等级"+"发育阶段"两个分区) -->
|
||||
<el-divider content-position="left">
|
||||
胚胎明细
|
||||
<span style="margin-left:8px;font-size:12px;color:#909399">
|
||||
共 {{ form.embryoDetails.length }} 枚 | 有效胚 {{ computedValidEmbryo }} 枚
|
||||
</span>
|
||||
</el-divider>
|
||||
|
||||
<!-- 快速添加按钮 -->
|
||||
<div style="margin-bottom:10px;display:flex;flex-wrap:wrap;gap:8px;">
|
||||
<el-button size="small" type="primary" @click="addEmbryo('A')">+ A级</el-button>
|
||||
<el-button size="small" type="success" @click="addEmbryo('B')">+ B级</el-button>
|
||||
<el-button size="small" type="warning" @click="addEmbryo('C')">+ C级</el-button>
|
||||
<el-button size="small" type="info" @click="addEmbryo('16细胞')">+ 16细胞</el-button>
|
||||
<el-button size="small" type="danger" plain @click="addEmbryo('未受精')">+ 未受精</el-button>
|
||||
<el-button size="small" type="danger" plain @click="addEmbryo('退化')">+ 退化</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 胚胎明细表格 -->
|
||||
<el-table :data="form.embryoDetails" border size="small" max-height="300"
|
||||
style="width:100%;margin-bottom:8px;"
|
||||
:row-class-name="embryoRowClass">
|
||||
<el-table-column label="序号" width="60" align="center">
|
||||
<template #default="scope">{{ scope.$index + 1 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="胚胎等级" width="130" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.embryoGrade" size="small" style="width:100%"
|
||||
@change="onGradeChange(scope.row)">
|
||||
<el-option label="A级" value="A" />
|
||||
<el-option label="B级" value="B" />
|
||||
<el-option label="C级" value="C" />
|
||||
<el-option label="16细胞" value="16细胞" />
|
||||
<el-option label="未受精" value="未受精" />
|
||||
<el-option label="退化" value="退化" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="去向" width="150" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.destination" size="small" style="width:100%">
|
||||
<el-option label="移植" value="移植" />
|
||||
<el-option label="冷冻保存" value="冷冻保存" />
|
||||
<el-option label="遗弃" value="遗弃" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="存储方式" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.storageMethod" size="small" style="width:100%"
|
||||
clearable placeholder="选择存储方式">
|
||||
<el-option label="胚胎保存液" value="胚胎保存液" />
|
||||
<el-option label="液氮冷冻" value="液氮冷冻" />
|
||||
<el-option label="PBS缓冲液" value="PBS缓冲液" />
|
||||
<el-option label="其他" value="其他" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="70" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="danger" icon="Delete" @click="removeEmbryo(scope.$index)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="form.embryoDetails.length === 0"
|
||||
style="text-align:center;color:#909399;padding:12px;border:1px dashed #e0e0e0;border-radius:4px;">
|
||||
暂无胚胎明细,请点击上方按钮添加
|
||||
</div>
|
||||
|
||||
<!-- 统计信息(只读,自动计算) -->
|
||||
<el-divider content-position="left">统计信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="冲胚数">
|
||||
<el-input :value="form.embryoDetails.length" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="有效胚">
|
||||
<el-input :value="computedValidEmbryo" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="移胚数" title="由配种记录使用后自动同步">
|
||||
<el-input :value="form.transferred || 0" disabled placeholder="自动同步" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="受体数" title="由配种记录使用后自动同步">
|
||||
<el-input :value="form.recipientCnt || 0" disabled placeholder="自动同步" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 其他信息 -->
|
||||
<el-divider content-position="left">其他信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="胚胎类型" prop="embryoType">
|
||||
<el-select v-model="form.embryoType" placeholder="请选择" style="width:100%">
|
||||
<el-option label="体内胚胎冻胚" value="体内胚胎冻胚" />
|
||||
<el-option label="体内胚胎鲜胚" value="体内胚胎鲜胚" />
|
||||
<el-option label="体外胚胎冻胚" value="体外胚胎冻胚" />
|
||||
<el-option label="体外胚胎鲜胚" value="体外胚胎鲜胚" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="胚胎来源" prop="embryoSource">
|
||||
<el-select v-model="form.embryoSource" placeholder="请选择" style="width:100%">
|
||||
<el-option label="自繁" value="自繁" />
|
||||
<el-option label="购入" value="购入" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="冲胚人" prop="flushOperator">
|
||||
<el-input v-model="form.flushOperator" placeholder="请输入冲胚人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="捡胚人" prop="collectOperator">
|
||||
<el-input v-model="form.collectOperator" placeholder="请输入捡胚人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" :rows="1" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</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>
|
||||
|
||||
<!-- =====================================================================
|
||||
从配种记录选择供体母羊 Dialog
|
||||
展示:配种类型 = 供体母羊配种(breedType=1) 的记录
|
||||
显示:配种日期 / 供体母羊耳号 / 供体公羊耳号
|
||||
===================================================================== -->
|
||||
<el-dialog title="选择供体母羊(从配种记录)" v-model="breedPickerOpen" width="700px" append-to-body>
|
||||
<!-- 搜索 -->
|
||||
<el-row :gutter="10" style="margin-bottom:10px;">
|
||||
<el-col :span="10">
|
||||
<el-input v-model="breedPickerQuery.eweManageTags" placeholder="母羊耳号搜索" clearable @keyup.enter="loadBreedRecords" />
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-button type="primary" @click="loadBreedRecords">搜索</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table
|
||||
v-loading="breedPickerLoading"
|
||||
:data="breedPickerList"
|
||||
highlight-current-row
|
||||
@current-change="onBreedPickerSelect"
|
||||
size="small"
|
||||
max-height="360">
|
||||
<el-table-column label="配种日期" align="center" prop="createTime" width="110">
|
||||
<template #default="scope">{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="供体母羊耳号" align="center" prop="eweManageTags" />
|
||||
<el-table-column label="母羊品种" align="center" prop="eweVariety" />
|
||||
<el-table-column label="供体公羊耳号" align="center" prop="donorRamNo" />
|
||||
<el-table-column label="公羊品种" align="center" prop="donorRamVariety" />
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="breedPickerTotal > 0"
|
||||
:total="breedPickerTotal"
|
||||
v-model:page="breedPickerQuery.pageNum"
|
||||
v-model:limit="breedPickerQuery.pageSize"
|
||||
@pagination="loadBreedRecords"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button type="primary" :disabled="!selectedBreedRow" @click="confirmBreedPicker">确认选择</el-button>
|
||||
<el-button @click="breedPickerOpen = false">取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Flush">
|
||||
import { listFlush, getFlush, delFlush, addFlush, updateFlush,
|
||||
getDonorInfo, getDonorFemaleList, getDonorMaleList, getSheepInfo,
|
||||
calculateEmbryoVariety } from "@/api/embryo/flush"
|
||||
// 注意:listBreedRecord 来自配种记录 API,需要在该 API 文件中导出此函数
|
||||
// 参考路径: @/api/produce/breed/breedRecord
|
||||
// 若路径不同,请自行调整
|
||||
import { listBreeding_records } from "@/api/Breeding_records/Breeding_records"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
// ============================
|
||||
// 列表页状态
|
||||
// ============================
|
||||
const flushList = 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 dateRange = ref([])
|
||||
const donorMaleOptions = ref([])
|
||||
const matingDateCache = ref(null)
|
||||
|
||||
// ============================
|
||||
// 表单 & 规则
|
||||
// ============================
|
||||
const data = reactive({
|
||||
form: {
|
||||
id: null,
|
||||
flushTime: null,
|
||||
donorFemaleNo: null,
|
||||
donorFemaleVariety: null,
|
||||
donorMaleNo: null,
|
||||
donorMaleVariety: null,
|
||||
embryoVariety: null,
|
||||
embryoAge: null,
|
||||
gradeA: 0, gradeB: 0, gradeC: 0, gradeD: 0,
|
||||
unfertilized: 0, degenerated: 0,
|
||||
totalEmbryo: 0, validEmbryo: 0,
|
||||
transferred: 0, recipientCnt: 0,
|
||||
embryoType: null,
|
||||
embryoSource: '自繁',
|
||||
flushOperator: null,
|
||||
collectOperator: null,
|
||||
ranchId: null, ranchName: null,
|
||||
remark: null,
|
||||
embryoDetails: [] // ← 胚胎明细列表
|
||||
},
|
||||
queryParams: {
|
||||
pageNum: 1, pageSize: 10,
|
||||
donorFemaleNo: null, donorMaleNo: null
|
||||
},
|
||||
rules: {
|
||||
flushTime: [{ required: true, message: "冲胚时间不能为空", trigger: "blur" }],
|
||||
donorFemaleNo: [{ required: true, message: "供体母号不能为空", trigger: "change" }],
|
||||
embryoType: [{ required: true, message: "胚胎类型不能为空", trigger: "change" }],
|
||||
embryoSource: [{ required: true, message: "胚胎来源不能为空", trigger: "change" }],
|
||||
flushOperator: [{ required: true, message: "冲胚人不能为空", trigger: "blur" }],
|
||||
collectOperator: [{ required: true, message: "捡胚人不能为空", trigger: "blur" }]
|
||||
}
|
||||
})
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
|
||||
// ============================
|
||||
// 配种记录选择弹窗状态
|
||||
// ============================
|
||||
const breedPickerOpen = ref(false)
|
||||
const breedPickerLoading = ref(false)
|
||||
const breedPickerList = ref([])
|
||||
const breedPickerTotal = ref(0)
|
||||
const selectedBreedRow = ref(null)
|
||||
const breedPickerQuery = reactive({
|
||||
pageNum: 1, pageSize: 10,
|
||||
breedType: 1, // 固定查询"供体母羊配种"
|
||||
eweManageTags: null
|
||||
})
|
||||
|
||||
// ============================
|
||||
// 计算属性:有效胚数量(A+B+C+16细胞)
|
||||
// ============================
|
||||
const computedValidEmbryo = computed(() => {
|
||||
return form.value.embryoDetails.filter(d =>
|
||||
['A', 'B', 'C', '16细胞'].includes(d.embryoGrade)
|
||||
).length
|
||||
})
|
||||
|
||||
// ============================
|
||||
// 列表操作
|
||||
// ============================
|
||||
function getList() {
|
||||
loading.value = true
|
||||
listFlush(proxy.addDateRange(queryParams.value, dateRange.value, 'FlushTime')).then(res => {
|
||||
flushList.value = res.rows
|
||||
total.value = res.total
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleQuery() { queryParams.value.pageNum = 1; getList() }
|
||||
function resetQuery() { dateRange.value = []; proxy.resetForm("queryRef"); handleQuery() }
|
||||
function handleSelectionChange(sel) {
|
||||
ids.value = sel.map(i => i.id)
|
||||
single.value = sel.length !== 1
|
||||
multiple.value = !sel.length
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 表单通用
|
||||
// ============================
|
||||
function cancel() { open.value = false; reset() }
|
||||
|
||||
function reset() {
|
||||
form.value = {
|
||||
id: null,
|
||||
flushTime: proxy.parseTime(new Date(), '{y}-{m}-{d}'),
|
||||
donorFemaleNo: null, donorFemaleVariety: null,
|
||||
donorMaleNo: null, donorMaleVariety: null,
|
||||
embryoVariety: null, embryoAge: null,
|
||||
gradeA: 0, gradeB: 0, gradeC: 0, gradeD: 0,
|
||||
unfertilized: 0, degenerated: 0,
|
||||
totalEmbryo: 0, validEmbryo: 0,
|
||||
transferred: 0, recipientCnt: 0,
|
||||
embryoType: null, embryoSource: '自繁',
|
||||
flushOperator: null, collectOperator: null,
|
||||
ranchId: null, ranchName: null,
|
||||
remark: null,
|
||||
embryoDetails: []
|
||||
}
|
||||
matingDateCache.value = null
|
||||
proxy.resetForm("flushRef")
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 新增 / 修改
|
||||
// ============================
|
||||
function handleAdd() {
|
||||
reset()
|
||||
loadDonorMaleList()
|
||||
open.value = true
|
||||
title.value = "添加冲胚记录"
|
||||
}
|
||||
|
||||
function handleUpdate(row) {
|
||||
reset()
|
||||
loadDonorMaleList()
|
||||
const _id = row.id || ids.value
|
||||
getFlush(_id).then(res => {
|
||||
form.value = { ...res.data, embryoDetails: res.data.embryoDetails || [] }
|
||||
open.value = true
|
||||
title.value = "修改冲胚记录"
|
||||
})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 胚胎明细行操作
|
||||
// ============================
|
||||
|
||||
/** 添加胚胎行 */
|
||||
function addEmbryo(grade) {
|
||||
const isWaste = ['未受精', '退化'].includes(grade)
|
||||
form.value.embryoDetails.push({
|
||||
embryoGrade: grade,
|
||||
destination: isWaste ? '遗弃' : '移植',
|
||||
storageMethod: isWaste ? '' : '胚胎保存液',
|
||||
embryoVariety: form.value.embryoVariety || null
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除胚胎行 */
|
||||
function removeEmbryo(index) {
|
||||
form.value.embryoDetails.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 切换等级时同步默认去向 */
|
||||
function onGradeChange(row) {
|
||||
const isWaste = ['未受精', '退化'].includes(row.embryoGrade)
|
||||
row.destination = isWaste ? '遗弃' : '移植'
|
||||
row.storageMethod = isWaste ? '' : (row.storageMethod || '胚胎保存液')
|
||||
}
|
||||
|
||||
/** 行颜色 */
|
||||
function embryoRowClass({ row }) {
|
||||
if (['未受精', '退化'].includes(row.embryoGrade)) return 'row-waste'
|
||||
if (row.destination === '冷冻保存') return 'row-frozen'
|
||||
return ''
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 供体母号相关
|
||||
// ============================
|
||||
|
||||
/** 手动输入耳号后触发 */
|
||||
function handleDonorFemaleInputChange(val) {
|
||||
if (!val) {
|
||||
form.value.donorFemaleVariety = null
|
||||
form.value.donorMaleNo = null
|
||||
form.value.donorMaleVariety = null
|
||||
form.value.embryoVariety = null
|
||||
form.value.ranchId = null
|
||||
form.value.ranchName = null
|
||||
matingDateCache.value = null
|
||||
return
|
||||
}
|
||||
getDonorInfo(val).then(res => {
|
||||
const info = res.data || {}
|
||||
form.value.donorFemaleVariety = info.donorFemaleVariety || null
|
||||
form.value.donorMaleNo = info.donorMaleNo || form.value.donorMaleNo
|
||||
form.value.donorMaleVariety = info.donorMaleVariety || null
|
||||
form.value.embryoVariety = info.embryoVariety || null
|
||||
form.value.ranchId = info.ranchId || null
|
||||
form.value.ranchName = info.ranchName || null
|
||||
matingDateCache.value = info.matingDate || null
|
||||
calculateEmbryoAge()
|
||||
updateEmbryoVariety()
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 从配种记录选择弹窗 */
|
||||
function openBreedRecordPicker() {
|
||||
breedPickerQuery.pageNum = 1
|
||||
breedPickerQuery.eweManageTags = null
|
||||
selectedBreedRow.value = null
|
||||
breedPickerList.value = []
|
||||
breedPickerOpen.value = true
|
||||
loadBreedRecords()
|
||||
}
|
||||
|
||||
function loadBreedRecords() {
|
||||
breedPickerLoading.value = true
|
||||
listBreedRecord({ ...breedPickerQuery }).then(res => {
|
||||
breedPickerList.value = res.rows || []
|
||||
breedPickerTotal.value = res.total || 0
|
||||
breedPickerLoading.value = false
|
||||
}).catch(() => { breedPickerLoading.value = false })
|
||||
}
|
||||
|
||||
function onBreedPickerSelect(row) {
|
||||
selectedBreedRow.value = row
|
||||
}
|
||||
|
||||
function confirmBreedPicker() {
|
||||
if (!selectedBreedRow.value) return
|
||||
const row = selectedBreedRow.value
|
||||
form.value.donorFemaleNo = row.eweManageTags
|
||||
form.value.donorFemaleVariety = row.eweVariety || null
|
||||
form.value.donorMaleNo = row.donorRamNo || form.value.donorMaleNo
|
||||
form.value.donorMaleVariety = row.donorRamVariety || null
|
||||
// 配种日期 → 计算胎龄
|
||||
matingDateCache.value = row.createTime || null
|
||||
calculateEmbryoAge()
|
||||
updateEmbryoVariety()
|
||||
breedPickerOpen.value = false
|
||||
|
||||
// 同步查一次牧场等信息
|
||||
getDonorInfo(row.eweManageTags).then(res => {
|
||||
const info = res.data || {}
|
||||
form.value.ranchId = info.ranchId || null
|
||||
form.value.ranchName = info.ranchName || null
|
||||
if (!form.value.embryoVariety && info.embryoVariety) {
|
||||
form.value.embryoVariety = info.embryoVariety
|
||||
}
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 供体父号
|
||||
// ============================
|
||||
function handleDonorMaleChange(val) {
|
||||
if (!val) { form.value.donorMaleVariety = null; updateEmbryoVariety(); return }
|
||||
const found = donorMaleOptions.value.find(i => i.manageTag === val)
|
||||
if (found) {
|
||||
form.value.donorMaleVariety = found.variety
|
||||
} else {
|
||||
getSheepInfo(val).then(res => {
|
||||
if (res.data) form.value.donorMaleVariety = res.data.variety
|
||||
})
|
||||
}
|
||||
updateEmbryoVariety()
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 胎龄 & 胚胎品种
|
||||
// ============================
|
||||
function handleFlushTimeChange() { calculateEmbryoAge() }
|
||||
|
||||
function calculateEmbryoAge() {
|
||||
if (matingDateCache.value && form.value.flushTime) {
|
||||
const diff = new Date(form.value.flushTime) - new Date(matingDateCache.value)
|
||||
const days = Math.floor(diff / 86400000)
|
||||
form.value.embryoAge = days > 0 ? days : 0
|
||||
} else {
|
||||
form.value.embryoAge = null
|
||||
}
|
||||
}
|
||||
|
||||
function updateEmbryoVariety() {
|
||||
const m = form.value.donorMaleVariety
|
||||
const f = form.value.donorFemaleVariety
|
||||
if (m && f) {
|
||||
calculateEmbryoVariety(m, f).then(res => {
|
||||
form.value.embryoVariety = res.data
|
||||
// 同步更新明细行的胚胎品种
|
||||
form.value.embryoDetails.forEach(d => { d.embryoVariety = res.data })
|
||||
})
|
||||
} else {
|
||||
form.value.embryoVariety = null
|
||||
}
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 下拉列表加载
|
||||
// ============================
|
||||
function loadDonorMaleList() {
|
||||
getDonorMaleList().then(res => { donorMaleOptions.value = res.data || [] }).catch(() => {})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 提交
|
||||
// ============================
|
||||
function submitForm() {
|
||||
proxy.$refs["flushRef"].validate(valid => {
|
||||
if (!valid) return
|
||||
if (form.value.embryoDetails.length === 0) {
|
||||
proxy.$modal.msgWarning("请至少添加一条胚胎明细")
|
||||
return
|
||||
}
|
||||
// 提交前同步明细中的胚胎品种
|
||||
form.value.embryoDetails.forEach(d => {
|
||||
if (!d.embryoVariety) d.embryoVariety = form.value.embryoVariety
|
||||
})
|
||||
|
||||
const api = form.value.id != null ? updateFlush : addFlush
|
||||
api(form.value).then(() => {
|
||||
proxy.$modal.msgSuccess(form.value.id != null ? "修改成功" : "新增成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 删除 & 导出
|
||||
// ============================
|
||||
function handleDelete(row) {
|
||||
const _ids = row.id || ids.value
|
||||
proxy.$modal.confirm('是否确认删除所选的冲胚记录?').then(() => delFlush(_ids)).then(() => {
|
||||
getList()
|
||||
proxy.$modal.msgSuccess("删除成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
proxy.download('embryo/flush/export', { ...queryParams.value }, `冲胚记录_${Date.now()}.xlsx`)
|
||||
}
|
||||
|
||||
// 初始化
|
||||
getList()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 废弃/退化行浅红色背景 */
|
||||
:deep(.row-waste) { background-color: #fff0f0; }
|
||||
/* 冷冻保存行浅蓝色背景 */
|
||||
:deep(.row-frozen) { background-color: #f0f7ff; }
|
||||
</style>
|
||||
@@ -107,6 +107,13 @@
|
||||
type="info" :closable="false" show-icon />
|
||||
</div>
|
||||
|
||||
<div class="mt10">
|
||||
<el-button type="success" icon="Download" @click="handleDownloadTemplate">
|
||||
下载配对模板
|
||||
</el-button>
|
||||
<span style="font-size:12px;color:#909399;margin-left:10px">下载空白模板,填写耳号后上传</span>
|
||||
</div>
|
||||
|
||||
<el-form :model="importForm" label-width="100px" class="mt16" style="max-width:600px">
|
||||
<el-form-item label="计划类型" required>
|
||||
<el-select v-model="importForm.planType" placeholder="请选择计划类型" style="width:260px">
|
||||
@@ -364,7 +371,8 @@ import {
|
||||
confirmApproveBreedPlan,
|
||||
viewBreedPlan,
|
||||
exportBreedPlanDetails,
|
||||
delBreedPlanGenerate
|
||||
delBreedPlanGenerate,
|
||||
downloadPairTemplate
|
||||
} from '@/api/mating_plan/generate'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
@@ -520,6 +528,23 @@ function handleClearImport() {
|
||||
if (uploadRef.value) uploadRef.value.clearFiles()
|
||||
}
|
||||
|
||||
async function handleDownloadTemplate() {
|
||||
try {
|
||||
const res = await downloadPairTemplate()
|
||||
const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = '配种配对模板.xlsx'
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
window.URL.revokeObjectURL(url)
|
||||
} catch (e) {
|
||||
proxy.$modal.msgError('下载模板失败:' + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
// =================== Tab3:计划列表 ===================
|
||||
const listLoading = ref(false)
|
||||
const planList = ref([])
|
||||
|
||||
@@ -29,10 +29,22 @@
|
||||
reserve-keyword
|
||||
placeholder="输入耳号搜索,支持多选"
|
||||
:remote-method="searchEarNumberMethod"
|
||||
:loading="earNumberLoading"
|
||||
@focus="handleQueryEarNumberFocus" :loading="earNumberLoading"
|
||||
style="width: 100%"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-if="earNumberLoading"
|
||||
label="正在加载数据..."
|
||||
value="__loading__"
|
||||
disabled
|
||||
/>
|
||||
<el-option
|
||||
v-else-if="earNumberQueryOptions.length === 0"
|
||||
label="暂无已销售记录"
|
||||
value="__empty__"
|
||||
disabled
|
||||
/>
|
||||
<el-option
|
||||
v-for="item in earNumberQueryOptions"
|
||||
:key="item"
|
||||
@@ -257,13 +269,35 @@
|
||||
<el-select
|
||||
v-model="form.bsManageTagsList"
|
||||
multiple
|
||||
filterable
|
||||
allow-create
|
||||
filterable
|
||||
remote
|
||||
allow-create
|
||||
reserve-keyword
|
||||
default-first-option
|
||||
placeholder="手动输入或选择"
|
||||
placeholder="请输入耳号任意部分进行搜索"
|
||||
:remote-method="formSearchEarNumberMethod"
|
||||
:loading="formEarNumberLoading"
|
||||
style="width: 100%"
|
||||
@change="handleTagChange">
|
||||
<el-option v-for="tag in earTagOptions" :key="tag" :label="tag" :value="tag" />
|
||||
@change="handleTagChange"
|
||||
@focus="handleEarNumberFocus">
|
||||
<el-option
|
||||
v-if="formEarNumberLoading"
|
||||
label="正在加载数据..."
|
||||
value="__loading__"
|
||||
disabled
|
||||
/>
|
||||
<el-option
|
||||
v-else-if="earTagOptions.length === 0"
|
||||
:label="form.sheepfoldId ? '该羊舍暂无羊只' : '暂无匹配数据'"
|
||||
value="__empty__"
|
||||
disabled
|
||||
/>
|
||||
<el-option
|
||||
v-for="tag in earTagOptions"
|
||||
:key="tag"
|
||||
:label="tag"
|
||||
:value="tag"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -455,13 +489,14 @@
|
||||
import { ref, reactive, toRefs, computed, getCurrentInstance, onMounted } from 'vue'
|
||||
import {
|
||||
listSaleRecord, getSaleRecord, delSaleRecord, addSaleRecord, updateSaleRecord,
|
||||
getSheepInfo, listSheepInventory, searchEarNumbers
|
||||
getSheepInfo, listSheepInventory, searchEarNumbers, searchSoldEarNumbers // <- 引入新增的 API
|
||||
} from '@/api/sale/saleRecord/saleRecord'
|
||||
import { listSheepfold_management } from '@/api/fileManagement/sheepfold_management'
|
||||
import { listUser } from '@/api/system/user'
|
||||
import { listCustomer } from '@/api/sale/customer/customer'
|
||||
import { regionData } from 'element-china-area-data'
|
||||
|
||||
const formEarNumberLoading = ref(false)
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { disease_type } = proxy.useDict('disease_type')
|
||||
|
||||
@@ -609,20 +644,35 @@ function handleQueryAreaChange(val) {
|
||||
}
|
||||
}
|
||||
|
||||
// 【新增】远程搜索耳号方法
|
||||
// 2. 【修改】顶部搜索栏耳号查询方法
|
||||
function searchEarNumberMethod(query) {
|
||||
if (query !== '') {
|
||||
earNumberLoading.value = true
|
||||
searchEarNumbers(query).then(res => {
|
||||
earNumberQueryOptions.value = res.data || []
|
||||
earNumberLoading.value = false
|
||||
}).catch(() => {
|
||||
earNumberQueryOptions.value = []
|
||||
earNumberLoading.value = false
|
||||
})
|
||||
} else {
|
||||
earNumberLoading.value = true
|
||||
// 这里允许传入空字符串,后端会返回前50条已售耳号
|
||||
searchSoldEarNumbers(query).then(res => {
|
||||
earNumberQueryOptions.value = res.data || []
|
||||
earNumberLoading.value = false
|
||||
}).catch(() => {
|
||||
earNumberQueryOptions.value = []
|
||||
}
|
||||
earNumberLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
// 【新增】表单内的耳号远程搜索方法
|
||||
function formSearchEarNumberMethod(query) {
|
||||
formEarNumberLoading.value = true
|
||||
// 将表单当前选中的羊舍ID传给后端。如果没有选,此处会传 null/undefined,后端将查询全库
|
||||
searchEarNumbers(query, form.value.sheepfoldId).then(res => {
|
||||
earTagOptions.value = res.data || []
|
||||
formEarNumberLoading.value = false
|
||||
}).catch(() => {
|
||||
earTagOptions.value = []
|
||||
formEarNumberLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
// 【新增】下拉框获取焦点时,如果还没数据,加载一下默认数据(前50条)
|
||||
function handleEarNumberFocus() {
|
||||
formSearchEarNumberMethod('')
|
||||
}
|
||||
|
||||
// 【新增】移除单个查询耳号
|
||||
@@ -649,6 +699,8 @@ function handleSheepfoldChange(val) {
|
||||
console.error("获取耳号失败", err)
|
||||
})
|
||||
}
|
||||
// 切换羊舍后,立刻用空关键字查一下该羊舍下的耳号,更新下拉列表
|
||||
formSearchEarNumberMethod('')
|
||||
}
|
||||
|
||||
function handleTagChange(tags) {
|
||||
@@ -776,10 +828,23 @@ function handleDelete(row) {
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// 【修改】导出功能:支持勾选导出与全量导出
|
||||
function handleExport() {
|
||||
proxy.download('saleRecord/saleRecord/export', {
|
||||
...queryParams.value
|
||||
}, `saleRecord_${new Date().getTime()}.xlsx`)
|
||||
// 组装要传给后端的查询参数
|
||||
const exportParams = { ...queryParams.value }
|
||||
let msg = "是否确认导出所有符合查询条件的销售记录?"
|
||||
|
||||
// 如果用户在表格中勾选了数据,就把勾选的ID集合塞进参数里,并改变提示语
|
||||
if (ids.value.length > 0) {
|
||||
exportParams.exportIds = ids.value
|
||||
msg = `是否确认导出选中的 ${ids.value.length} 条销售记录?`
|
||||
}
|
||||
|
||||
// 给用户一个明确的二次确认弹窗
|
||||
proxy.$modal.confirm(msg).then(() => {
|
||||
// 确认后调用导出接口,附带时间戳作为文件名
|
||||
proxy.download('saleRecord/saleRecord/export', exportParams, `羊只销售记录_${new Date().getTime()}.xlsx`)
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
@@ -804,6 +869,14 @@ function diseaseTypeFormat(row) {
|
||||
// 如果静态选项 label 和 value 一样,则直接返回即可
|
||||
return row.diseaseType
|
||||
}
|
||||
|
||||
// 3. 【新增】输入框获取焦点时,如果还没数据,自动查询
|
||||
function handleQueryEarNumberFocus() {
|
||||
// 为了防止每次点击都发请求,判断如果没有输入内容且下拉框为空,才去查默认数据
|
||||
if (earNumberQueryOptions.value.length === 0) {
|
||||
searchEarNumberMethod('')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user