Compare commits

..

18 Commits

Author SHA1 Message Date
7a5ed75da5 perf(views/frozen-sale): 销售项总价动态计算
+ 销售项总价动态计算
2026-03-08 20:30:36 +08:00
c87f1e7536 fix(views/frozen-sale): 表单销售项下列列表行为与开发环境不一致(失效)
+ 表单销售项下列列表行为与开发环境不一致(失效)
    + 测试环境与打包构建严格等级不一致导致
2026-03-08 19:35:31 +08:00
zyk
b4dbefa9d2 Merge remote-tracking branch 'origin/main' 2026-03-07 18:45:24 +08:00
zyk
14d85c7bbb 修复问题 2026-03-07 18:45:16 +08:00
4ff466b2c7 消毒 2026-03-07 18:11:21 +08:00
3bfc2cffce Merge branch 'main' of http://118.182.97.76:3000/admin/zhyc-sheep-ui 2026-03-07 15:35:29 +08:00
zyk
191ea111f7 配种计划导出更新 2026-03-07 12:38:58 +08:00
zyk
5fb6cecde5 Merge remote-tracking branch 'origin/main' 2026-03-07 11:22:59 +08:00
zyk
f5722e4a1b 胚胎移植所有逻辑完成 2026-03-07 11:22:52 +08:00
da77287c0f 生物安全模块羊只耳号查询修改 2026-03-06 22:30:44 +08:00
ll
b9febb4874 Merge branch 'main' of http://118.182.97.76:3000/admin/zhyc-sheep-ui 2026-03-06 11:12:25 +08:00
ll
ca9f7c4a1a 羊只销售BUg修复 2026-03-06 11:12:18 +08:00
zyh
79ba77c138 耳号模糊查询修改 2026-03-05 21:39:44 +08:00
zyk
1b8c32c271 Merge remote-tracking branch 'origin/main' 2026-03-05 14:58:51 +08:00
zyk
dda3f8bdf7 产羔导出更新 2026-03-05 14:58:45 +08:00
ll
8a331158e5 奶品管理销售管理固定表头 2026-03-05 11:29:31 +08:00
ll
2abd257ba4 Merge branch 'main' of http://118.182.97.76:3000/admin/zhyc-sheep-ui 2026-03-04 20:48:44 +08:00
ll
9591d47827 羊只档案导出修改 2026-03-04 20:48:22 +08:00
48 changed files with 3355 additions and 1821 deletions

View File

@@ -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 }
})
}

View File

@@ -75,4 +75,4 @@ export function exportSperm(query) {
data: query,
responseType: 'blob'
})
}
}

View File

@@ -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 }
})
}

View File

@@ -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 }
})
}

View File

@@ -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}
})
}

View File

@@ -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 }
})
}

View File

@@ -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 }
})
}

View File

@@ -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 }
})
}

View File

@@ -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 }
})
}

View File

@@ -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 }
})
}

View 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
})
}

View File

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

View File

@@ -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
})
}
}

View File

@@ -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([]) //自定义技术员数组变量

View File

@@ -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 }))
})

View File

@@ -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([]) //自定义技术员数组变量

View File

@@ -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([]) //自定义技术员数组变量

View File

@@ -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()

View File

@@ -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([]) //自定义技术员数组变量

View File

@@ -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')

View File

@@ -107,7 +107,7 @@
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-select
v-model="queryParams.technician"
@@ -196,6 +196,21 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="母羊耳号" align="center" prop="femaleEarNumber" width="120" fixed="left" />
<el-table-column label="母羊品种" align="center" prop="femaleBreed" width="100" />
<el-table-column label="事件类型" align="center" width="90">
<template #default>
<el-tag type="success" size="small">产羔</el-tag>
</template>
</el-table-column>
<el-table-column label="产羔日期" align="center" prop="createTime" width="110">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="配种类型" align="center" prop="breedType" width="140">
<template #default="scope">
<span>{{ getBreedTypeLabel(scope.row.breedType) }}</span>
</template>
</el-table-column>
<el-table-column label="配种日期" align="center" prop="breedingDate" width="110">
<template #default="scope">
<span>{{ parseTime(scope.row.breedingDate, '{y}-{m}-{d}') }}</span>
@@ -204,6 +219,12 @@
<el-table-column label="胎次" align="center" prop="parity" width="80" />
<el-table-column label="公羊耳号" align="center" prop="maleEarNumber" width="120" />
<el-table-column label="公羊品种" align="center" prop="maleBreed" width="120" />
<!-- 供体信息胚胎移植时有值 -->
<el-table-column label="供体母羊" align="center" prop="donorEwe" width="120" />
<el-table-column label="供体母羊品种" align="center" prop="donorEweBreed" width="120" />
<el-table-column label="供体公羊" align="center" prop="donorRam" width="120" />
<el-table-column label="供体公羊品种" align="center" prop="donorRamBreed" width="120" />
<el-table-column label="移胚数" align="center" prop="embryoCount" width="90" />
<el-table-column label="产羔数量" align="center" prop="lambsBorn" width="90" />
<el-table-column label="活羔数量" align="center" prop="survival" width="90" />
<el-table-column label="折损数" align="center" prop="loss" width="80">
@@ -211,6 +232,23 @@
<span>{{ (scope.row.lambsBorn || 0) - (scope.row.survival || 0) }}</span>
</template>
</el-table-column>
<el-table-column label="羔羊品种" align="center" prop="lambBreedId" width="110">
<template #default="scope">
<span>{{ getVarietyName(scope.row.lambBreedId) }}</span>
</template>
</el-table-column>
<template v-for="n in 8" :key="'lambcols'+n">
<el-table-column :label="'羔羊耳号'+n" align="center" width="130">
<template #default="scope">
<span>{{ scope.row.lambDetails && scope.row.lambDetails[n-1] ? scope.row.lambDetails[n-1].lambEarNumber : '' }}</span>
</template>
</el-table-column>
<el-table-column :label="'羔羊'+n+'出生重'" align="center" width="100">
<template #default="scope">
<span>{{ scope.row.lambDetails && scope.row.lambDetails[n-1] ? scope.row.lambDetails[n-1].birthWeight : '' }}</span>
</template>
</el-table-column>
</template>
<el-table-column label="技术员" align="center" prop="technician" width="100" />
<el-table-column label="月龄" align="center" prop="monthAge" width="80" />
<el-table-column label="产羔评分" align="center" prop="score" width="90" />
@@ -267,6 +305,30 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="事件类型">
<el-input value="产羔" readonly />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="产羔日期" prop="createTime">
<el-date-picker
clearable
v-model="form.createTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择产羔日期"
style="width:100%">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="配种类型">
<el-input :value="getBreedTypeLabel(form.breedType)" placeholder="配种类型" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="公羊耳号" prop="maleEarNumber">
@@ -279,13 +341,47 @@
</el-form-item>
</el-col>
</el-row>
<!-- 供体信息胚胎移植时显示 -->
<template v-if="isEmbryoTransfer">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="供体母羊">
<el-input v-model="form.donorEwe" placeholder="供体母羊耳号" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供体母羊品种">
<el-input v-model="form.donorEweBreed" placeholder="供体母羊品种" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="供体公羊">
<el-input v-model="form.donorRam" placeholder="供体公羊耳号" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供体公羊品种">
<el-input v-model="form.donorRamBreed" placeholder="供体公羊品种" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="移胚数">
<el-input v-model="form.embryoCount" placeholder="移胚数" readonly />
</el-form-item>
</el-col>
</el-row>
</template>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="怀孕天数" prop="pregnancyDays">
<el-input v-model="form.pregnancyDays" placeholder="怀孕天数" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="技术员" prop="technician">
<el-select
@@ -328,17 +424,6 @@
<el-input v-model.number="form.score" placeholder="请输入产羔评分" type="number" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="产羔日期" prop="createTime">
<el-date-picker
clearable
v-model="form.createTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择产羔日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
@@ -370,7 +455,7 @@
<el-col :span="8">
<el-form-item :label="`羔羊耳号`" :prop="`lambForms.${index}.lambEarNumber`">
<el-input v-model="lamb.lambEarNumber" placeholder="请输入羔羊耳号"
@input="handleLambEarNumberInput(index)"/>
@input="handleLambEarNumberInput(index)"/>
</el-form-item>
</el-col>
<el-col :span="8">
@@ -452,6 +537,13 @@
<el-descriptions-item label="公羊耳号">{{ detailData.maleEarNumber }}</el-descriptions-item>
<el-descriptions-item label="公羊品种">{{ detailData.maleBreed }}</el-descriptions-item>
<el-descriptions-item label="配种日期">{{ parseTime(detailData.breedingDate, '{y}-{m}-{d}') }}</el-descriptions-item>
<template v-if="detailData.donorEwe || detailData.donorRam">
<el-descriptions-item label="供体母羊">{{ detailData.donorEwe || '-' }}</el-descriptions-item>
<el-descriptions-item label="供体母羊品种">{{ detailData.donorEweBreed || '-' }}</el-descriptions-item>
<el-descriptions-item label="供体公羊">{{ detailData.donorRam || '-' }}</el-descriptions-item>
<el-descriptions-item label="供体公羊品种">{{ detailData.donorRamBreed || '-' }}</el-descriptions-item>
<el-descriptions-item label="移胚数">{{ detailData.embryoCount || '-' }}</el-descriptions-item>
</template>
<el-descriptions-item label="产羔数量">{{ detailData.lambsBorn }}</el-descriptions-item>
<el-descriptions-item label="活羔数量">{{ detailData.survival }}</el-descriptions-item>
<el-descriptions-item label="技术员">{{ detailData.technician }}</el-descriptions-item>
@@ -539,6 +631,11 @@ const detailData = ref({})
const lambDetailList = ref([])
const varietyList = ref([]) // 品种列表
// 是否胚胎移植有供体母羊或供体公羊信息时为true
const isEmbryoTransfer = computed(() => {
return !!(form.value.donorEwe || form.value.donorRam)
})
const data = reactive({
form: {},
queryParams: {
@@ -813,6 +910,19 @@ function getGenderDisplay(gender) {
return { label: '未知', type: 'info' }
}
/** 配种类型标签映射 */
function getBreedTypeLabel(breedType) {
const map = {
'1': '供体母羊配种',
'2': '同期发情人工授精',
'3': '本交',
'4': '自然发情人工授精',
'5': '胚胎移植'
}
if (breedType == null || breedType === '') return '-'
return map[String(breedType)] || String(breedType)
}
/** 母羊耳号输入处理 */
function handleEarNumberInput() {
// 清空相关联动字段
@@ -822,6 +932,12 @@ function handleEarNumberInput() {
form.value.breedingDate = null
form.value.pregnancyDays = null
form.value.technician = null
form.value.donorEwe = null
form.value.donorEweBreed = null
form.value.donorRam = null
form.value.donorRamBreed = null
form.value.embryoCount = null
form.value.breedType = null
}
/** 母羊耳号失焦处理 - 自动查询配种信息 */
@@ -840,6 +956,13 @@ function handleEarNumberBlur() {
form.value.breedingDate = breedingData.breeding_date
form.value.pregnancyDays = breedingData.pregnancy_days
form.value.technician = breedingData.technician || ''
// 供体信息(胚胎移植时有值)
form.value.donorEwe = breedingData.donor_ewe || null
form.value.donorEweBreed = breedingData.donor_ewe_breed || null
form.value.donorRam = breedingData.donor_ram || null
form.value.donorRamBreed = breedingData.donor_ram_breed || null
form.value.embryoCount = breedingData.embryo_count || null
form.value.breedType = breedingData.breed_type || null
const mVariety = varietyList.value.find(v => v.variety === breedingData.male_breed);
const fVariety = varietyList.value.find(v => v.variety === breedingData.female_breed);
@@ -874,10 +997,19 @@ function handleEarNumberBlur() {
function getList() {
loading.value = true
listLambing_records(queryParams.value).then(response => {
lambing_recordsList.value = response.rows
const rows = response.rows || []
total.value = response.total
loading.value = false
})
// 批量加载每行的羔羊详情
const promises = rows.map(row =>
getLambDetail(row.id).then(res => {
row.lambDetails = res.data || []
}).catch(() => { row.lambDetails = [] })
)
Promise.all(promises).then(() => {
lambing_recordsList.value = rows
loading.value = false
})
}).catch(() => { loading.value = false })
}
// 取消按钮
@@ -903,7 +1035,13 @@ function reset() {
score: null,
comment: null,
createBy: null,
createTime: null
createTime: null,
donorEwe: null,
donorEweBreed: null,
donorRam: null,
donorRamBreed: null,
embryoCount: null,
breedType: null
}
showLambForms.value = false
lambForms.value = []
@@ -936,6 +1074,8 @@ function handleSelectionChange(selection) {
/** 新增按钮操作 */
function handleAdd() {
reset()
// 默认产羔日期为今天
form.value.createTime = new Date().toISOString().split('T')[0]
open.value = true
title.value = "添加产羔记录"
}

View File

@@ -69,37 +69,40 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="dryMatterCorrectionList"
@selection-change="handleSelectionChange"
style="width: 100%">
<el-table-column type="selection" align="center" />
<el-table-column label="年月" align="center" prop="datetime" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}') }}</span>
</template>
</el-table-column>
<el-table-column label="厂区" align="center" prop="factory">
<template #default="scope">
<dict-tag :options="da_ranch" :value="scope.row.factory"/>
</template>
</el-table-column>
<el-table-column label="干物质含量" align="center" prop="content" sortable />
<el-table-column label="干物质标准" align="center" prop="standard" sortable />
<el-table-column label="干物质系数" align="center" prop="coefficient" sortable>
<template #default="scope">
<span>{{ formatCoefficient(scope.row.coefficient) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['dryMatterCorrection:dryMatterCorrection:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dryMatterCorrection:dryMatterCorrection:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="table-wrapper">
<el-table
v-loading="loading"
:data="dryMatterCorrectionList"
@selection-change="handleSelectionChange"
style="width: 100%"
height="100%">
<el-table-column type="selection" align="center" />
<el-table-column label="年月" align="center" prop="datetime" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}') }}</span>
</template>
</el-table-column>
<el-table-column label="厂区" align="center" prop="factory">
<template #default="scope">
<dict-tag :options="da_ranch" :value="scope.row.factory"/>
</template>
</el-table-column>
<el-table-column label="干物质含量" align="center" prop="content" sortable />
<el-table-column label="干物质标准" align="center" prop="standard" sortable />
<el-table-column label="干物质系数" align="center" prop="coefficient" sortable>
<template #default="scope">
<span>{{ formatCoefficient(scope.row.coefficient) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['dryMatterCorrection:dryMatterCorrection:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dryMatterCorrection:dryMatterCorrection:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total>0"
:total="total"
@@ -373,4 +376,31 @@ getList()
.el-form-item {
margin-bottom: 15px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -75,126 +75,128 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="freshMilkTestList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="来源"
align="center"
prop="source"
v-if="selectedColumns.includes('source')" />
<el-table-column
label="检测日期"
align="center"
prop="datetime"
width="180"
v-if="selectedColumns.includes('datetime')"
sortable>
<template #default="scope">
<span>{{ formatDate(scope.row.datetime) }}</span>
</template>
</el-table-column>
<el-table-column
label="脂肪g/100g"
align="center"
prop="fat"
v-if="selectedColumns.includes('fat')"
sortable />
<el-table-column
label="蛋白质g/100g"
align="center"
prop="protein"
v-if="selectedColumns.includes('protein')"
sortable />
<el-table-column
label="非脂g/100g"
align="center"
prop="nonFat"
v-if="selectedColumns.includes('nonFat')"
sortable />
<el-table-column
label="酸度oT"
align="center"
prop="acidity"
v-if="selectedColumns.includes('acidity')"
sortable />
<el-table-column
label="菌落总数1"
align="center"
prop="bacterialColony1"
v-if="selectedColumns.includes('bacterialColony1')"
sortable />
<el-table-column
label="菌落总数2"
align="center"
prop="bacterialColony2"
v-if="selectedColumns.includes('bacterialColony2')"
sortable />
<el-table-column
label="菌落总数3"
align="center"
prop="bacterialColony3"
v-if="selectedColumns.includes('bacterialColony3')"
sortable />
<el-table-column
label="菌落总数4"
align="center"
prop="bacterialColony4"
v-if="selectedColumns.includes('bacterialColony4')"
sortable />
<el-table-column
label="菌落总数5"
align="center"
prop="bacterialColony5"
v-if="selectedColumns.includes('bacterialColony5')"
sortable />
<el-table-column
label="大肠菌群(CFU/ml)"
align="center"
prop="coli"
v-if="selectedColumns.includes('coli')"
sortable />
<el-table-column
label="乳铁蛋白(mg/L)"
align="center"
prop="lactoferrin"
v-if="selectedColumns.includes('lactoferrin')"
sortable />
<el-table-column
label="免疫球蛋白(mg/L)"
align="center"
prop="ig"
v-if="selectedColumns.includes('ig')"
sortable />
<div class="table-wrapper">
<el-table v-loading="loading" :data="freshMilkTestList" @selection-change="handleSelectionChange" height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="来源"
align="center"
prop="source"
v-if="selectedColumns.includes('source')" />
<el-table-column
label="检测日期"
align="center"
prop="datetime"
width="180"
v-if="selectedColumns.includes('datetime')"
sortable>
<template #default="scope">
<span>{{ formatDate(scope.row.datetime) }}</span>
</template>
</el-table-column>
<el-table-column
label="备注"
align="center"
prop="commnet"
v-if="selectedColumns.includes('commnet')" />
<el-table-column
label="创建人"
align="center"
prop="createBy"
v-if="selectedColumns.includes('createBy')" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
v-if="selectedColumns.includes('createTime')"
sortable>
<template #default="scope">
<span>{{ formatDateTime(scope.row.createTime) }}</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="['freshMilkTest:freshMilkTest:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['freshMilkTest:freshMilkTest:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-table-column
label="脂肪g/100g"
align="center"
prop="fat"
v-if="selectedColumns.includes('fat')"
sortable />
<el-table-column
label="蛋白质g/100g"
align="center"
prop="protein"
v-if="selectedColumns.includes('protein')"
sortable />
<el-table-column
label="非脂g/100g"
align="center"
prop="nonFat"
v-if="selectedColumns.includes('nonFat')"
sortable />
<el-table-column
label="酸度oT"
align="center"
prop="acidity"
v-if="selectedColumns.includes('acidity')"
sortable />
<el-table-column
label="菌落总数1"
align="center"
prop="bacterialColony1"
v-if="selectedColumns.includes('bacterialColony1')"
sortable />
<el-table-column
label="菌落总数2"
align="center"
prop="bacterialColony2"
v-if="selectedColumns.includes('bacterialColony2')"
sortable />
<el-table-column
label="菌落总数3"
align="center"
prop="bacterialColony3"
v-if="selectedColumns.includes('bacterialColony3')"
sortable />
<el-table-column
label="菌落总数4"
align="center"
prop="bacterialColony4"
v-if="selectedColumns.includes('bacterialColony4')"
sortable />
<el-table-column
label="菌落总数5"
align="center"
prop="bacterialColony5"
v-if="selectedColumns.includes('bacterialColony5')"
sortable />
<el-table-column
label="大肠菌群(CFU/ml)"
align="center"
prop="coli"
v-if="selectedColumns.includes('coli')"
sortable />
<el-table-column
label="乳铁蛋白(mg/L)"
align="center"
prop="lactoferrin"
v-if="selectedColumns.includes('lactoferrin')"
sortable />
<el-table-column
label="免疫球蛋白(mg/L)"
align="center"
prop="ig"
v-if="selectedColumns.includes('ig')"
sortable />
<el-table-column
label="备注"
align="center"
prop="commnet"
v-if="selectedColumns.includes('commnet')" />
<el-table-column
label="创建人"
align="center"
prop="createBy"
v-if="selectedColumns.includes('createBy')" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
v-if="selectedColumns.includes('createTime')"
sortable>
<template #default="scope">
<span>{{ formatDateTime(scope.row.createTime) }}</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="['freshMilkTest:freshMilkTest:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['freshMilkTest:freshMilkTest:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total>0"
@@ -642,4 +644,32 @@ onMounted(() => {
.el-dialog__body {
padding: 15px 20px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -49,36 +49,38 @@
</template>
</el-dialog>
<el-table :data="rows" border style="margin-top:16px" v-loading="loading">
<el-table-column prop="datetime" label="日期" width="120" sortable fixed="left">
<template #default="{ row }">
{{ row.datetime ? row.datetime.substring(0, 10) : '' }}
</template>
</el-table-column>
<el-table-column prop="num" label="羊数" sortable width="100" />
<el-table-column prop="colostSheep" label="初乳羊" sortable width="100" />
<el-table-column prop="commercialIntake" label="商乳入库" sortable width="120" />
<el-table-column prop="antiIntake" label="乳入库" sortable width="120" />
<el-table-column prop="colostIntake" label="乳入库" sortable width="120" />
<el-table-column prop="intakeTotal" label="入库小计" sortable width="120" />
<el-table-column prop="commercialTest" label="商乳实验用奶" sortable width="140" />
<el-table-column prop="colostTest" label="乳实验用奶" sortable width="140" />
<el-table-column prop="transferCommercial" label="商乳调拨出库" sortable width="140" />
<el-table-column prop="transferAnti" label="乳调拨出库" sortable width="140" />
<el-table-column prop="transferColost" label="乳调拨出库" sortable width="140" />
<el-table-column prop="transferTotal" label="调拨小计" sortable width="120" />
<el-table-column prop="loss" label="损耗" sortable width="100" />
<el-table-column v-for="f in selectedFeed" :key="'feed-'+f" :prop="f" :label="f" sortable width="120" />
<el-table-column v-for="s in selectedSale" :key="'sale-'+s" :prop="s" :label="s" sortable width="120" />
<el-table-column prop="stockCommercial" label="商乳库存" sortable width="120" />
<el-table-column prop="stockAnti" label="乳库存" sortable width="120" />
<el-table-column prop="colost" label="乳库存" sortable width="120" />
<el-table-column prop="returnFresh" label="爱特退回鲜奶" sortable width="140" />
<el-table-column prop="returnYogurt" label="爱特退回奶" sortable width="140" />
</el-table>
<div class="table-wrapper">
<el-table :data="rows" border style="margin-top:16px" v-loading="loading" height="100%">
<el-table-column prop="datetime" label="日期" width="120" sortable fixed="left">
<template #default="{ row }">
{{ row.datetime ? row.datetime.substring(0, 10) : '' }}
</template>
</el-table-column>
<el-table-column prop="num" label="羊" sortable width="100" />
<el-table-column prop="colostSheep" label="初乳羊" sortable width="100" />
<el-table-column prop="commercialIntake" label="乳入库" sortable width="120" />
<el-table-column prop="antiIntake" label="乳入库" sortable width="120" />
<el-table-column prop="colostIntake" label="初乳入库" sortable width="120" />
<el-table-column prop="intakeTotal" label="入库小计" sortable width="120" />
<el-table-column prop="commercialTest" label="乳实验用奶" sortable width="140" />
<el-table-column prop="colostTest" label="初乳实验用奶" sortable width="140" />
<el-table-column prop="transferCommercial" label="乳调拨出库" sortable width="140" />
<el-table-column prop="transferAnti" label="乳调拨出库" sortable width="140" />
<el-table-column prop="transferColost" label="初乳调拨出库" sortable width="140" />
<el-table-column prop="transferTotal" label="调拨小计" sortable width="120" />
<el-table-column prop="loss" label="损耗" sortable width="100" />
<el-table-column v-for="f in selectedFeed" :key="'feed-'+f" :prop="f" :label="f" sortable width="120" />
<el-table-column v-for="s in selectedSale" :key="'sale-'+s" :prop="s" :label="s" sortable width="120" />
<el-table-column prop="stockCommercial" label="乳库存" sortable width="120" />
<el-table-column prop="stockAnti" label="乳库存" sortable width="120" />
<el-table-column prop="colost" label="初乳库存" sortable width="120" />
<el-table-column prop="returnFresh" label="爱特退回奶" sortable width="140" />
<el-table-column prop="returnYogurt" label="爱特退回酸奶" sortable width="140" />
</el-table>
</div>
<pagination
v-show="total>0"
@@ -221,4 +223,32 @@ onMounted(() => {
.mb-4 {
margin-bottom: 16px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -93,29 +93,31 @@
</el-col>
</el-row>
<el-table :data="tableData" v-loading="loading">
<el-table-column prop="datetime" label="日期" width="110" sortable>
<template #default="{ row }">
{{ parseTime(row.datetime, '{y}-{m}-{d}') }}
</template>
</el-table-column>
<el-table-column prop="manageEarNo" label="管理耳号" />
<el-table-column prop="electronicEarNo" label="电子耳号" />
<el-table-column prop="parity" label="胎次" sortable />
<el-table-column prop="factory" label="厂区" />
<el-table-column prop="classes" label="班次" sortable />
<el-table-column prop="milk" label="班次产奶量" sortable>
<template #default="{ row }">
{{ row.milk ? Number(row.milk).toFixed(2) : '-' }}
</template>
</el-table-column>
<el-table-column prop="correctedMilk" label="班次校正奶量" sortable>
<template #default="{ row }">
{{ row.correctedMilk ? Number(row.correctedMilk).toFixed(2) : '-' }}
</template>
</el-table-column>
</el-table>
<div class="table-wrapper">
<el-table :data="tableData" v-loading="loading" height="100%">
<el-table-column prop="datetime" label="日期" width="110" sortable>
<template #default="{ row }">
{{ parseTime(row.datetime, '{y}-{m}-{d}') }}
</template>
</el-table-column>
<el-table-column prop="manageEarNo" label="管理耳号" />
<el-table-column prop="electronicEarNo" label="电子耳号" />
<el-table-column prop="parity" label="胎次" sortable />
<el-table-column prop="factory" label="厂区" />
<el-table-column prop="classes" label="班次" sortable />
<el-table-column prop="milk" label="班次产奶量" sortable>
<template #default="{ row }">
{{ row.milk ? Number(row.milk).toFixed(2) : '-' }}
</template>
</el-table-column>
<el-table-column prop="correctedMilk" label="班次校正奶量" sortable>
<template #default="{ row }">
{{ row.correctedMilk ? Number(row.correctedMilk).toFixed(2) : '-' }}
</template>
</el-table-column>
</el-table>
</div>
<pagination v-show="total>0" :total="total"
v-model:page="queryParams.pageNum"
@@ -315,4 +317,32 @@ getList();
background-color: #f5f7fa;
border-radius: 4px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -48,20 +48,22 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="parityCorrectionList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="胎次" align="center" prop="parity" sortable />
<el-table-column label="系数" align="center" prop="coef" sortable />
<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="['parityCorrection:parityCorrection:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['parityCorrection:parityCorrection:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="table-wrapper">
<el-table v-loading="loading" :data="parityCorrectionList" @selection-change="handleSelectionChange" height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="胎次" align="center" prop="parity" sortable />
<el-table-column label="系数" align="center" prop="coef" sortable />
<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="['parityCorrection:parityCorrection:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['parityCorrection:parityCorrection:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total>0"
:total="total"
@@ -214,4 +216,33 @@ function handleDelete(row) {
}
getList()
</script>
</script>
<style scoped>
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -75,48 +75,50 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="rawMilkTestList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="检测日期" align="center" prop="datetime" width="180" v-if="visibleColumns.datetime" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="来源" align="center" prop="source" v-if="visibleColumns.source" />
<el-table-column label="冰点" align="center" prop="freeze" v-if="visibleColumns.freeze" sortable />
<el-table-column label="相对密度" align="center" prop="density" v-if="visibleColumns.density" sortable />
<el-table-column label="脂肪g/100g" align="center" prop="fat" v-if="visibleColumns.fat" sortable />
<el-table-column label="蛋白质g/100g" align="center" prop="protein" v-if="visibleColumns.protein" sortable />
<el-table-column label="非脂g/100g" align="center" prop="nonFat" v-if="visibleColumns.nonFat" sortable />
<el-table-column label="干物质mg/100g" align="center" prop="dryMatter" v-if="visibleColumns.dryMatter" sortable />
<el-table-column label="杂质度mg/100g" align="center" prop="impurityDegree" v-if="visibleColumns.impurityDegree" sortable />
<el-table-column label="乳糖g/100g" align="center" prop="lactose" v-if="visibleColumns.lactose" sortable />
<el-table-column label="灰度g/100g" align="center" prop="ashContent" v-if="visibleColumns.ashContent" sortable />
<el-table-column label="酸度" align="center" prop="acidity" v-if="visibleColumns.acidity" sortable />
<el-table-column label="ph" align="center" prop="ph" v-if="visibleColumns.ph" sortable />
<el-table-column label="菌落总数" align="center" prop="bacterialColony" v-if="visibleColumns.bacterialColony" sortable />
<el-table-column label="乳铁蛋白" align="center" prop="lactoferrin" v-if="visibleColumns.lactoferrin" sortable />
<el-table-column label="免疫球蛋白" align="center" prop="ig" v-if="visibleColumns.ig" sortable />
<el-table-column label="体细胞" align="center" prop="somaticCell" v-if="visibleColumns.somaticCell" sortable />
<el-table-column label="尿素氮" align="center" prop="usea" v-if="visibleColumns.usea" sortable />
<el-table-column label="脂蛋比" align="center" prop="fatRatio" v-if="visibleColumns.fatRatio" sortable />
<el-table-column label="备注" align="center" prop="comment" v-if="visibleColumns.comment" />
<el-table-column label="创建人" align="center" prop="createBy" v-if="visibleColumns.createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" v-if="visibleColumns.createTime" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</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="['rawMilkTest:rawMilkTest:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['rawMilkTest:rawMilkTest:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="table-wrapper">
<el-table v-loading="loading" :data="rawMilkTestList" @selection-change="handleSelectionChange" height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="检测日期" align="center" prop="datetime" width="180" v-if="visibleColumns.datetime" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="来源" align="center" prop="source" v-if="visibleColumns.source" />
<el-table-column label="冰点" align="center" prop="freeze" v-if="visibleColumns.freeze" sortable />
<el-table-column label="相对密度" align="center" prop="density" v-if="visibleColumns.density" sortable />
<el-table-column label="脂肪g/100g" align="center" prop="fat" v-if="visibleColumns.fat" sortable />
<el-table-column label="蛋白质g/100g" align="center" prop="protein" v-if="visibleColumns.protein" sortable />
<el-table-column label="非脂g/100g" align="center" prop="nonFat" v-if="visibleColumns.nonFat" sortable />
<el-table-column label="干物质mg/100g" align="center" prop="dryMatter" v-if="visibleColumns.dryMatter" sortable />
<el-table-column label="杂质度mg/100g" align="center" prop="impurityDegree" v-if="visibleColumns.impurityDegree" sortable />
<el-table-column label="乳糖g/100g" align="center" prop="lactose" v-if="visibleColumns.lactose" sortable />
<el-table-column label="灰度g/100g" align="center" prop="ashContent" v-if="visibleColumns.ashContent" sortable />
<el-table-column label="酸度" align="center" prop="acidity" v-if="visibleColumns.acidity" sortable />
<el-table-column label="ph" align="center" prop="ph" v-if="visibleColumns.ph" sortable />
<el-table-column label="菌落总数" align="center" prop="bacterialColony" v-if="visibleColumns.bacterialColony" sortable />
<el-table-column label="乳铁蛋白" align="center" prop="lactoferrin" v-if="visibleColumns.lactoferrin" sortable />
<el-table-column label="免疫球蛋白" align="center" prop="ig" v-if="visibleColumns.ig" sortable />
<el-table-column label="体细胞" align="center" prop="somaticCell" v-if="visibleColumns.somaticCell" sortable />
<el-table-column label="尿素氮" align="center" prop="usea" v-if="visibleColumns.usea" sortable />
<el-table-column label="脂蛋比" align="center" prop="fatRatio" v-if="visibleColumns.fatRatio" sortable />
<el-table-column label="备注" align="center" prop="comment" v-if="visibleColumns.comment" />
<el-table-column label="创建" align="center" prop="createBy" v-if="visibleColumns.createBy" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" v-if="visibleColumns.createTime" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</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="['rawMilkTest:rawMilkTest:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['rawMilkTest:rawMilkTest:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total>0"
:total="total"
@@ -520,4 +522,33 @@ onMounted(() => {
initVisibleColumns()
getList()
})
</script>
</script>
<style scoped>
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -67,17 +67,19 @@
<el-button type="success" icon="Download" @click="handleExport">导出</el-button>
</div>
<el-table :data="list" border style="width: 100%" v-loading="loading" :row-key="row => row.sheepId">
<el-table-column
v-for="col in visibleColumns"
:key="col.prop"
:label="col.label"
:prop="col.prop"
:min-width="col.minWidth || 120"
:sortable="col.sortable || false"
:formatter="col.formatter || undefined"
/>
</el-table>
<div class="table-wrapper">
<el-table :data="list" border style="width: 100%" v-loading="loading" :row-key="row => row.sheepId" height="100%">
<el-table-column
v-for="col in visibleColumns"
:key="col.prop"
:label="col.label"
:prop="col.prop"
:min-width="col.minWidth || 120"
:sortable="col.sortable || false"
:formatter="col.formatter || undefined"
/>
</el-table>
</div>
<el-pagination
v-show="total > 0"
@@ -288,4 +290,31 @@ export default {
background-color: #f5f7fa;
border-radius: 4px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -69,33 +69,35 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="weightCorrectionList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="日期" align="center" prop="datetime" width="180" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="厂区" align="center" prop="factory">
<template #default="scope">
<dict-tag :options="da_ranch" :value="scope.row.factory"/>
</template>
</el-table-column>
<el-table-column label="实际奶量" align="center" prop="actual" sortable />
<el-table-column label="系统奶量" align="center" prop="systemMilk" sortable />
<el-table-column label="称重系数" align="center" prop="coefficient" sortable>
<template #default="scope">
<span>{{ scope.row.coefficient ? scope.row.coefficient.toFixed(2) : '' }}</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="['weightCorrection:weightCorrection:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['weightCorrection:weightCorrection:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="table-wrapper">
<el-table v-loading="loading" :data="weightCorrectionList" @selection-change="handleSelectionChange" height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="日期" align="center" prop="datetime" width="180" sortable>
<template #default="scope">
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="厂区" align="center" prop="factory">
<template #default="scope">
<dict-tag :options="da_ranch" :value="scope.row.factory"/>
</template>
</el-table-column>
<el-table-column label="实际奶量" align="center" prop="actual" sortable />
<el-table-column label="系统奶量" align="center" prop="systemMilk" sortable />
<el-table-column label="称重系数" align="center" prop="coefficient" sortable>
<template #default="scope">
<span>{{ scope.row.coefficient ? scope.row.coefficient.toFixed(2) : '' }}</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="['weightCorrection:weightCorrection:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['weightCorrection:weightCorrection:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total>0"
:total="total"
@@ -324,4 +326,32 @@ getList()
.el-form-item {
margin-bottom: 15px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -75,126 +75,128 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="yogurtTestList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="来源"
align="center"
prop="source"
v-if="selectedColumns.includes('source')" />
<el-table-column
label="检测日期"
align="center"
prop="datetime"
width="180"
v-if="selectedColumns.includes('datetime')"
sortable>
<template #default="scope">
<span>{{ formatDate(scope.row.datetime) }}</span>
</template>
</el-table-column>
<el-table-column
label="脂肪g/100g"
align="center"
prop="fat"
v-if="selectedColumns.includes('fat')"
sortable />
<el-table-column
label="蛋白质g/100g"
align="center"
prop="protein"
v-if="selectedColumns.includes('protein')"
sortable />
<el-table-column
label="非脂g/100g"
align="center"
prop="nonFat"
v-if="selectedColumns.includes('nonFat')"
sortable />
<el-table-column
label="酸度oT"
align="center"
prop="acidity"
v-if="selectedColumns.includes('acidity')"
sortable />
<el-table-column
label="菌落总数1"
align="center"
prop="bacterialColony1"
v-if="selectedColumns.includes('bacterialColony1')"
sortable />
<el-table-column
label="菌落总数2"
align="center"
prop="bacterialClony2"
v-if="selectedColumns.includes('bacterialClony2')"
sortable />
<el-table-column
label="菌落总数3"
align="center"
prop="bacterialClony3"
v-if="selectedColumns.includes('bacterialClony3')"
sortable />
<el-table-column
label="菌落总数4"
align="center"
prop="bacterialClony4"
v-if="selectedColumns.includes('bacterialClony4')"
sortable />
<el-table-column
label="菌落总数5"
align="center"
prop="bacterialClony5"
v-if="selectedColumns.includes('bacterialClony5')"
sortable />
<el-table-column
label="酵母菌(CFU/g)"
align="center"
prop="yeast"
v-if="selectedColumns.includes('yeast')"
sortable />
<el-table-column
label="霉菌(CFU/g)"
align="center"
prop="mould"
v-if="selectedColumns.includes('mould')"
sortable />
<el-table-column
label="乳酸菌(CFU/g)"
align="center"
prop="lacto"
v-if="selectedColumns.includes('lacto')"
sortable />
<div class="table-wrapper">
<el-table v-loading="loading" :data="yogurtTestList" @selection-change="handleSelectionChange" height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="来源"
align="center"
prop="source"
v-if="selectedColumns.includes('source')" />
<el-table-column
label="检测日期"
align="center"
prop="datetime"
width="180"
v-if="selectedColumns.includes('datetime')"
sortable>
<template #default="scope">
<span>{{ formatDate(scope.row.datetime) }}</span>
</template>
</el-table-column>
<el-table-column
label="备注"
align="center"
prop="comment"
v-if="selectedColumns.includes('comment')" />
<el-table-column
label="创建人"
align="center"
prop="createBy"
v-if="selectedColumns.includes('createBy')" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
v-if="selectedColumns.includes('createTime')"
sortable>
<template #default="scope">
<span>{{ formatDateTime(scope.row.createTime) }}</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="['yogurtTest:yogurtTest:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['yogurtTest:yogurtTest:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-table-column
label="脂肪g/100g"
align="center"
prop="fat"
v-if="selectedColumns.includes('fat')"
sortable />
<el-table-column
label="蛋白质g/100g"
align="center"
prop="protein"
v-if="selectedColumns.includes('protein')"
sortable />
<el-table-column
label="非脂g/100g"
align="center"
prop="nonFat"
v-if="selectedColumns.includes('nonFat')"
sortable />
<el-table-column
label="酸度oT"
align="center"
prop="acidity"
v-if="selectedColumns.includes('acidity')"
sortable />
<el-table-column
label="菌落总数1"
align="center"
prop="bacterialColony1"
v-if="selectedColumns.includes('bacterialColony1')"
sortable />
<el-table-column
label="菌落总数2"
align="center"
prop="bacterialClony2"
v-if="selectedColumns.includes('bacterialClony2')"
sortable />
<el-table-column
label="菌落总数3"
align="center"
prop="bacterialClony3"
v-if="selectedColumns.includes('bacterialClony3')"
sortable />
<el-table-column
label="菌落总数4"
align="center"
prop="bacterialClony4"
v-if="selectedColumns.includes('bacterialClony4')"
sortable />
<el-table-column
label="菌落总数5"
align="center"
prop="bacterialClony5"
v-if="selectedColumns.includes('bacterialClony5')"
sortable />
<el-table-column
label="酵母菌(CFU/g)"
align="center"
prop="yeast"
v-if="selectedColumns.includes('yeast')"
sortable />
<el-table-column
label="霉菌(CFU/g)"
align="center"
prop="mould"
v-if="selectedColumns.includes('mould')"
sortable />
<el-table-column
label="乳酸菌(CFU/g)"
align="center"
prop="lacto"
v-if="selectedColumns.includes('lacto')"
sortable />
<el-table-column
label="备注"
align="center"
prop="comment"
v-if="selectedColumns.includes('comment')" />
<el-table-column
label="创建人"
align="center"
prop="createBy"
v-if="selectedColumns.includes('createBy')" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
v-if="selectedColumns.includes('createTime')"
sortable>
<template #default="scope">
<span>{{ formatDateTime(scope.row.createTime) }}</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="['yogurtTest:yogurtTest:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['yogurtTest:yogurtTest:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total>0"
@@ -644,4 +646,31 @@ onMounted(() => {
.el-dialog__body {
padding: 15px 20px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

File diff suppressed because it is too large Load Diff

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

View File

@@ -1271,16 +1271,31 @@ function handleDelete(row) {
}).catch(() => {})
}
// 8. 修改 handleExport 函数,导出时也包含自定义筛选条件
// 8. 修复:精确读取表格实际显示的列进行导出
function handleExport() {
const exportParams = { ...queryParams.value }
// 如果有自定义筛选条件,合并到导出参数中
// 1. 处理勾选的行
if (ids.value.length > 0) {
exportParams.exportIds = ids.value.join(',')
}
// 2. 【核心修复】直接遍历 columns只有 visible 为 true 的才允许导出!绝对防漏
const actualVisibleCols = Object.keys(columns).filter(key => columns[key].visible);
if (actualVisibleCols.length > 0) {
exportParams.visibleColumns = actualVisibleCols.join(',')
}
// 3. 合并自定义筛选
if (isCustomFilterActive.value && Object.keys(customFilterParams.value).length > 0) {
Object.assign(exportParams, customFilterParams.value)
}
proxy.download('sheep_file/sheep_file/export', exportParams, `sheep_file_${new Date().getTime()}.xlsx`)
const tipMsg = ids.value.length > 0 ? "是否确认导出选中的数据项?" : "未勾选具体行,是否确认导出当前条件下的所有数据?";
proxy.$modal.confirm(tipMsg).then(function() {
proxy.download('sheep_file/sheep_file/export', exportParams, `sheep_file_${new Date().getTime()}.xlsx`)
}).catch(() => {})
}
// 打开列设置对话框

View File

@@ -132,8 +132,8 @@
</el-col>
<el-col :span="12">
<el-form-item label="总价" prop="price">
<el-input v-model="form.price" placeholder="请输入总价" />
<el-form-item label="总价" prop="totalPrice">
<el-input :model-value="totalPrice.toFixed(2)" readonly />
</el-form-item>
</el-col>
@@ -298,21 +298,17 @@
const { queryParams, form, rules } = toRefs(data)
function getItemCodeOptions(row) {
if (row.itemType === "embryo") {
return this.CodeDict.embryo || []
}
if (row.itemType === "semen") {
return this.CodeDict.semen || []
}
return []
return CodeDict[row.itemType] || []
}
/** 查询销售主单列表 */
function getList() {
loading.value = true
getSaleCodeDict().then(response => {
Object.assign(CodeDict, response.data)
})
console.log(CodeDict)
listSale(queryParams.value).then(response => {
saleList.value = response.rows
total.value = response.total
@@ -320,6 +316,16 @@
})
}
// =============== 表单总价计算 =================
const totalPrice = computed(() => {
return ddSaleItemList.value.reduce((sum, item) => {
const price = Number(item.unitPrice) || 0
return sum + price
}, 0)
})
// ================ End ========================
// =============== 用户字典数据 =================
const userDict = ref([])
@@ -418,6 +424,8 @@
proxy.$refs["saleRef"].validate(valid => {
if (valid) {
form.value.ddSaleItemList = ddSaleItemList.value
// 将计算的总价赋值给表单数据
form.value.price = totalPrice.value.toFixed(2)
if (form.value.id != null) {
updateSale(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")

View File

@@ -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([])

View File

@@ -605,12 +605,27 @@ function loadSheepTypeList() {
});
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
function handlePaste() {
nextTick(() => handlePasteSubmit())

View File

@@ -522,12 +522,27 @@ function loadVarietyOptions() {
})
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
function clearEarNumbers() {

View File

@@ -540,12 +540,27 @@ function loadVarietyOptions() {
varietyOptions.value = res.rows;
})
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
function clearEarNumbers() {
queryParams.value.manageTagsList = []

View File

@@ -454,13 +454,27 @@ function getSheepfoldOptions() {
sheepfoldOptions.value = res.rows
})
}
/* 远程搜耳号 */
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
/* 清空所有耳号 */

View File

@@ -497,12 +497,29 @@ function getSheepfoldOptions() {
sheepfoldOptions.value = res.rows
})
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
// 搜索耳号的方法(用于下拉框远程搜索)
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
// 调用API搜索耳号
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
/* 粘贴事件 */
function handlePaste() {

View File

@@ -467,12 +467,29 @@ function getSheepfoldOptions() {
sheepfoldOptions.value = res.rows
})
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
// 搜索耳号的方法(用于下拉框远程搜索)
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
// 调用API搜索耳号
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
/* 粘贴事件 */
function handlePaste() {

View File

@@ -629,7 +629,29 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
// 搜索耳号的方法(用于下拉框远程搜索)
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
try {
// 调用API搜索耳号
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
} finally {
earLoading.value = false
}
}
//重置搜索框
function resetQuery() {
daterangeTransDate.value = [];

View File

@@ -769,12 +769,29 @@ function handleDelete(row) {
})
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
// 搜索耳号的方法(用于下拉框远程搜索)
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
// 调用API搜索耳号
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
async function handleRanchChange(ranchName) {
if (!ranchName) {

View File

@@ -559,12 +559,27 @@ function filterSheepfold(query) {
fold.sheepfoldName.includes(query)
)
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
function clearEarNumbers() {
queryParams.value.manageTagsList = []

View File

@@ -508,12 +508,27 @@ const fetchTechnicalList = () => {
technicalOptions.value = []
})
}
function searchEarNumber(query) {
if (!query) { earOptions.value = []; return }
const searchEarNumber = async (query) => {
if (!query || query.trim() === '') {
earOptions.value = []
return
}
earLoading.value = true
searchEarNumbers(query.trim()).then(res => {
earOptions.value = res.data || []
}).finally(() => earLoading.value = false)
try {
const res = await searchEarNumbers(query.trim())
if (res.code === 200 && Array.isArray(res.data)) {
earOptions.value = res.data
} else {
earOptions.value = []
}
} catch (error) {
console.error('搜索耳号失败:', error)
earOptions.value = []
proxy.$modal.msgError('搜索耳号失败')
} finally {
earLoading.value = false
}
}
function clearEarNumbers() {
queryParams.value.manageTagsList = []

View File

@@ -70,37 +70,39 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="customerList" @selection-change="handleSelectionChange" @sort-change="handleSortChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="客户名称" align="center" prop="name" />
<el-table-column label="客户电话" align="center" prop="phone" sortable="custom" />
<el-table-column label="所在地区" align="center" width="150" show-overflow-tooltip>
<template #default="scope">
{{ (scope.row.province || '') + (scope.row.city || '') + (scope.row.district || '') }}
</template>
</el-table-column>
<el-table-column label="详细地址" align="center" prop="address" show-overflow-tooltip />
<el-table-column label="创建人" align="center" prop="createBy" width="100" />
<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>
<div class="table-wrapper">
<el-table v-loading="loading" :data="customerList" @selection-change="handleSelectionChange" @sort-change="handleSortChange" height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="客户名称" align="center" prop="name" />
<el-table-column label="客户电话" align="center" prop="phone" sortable="custom" />
<el-table-column label="所在地区" align="center" width="150" show-overflow-tooltip>
<template #default="scope">
{{ (scope.row.province || '') + (scope.row.city || '') + (scope.row.district || '') }}
</template>
</el-table-column>
<el-table-column label="详细地址" align="center" prop="address" show-overflow-tooltip />
<el-table-column label="创建人" align="center" prop="createBy" width="100" />
<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" prop="remark" show-overflow-tooltip />
<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="['customer:customer:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['customer:customer:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<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="['customer:customer:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['customer:customer:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
@@ -345,4 +347,33 @@ function handleExport() {
...queryParams.value
}, `customer_${new Date().getTime()}.xlsx`)
}
</script>
</script>
<style scoped>
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -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"
@@ -180,63 +192,65 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</el-row>
<el-table v-loading="loading" :data="saleRecordList" @selection-change="handleSelectionChange" style="width: 100%">
<el-table-column type="selection" width="55" align="center" fixed="left"/>
<el-table-column label="耳号" align="center" prop="bsManageTags" width="120" fixed="left" show-overflow-tooltip />
<el-table-column label="品种" align="center" prop="variety" width="100" show-overflow-tooltip />
<el-table-column label="事件类型" align="center" prop="eventType" width="80" />
<el-table-column label="销售日期" align="center" prop="saleDate" width="100">
<template #default="scope"><span>{{ parseTime(scope.row.saleDate, '{y}-{m}-{d}') }}</span></template>
</el-table-column>
<el-table-column label="羊只类型" align="center" prop="sheepName" width="100" show-overflow-tooltip />
<el-table-column label="性别" align="center" prop="gender" width="60" />
<el-table-column label="月龄" align="center" prop="monthAge" width="60" />
<el-table-column label="胎次" align="center" prop="parity" width="60" />
<el-table-column label="当前重量(kg)" align="center" prop="currentWeight" width="110" />
<el-table-column label="计价方式" align="center" prop="pricingMethod" width="100" />
<el-table-column label="单价" align="center" prop="unitPrice" width="100">
<template #default="scope">
{{ scope.row.unitPrice }}
<span v-if="scope.row.pricingMethod=='按体重'">/kg</span>
<span v-else-if="scope.row.unitPrice"></span>
</template>
</el-table-column>
<el-table-column label="重量(kg)" align="center" prop="avgWeight" width="100" />
<el-table-column label="单只羊价格(元)" align="center" prop="avgPricePerSheep" width="120" />
<el-table-column label="销售类别" align="center" prop="saleType" width="100" show-overflow-tooltip />
<el-table-column label="客户名称" align="center" prop="customerName" width="120" show-overflow-tooltip />
<el-table-column label="客户电话" align="center" prop="customerPhone" width="120" show-overflow-tooltip />
<el-table-column label="所在地区" align="center" prop="customerArea" width="150" show-overflow-tooltip />
<el-table-column label="详细地址" align="center" prop="customerAddress" width="180" show-overflow-tooltip />
<el-table-column label="销售人员" align="center" prop="salesPersonName" width="100" />
<el-table-column label="检疫证号" align="center" prop="quarantineNo" width="120" show-overflow-tooltip />
<el-table-column label="审批编号" align="center" prop="approvalNo" width="120" show-overflow-tooltip />
<el-table-column label="疾病类型" align="center" prop="diseaseType" :formatter="diseaseTypeFormat" width="100" show-overflow-tooltip />
<el-table-column label="次要原因" align="center" prop="secondaryReason" width="120" show-overflow-tooltip />
<el-table-column label="羊舍" align="center" prop="sheepfoldName" width="120" show-overflow-tooltip />
<el-table-column label="班组" align="center" prop="groupCode" width="100" />
<el-table-column label="繁育状态" align="center" prop="breed" width="80" />
<el-table-column label="产后天数" align="center" prop="postLambingDay" width="80" />
<el-table-column label="泌乳天数" align="center" prop="lactationDay" width="80" />
<el-table-column label="怀孕天数" align="center" prop="lambingDay" width="80" />
<el-table-column label="技术员" align="center" prop="technicianName" width="100" />
<el-table-column label="处理人" align="center" prop="handlerName" width="100" />
<el-table-column label="创建人" align="center" prop="createdByName" width="100" />
<el-table-column label="创建日期" align="center" prop="createdAt" width="100">
<template #default="scope"><span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span></template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" width="150" show-overflow-tooltip />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['saleRecord:saleRecord:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['saleRecord:saleRecord:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="table-wrapper">
<el-table v-loading="loading" :data="saleRecordList" @selection-change="handleSelectionChange" style="width: 100%" height="100%">
<el-table-column type="selection" width="55" align="center" fixed="left"/>
<el-table-column label="耳号" align="center" prop="bsManageTags" width="120" fixed="left" show-overflow-tooltip />
<el-table-column label="品种" align="center" prop="variety" width="100" show-overflow-tooltip />
<el-table-column label="事件类型" align="center" prop="eventType" width="80" />
<el-table-column label="销售日期" align="center" prop="saleDate" width="100">
<template #default="scope"><span>{{ parseTime(scope.row.saleDate, '{y}-{m}-{d}') }}</span></template>
</el-table-column>
<el-table-column label="羊只类型" align="center" prop="sheepName" width="100" show-overflow-tooltip />
<el-table-column label="性别" align="center" prop="gender" width="60" />
<el-table-column label="月龄" align="center" prop="monthAge" width="60" />
<el-table-column label="胎次" align="center" prop="parity" width="60" />
<el-table-column label="当前重量(kg)" align="center" prop="currentWeight" width="110" />
<el-table-column label="计价方式" align="center" prop="pricingMethod" width="100" />
<el-table-column label="单价" align="center" prop="unitPrice" width="100">
<template #default="scope">
{{ scope.row.unitPrice }}
<span v-if="scope.row.pricingMethod=='按体重'">/kg</span>
<span v-else-if="scope.row.unitPrice"></span>
</template>
</el-table-column>
<el-table-column label="重量(kg)" align="center" prop="avgWeight" width="100" />
<el-table-column label="单只羊价格(元)" align="center" prop="avgPricePerSheep" width="120" />
<el-table-column label="销售类别" align="center" prop="saleType" width="100" show-overflow-tooltip />
<el-table-column label="客户名称" align="center" prop="customerName" width="120" show-overflow-tooltip />
<el-table-column label="客户电话" align="center" prop="customerPhone" width="120" show-overflow-tooltip />
<el-table-column label="所在地区" align="center" prop="customerArea" width="150" show-overflow-tooltip />
<el-table-column label="详细地址" align="center" prop="customerAddress" width="180" show-overflow-tooltip />
<el-table-column label="销售人员" align="center" prop="salesPersonName" width="100" />
<el-table-column label="检疫证号" align="center" prop="quarantineNo" width="120" show-overflow-tooltip />
<el-table-column label="审批编号" align="center" prop="approvalNo" width="120" show-overflow-tooltip />
<el-table-column label="疾病类型" align="center" prop="diseaseType" :formatter="diseaseTypeFormat" width="100" show-overflow-tooltip />
<el-table-column label="次要原因" align="center" prop="secondaryReason" width="120" show-overflow-tooltip />
<el-table-column label="羊舍" align="center" prop="sheepfoldName" width="120" show-overflow-tooltip />
<el-table-column label="班组" align="center" prop="groupCode" width="100" />
<el-table-column label="繁育状态" align="center" prop="breed" width="80" />
<el-table-column label="产后天数" align="center" prop="postLambingDay" width="80" />
<el-table-column label="泌乳天数" align="center" prop="lactationDay" width="80" />
<el-table-column label="怀孕天数" align="center" prop="lambingDay" width="80" />
<el-table-column label="技术员" align="center" prop="technicianName" width="100" />
<el-table-column label="处理人" align="center" prop="handlerName" width="100" />
<el-table-column label="创建" align="center" prop="createdByName" width="100" />
<el-table-column label="创建日期" align="center" prop="createdAt" width="100">
<template #default="scope"><span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span></template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" width="150" show-overflow-tooltip />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['saleRecord:saleRecord:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['saleRecord:saleRecord:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination v-show="total>0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
@@ -255,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>
@@ -453,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')
@@ -607,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('')
}
// 【新增】移除单个查询耳号
@@ -647,6 +699,8 @@ function handleSheepfoldChange(val) {
console.error("获取耳号失败", err)
})
}
// 切换羊舍后,立刻用空关键字查一下该羊舍下的耳号,更新下拉列表
formSearchEarNumberMethod('')
}
function handleTagChange(tags) {
@@ -774,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() {
@@ -802,6 +869,14 @@ function diseaseTypeFormat(row) {
// 如果静态选项 label 和 value 一样,则直接返回即可
return row.diseaseType
}
// 3. 【新增】输入框获取焦点时,如果还没数据,自动查询
function handleQueryEarNumberFocus() {
// 为了防止每次点击都发请求,判断如果没有输入内容且下拉框为空,才去查默认数据
if (earNumberQueryOptions.value.length === 0) {
searchEarNumberMethod('')
}
}
</script>
<style scoped>
@@ -815,4 +890,31 @@ function diseaseTypeFormat(row) {
background-color: #f5f7fa;
border-radius: 4px;
}
/* 1. 将整个页面容器变为弹性布局,并固定总高度 */
.app-container {
/* calc(100vh - 84px) 中的 84px 是顶部导航栏和标签栏的大致高度,
如果你的系统顶部更高或更低,可以适当调整这个数值(例如 100px 或 120px) */
height: calc(100vh - 84px);
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 2. 让搜索表单、操作按钮、应用筛选提示、分页组件 不被挤压变形 */
.el-form,
.mb8,
.applied-filters,
.pagination-container {
flex-shrink: 0;
}
/* 3. 让刚刚新增的表格包裹层自动撑满中间的所有剩余空间 */
.table-wrapper {
flex: 1; /* 占据所有剩余空间 */
min-height: 0; /* 🌟 关键:防止 flex 子项高度无限撑开导致页面出现滚动条 */
overflow: hidden;
display: flex;
flex-direction: column;
}
</style>