Compare commits
39 Commits
90953eed61
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4dbefa9d2 | ||
|
|
14d85c7bbb | ||
| 4ff466b2c7 | |||
| 3bfc2cffce | |||
|
|
191ea111f7 | ||
|
|
5fb6cecde5 | ||
|
|
f5722e4a1b | ||
| da77287c0f | |||
| b9febb4874 | |||
| ca9f7c4a1a | |||
| 79ba77c138 | |||
|
|
1b8c32c271 | ||
|
|
dda3f8bdf7 | ||
| 8a331158e5 | |||
| 2abd257ba4 | |||
| 9591d47827 | |||
| cb8dacad92 | |||
|
|
a0507927df | ||
|
|
37813178aa | ||
| 467733e2c3 | |||
| 83beadc988 | |||
| 9a6e31a5be | |||
| bcb1970c1c | |||
| 6ade881750 | |||
| 2e82622cf1 | |||
| f05ab75821 | |||
| cffa082285 | |||
| 88d3b4364f | |||
| e7a59de3ae | |||
| b7a611307e | |||
|
|
5eab7c7b82 | ||
|
|
6e58af0fea | ||
| 4484c74f94 | |||
| f54156892e | |||
| 01c6b1a909 | |||
| 5474efd3f4 | |||
| 801446f2cd | |||
| 5555d6a747 | |||
| ab3efaa405 |
@@ -82,4 +82,14 @@ export function getBreedRecordsByTimeRange(sheepId, startDate, endDate) {
|
||||
url: `/Breeding_records/Breeding_records/getByTimeRange/${sheepId}/${startDate}/${endDate}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 模糊搜索耳号(用于表单 autocomplete)
|
||||
// gender: 'ewe'=母羊 'ram'=公羊 不传=不限
|
||||
export function searchBreedEarNumbers(query, gender) {
|
||||
return request({
|
||||
url: '/Breeding_records/Breeding_records/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { query, gender }
|
||||
})
|
||||
}
|
||||
@@ -75,4 +75,4 @@ export function exportSperm(query) {
|
||||
data: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,3 +42,11 @@ export function delDeworm(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/deworm/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,3 +42,12 @@ export function delDiagnosis(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/diagnosis/diagnosis/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,3 +42,11 @@ export function delDisinfect(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function searchSheepfold(query) {
|
||||
return request({
|
||||
url: '/biosafety/disinfect/searchSheepfold',
|
||||
method: 'get',
|
||||
params: {sheepfold: query}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,3 +42,12 @@ export function delHealth(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/health/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delImmunity(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/immunity/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delQuarantine(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/quarantine/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delTreatment(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/treatment/treatment/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
@@ -42,3 +42,12 @@ export function delUsageInfo(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询耳号
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/biosafety/usageInfo/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { sheepNo: query }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,3 +8,11 @@ export function getUserByPost(query) {
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 根据查看岗位
|
||||
export function getPostTeam() {
|
||||
return request({
|
||||
url: '/userPost/getPostTeam',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -58,4 +58,30 @@ export function getDonorFemaleList() {
|
||||
url: '/embryo/flush/donorFemaleList',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取供体公羊下拉列表
|
||||
export function getDonorMaleList() {
|
||||
return request({
|
||||
url: '/embryo/flush/donorMaleList',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据耳号获取基础信息
|
||||
export function getSheepInfo(manageTag) {
|
||||
return request({
|
||||
url: '/embryo/flush/getSheepInfo',
|
||||
method: 'get',
|
||||
params: { manageTag }
|
||||
})
|
||||
}
|
||||
|
||||
// 计算胚胎品种
|
||||
export function calculateEmbryoVariety(maleVariety, femaleVariety) {
|
||||
return request({
|
||||
url: '/embryo/flush/calculateVariety',
|
||||
method: 'get',
|
||||
params: { maleVariety, femaleVariety }
|
||||
})
|
||||
}
|
||||
63
src/api/embryodetail/embryodetail.js
Normal file
63
src/api/embryodetail/embryodetail.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询可供移植的胚胎明细
|
||||
// flushId 可选:传则只查该批次,不传则返回所有可移植胚胎
|
||||
export function listAvailableEmbryos(flushId) {
|
||||
return request({
|
||||
url: '/embryo/detail/available',
|
||||
method: 'get',
|
||||
params: flushId ? { flushId } : {}
|
||||
})
|
||||
}
|
||||
|
||||
// 将某枚胚胎标记为已移植,并关联配种记录ID
|
||||
export function markEmbryoTransferred(id, breedRecordId) {
|
||||
return request({
|
||||
url: '/embryo/detail/markTransferred',
|
||||
method: 'post',
|
||||
params: { id, breedRecordId }
|
||||
})
|
||||
}
|
||||
|
||||
// 批量标记胚胎已移植,并同步冲胚表统计字段
|
||||
// data: { ids: [1,2,3], breedRecordId: 100 }
|
||||
export function markBatchEmbryoTransferred(data) {
|
||||
return request({
|
||||
url: '/Breeding_records/Breeding_records/markBatchEmbryoTransferred',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 根据配种记录ID查询已移植的胚胎明细列表(用于"查看胚胎"弹窗)
|
||||
export function getEmbryosByBreedRecord(breedRecordId) {
|
||||
return request({
|
||||
url: '/Breeding_records/Breeding_records/embryosByBreedRecord/' + breedRecordId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据冲胚记录ID查询胚胎明细列表(含父记录字段,供冲胚编辑/查看回显用)
|
||||
export function listEmbryosByFlushId(flushId) {
|
||||
return request({
|
||||
url: `/embryo/detail/byFlush/${flushId}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取单条胚胎明细
|
||||
export function getEmbryoDetail(id) {
|
||||
return request({
|
||||
url: `/embryo/detail/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 修改单条胚胎明细(如修改去向、存储方式)
|
||||
export function updateEmbryoDetail(data) {
|
||||
return request({
|
||||
url: '/embryo/detail',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -18,22 +18,63 @@ export function getBreedPlanGenerate(id) {
|
||||
}
|
||||
|
||||
// 筛选符合条件的母羊
|
||||
export function selectEligibleEwe() {
|
||||
export function selectEligibleEwe(params) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/selectEwe',
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 筛选符合条件的公羊
|
||||
export function selectEligibleRam() {
|
||||
export function selectEligibleRam(params) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/selectRam',
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 自动生成配种计划
|
||||
/**
|
||||
* 导出已选母羊/公羊配对表(按轮询自动配对,用户可在Excel中调整后再导入)
|
||||
* @param {Object} data - { eweIds: [], ramIds: [] }
|
||||
*/
|
||||
export function exportSelectedPairs(data) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/exportPairs',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析上传的配对Excel,返回预览数据,不生成计划
|
||||
* 使用 FormData 上传文件
|
||||
* @param {FormData} formData - 包含 file 字段的表单数据
|
||||
*/
|
||||
export function parsePairsFromExcel(formData) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/parsePairs',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据导入的配对数据生成配种计划
|
||||
* @param {Object} data - { planType: 1, pairs: [{eweEarNo, ramEarNo, eweId, ramId}] }
|
||||
*/
|
||||
export function generateBreedPlanFromPairs(data) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/generateFromPairs',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 自动生成配种计划(按比例分配,原有逻辑)
|
||||
export function autoGenerateBreedPlan(data) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/auto',
|
||||
@@ -85,24 +126,15 @@ export function viewBreedPlan(id) {
|
||||
})
|
||||
}
|
||||
|
||||
// 导出配种计划详情
|
||||
// 导出配种计划详情(已审批计划的详细Excel)
|
||||
export function exportBreedPlanDetails(id) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/export/' + id,
|
||||
method: 'get',
|
||||
method: 'post',
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 修改配种计划详情
|
||||
export function updateBreedPlan(data) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/update',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除配种计划生成
|
||||
export function delBreedPlanGenerate(id) {
|
||||
return request({
|
||||
@@ -114,9 +146,18 @@ export function delBreedPlanGenerate(id) {
|
||||
// 模糊查询母羊耳号列表
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/mating_plan/generate/search_ear_numbers', // 根据实际路径修改
|
||||
url: '/mating_plan/generate/search_ear_numbers',
|
||||
method: 'get',
|
||||
params: { query }
|
||||
})
|
||||
}
|
||||
|
||||
// 下载配对模板(空白模板,只有表头)
|
||||
export function downloadPairTemplate() {
|
||||
return request({
|
||||
url: '/mating_plan/generate/exportPairs',
|
||||
method: 'post',
|
||||
data: { eweIds: [], ramIds: [] },
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -1,5 +1,27 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 【修改】增加 sheepfoldId 过滤参数
|
||||
export function searchEarNumbers(query, sheepfoldId) {
|
||||
return request({
|
||||
url: '/saleRecord/saleRecord/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { query, sheepfoldId }
|
||||
})
|
||||
}
|
||||
|
||||
// 【新增】查询存栏羊只列表(用于根据羊舍筛选耳号)
|
||||
// 假设后端有一个基础的羊只档案查询接口,如果没有,需要后端支持
|
||||
// 这里暂时复用 getSheepInfo 的路径或者假设有一个 /file/sheep/list 接口
|
||||
// 如果你没有专门的羊只列表接口,我们可以尝试用 getSheepInfo 的逻辑变通,或者你需要在后端增加一个 listSheep 接口
|
||||
export function listSheepInventory(query) {
|
||||
return request({
|
||||
// 修改为真实的后端接口路径
|
||||
url: '/saleRecord/saleRecord/listSheepBySheepfoldId',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询羊只销售记录列表
|
||||
export function listSaleRecord(query) {
|
||||
return request({
|
||||
@@ -60,3 +82,12 @@ export function getSheepInfo(bsManageTags) {
|
||||
params: { bsManageTags }
|
||||
})
|
||||
}
|
||||
|
||||
// 【新增】查询已销售的羊只耳号(用于查询栏)
|
||||
export function searchSoldEarNumbers(query) {
|
||||
return request({
|
||||
url: '/saleRecord/saleRecord/searchSoldEarNumbers',
|
||||
method: 'get',
|
||||
params: { query }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -86,4 +86,12 @@ export function searchHandler(query) {
|
||||
method: 'get',
|
||||
params: { query }
|
||||
})
|
||||
}
|
||||
|
||||
export function searchEarNumbers(query) {
|
||||
return request({
|
||||
url: '/sheep_death/death/search_ear_numbers', // 根据实际路径修改
|
||||
method: 'get',
|
||||
params: { query }
|
||||
})
|
||||
}
|
||||
@@ -21,6 +21,10 @@
|
||||
/>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
<div class="sidebar-version">
|
||||
构建版本: {{ commitId }}<br/>
|
||||
<div>构建时间: {{ formatTime(buildTime) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -32,6 +36,21 @@ import useAppStore from '@/store/modules/app'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import usePermissionStore from '@/store/modules/permission'
|
||||
|
||||
const buildTime = __BUILD_TIME__
|
||||
const commitId = __COMMIT_ID__
|
||||
const formatTime = (time) => {
|
||||
return new Intl.DateTimeFormat('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false,
|
||||
timeZone: 'Asia/Shanghai'
|
||||
}).format(new Date(time))
|
||||
}
|
||||
|
||||
|
||||
const route = useRoute()
|
||||
const appStore = useAppStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
@@ -101,4 +120,22 @@ const activeMenu = computed(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
.sidebar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.menu-wrapper {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar-version {
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: left;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createWebHistory, createRouter } from 'vue-router'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
/* Layout */
|
||||
import Layout from '@/layout'
|
||||
|
||||
@@ -83,6 +83,24 @@ export const constantRoutes = [
|
||||
meta: { title: '个人中心', icon: 'user' }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/fileManagement',
|
||||
component: Layout,
|
||||
hidden: true, // 若不需要在侧边栏显示「档案管理」菜单,设为 true
|
||||
redirect: 'noRedirect',
|
||||
children: [
|
||||
{
|
||||
path: 'pedigree', // 最终路径为 /fileManagement/pedigree
|
||||
component: () => import('@/views/fileManagement/pedigree/index.vue'),
|
||||
name: 'Pedigree',
|
||||
meta: {
|
||||
title: '羊只系谱',
|
||||
activeMenu: '/fileManagement/pedigree' // 高亮对应的菜单(可选)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
@@ -159,6 +177,28 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/fileManagement',
|
||||
component: Layout,
|
||||
hidden: false, // 是否在侧边栏显示,默认 false 显示
|
||||
redirect: 'noRedirect',
|
||||
name: 'FileManagement',
|
||||
meta: {
|
||||
title: '档案管理',
|
||||
icon: 'example' // 你可以换成合适的图标名(如 'tree')
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'pedigree', // 最终路径 /fileManagement/pedigree
|
||||
component: () => import('@/views/fileManagement/pedigree/index.vue'),
|
||||
name: 'Pedigree',
|
||||
meta: {
|
||||
title: '系谱图',
|
||||
activeMenu: '/fileManagement/pedigree'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +1,114 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
|
||||
<el-form-item label="耳号" prop="allEarNumbers">
|
||||
<el-select
|
||||
v-model="queryParams.allEarNumbers"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="请输入耳号搜索"
|
||||
:remote-method="searchEarNumber"
|
||||
:loading="earNumberLoading"
|
||||
style="width: 240px"
|
||||
clearable
|
||||
<el-form class="sticky-search-form" model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
|
||||
<!-- 给每个 el-form-item 添加 sticky-item 类 -->
|
||||
<el-form-item label="耳号" prop="allEarNumbers" class="sticky-item">
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
|
||||
<!-- 主选择器:不显示已选标签 -->
|
||||
<el-select
|
||||
v-model="queryParams.allEarNumbers"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="输入耳号搜索"
|
||||
:remote-method="searchEarNumber"
|
||||
:loading="earNumberLoading"
|
||||
allow-create
|
||||
default-first-option
|
||||
collapse-tags
|
||||
:max-collapse-tags="0"
|
||||
style="width: 300px"
|
||||
@change="handleEarNumberChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in earNumberOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<!-- 辅助粘贴输入框 -->
|
||||
<el-input
|
||||
v-model="pasteInput"
|
||||
placeholder="或粘贴多个耳号(空格/换行/逗号分隔)"
|
||||
style="width: 300px"
|
||||
@paste="handlePaste"
|
||||
@keyup.enter="handlePasteSubmit"
|
||||
clearable
|
||||
>
|
||||
<template #append>
|
||||
<el-button @click="handlePasteSubmit" :icon="Plus">添加</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<!-- 耳号计数显示 -->
|
||||
<el-tag
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="large"
|
||||
>
|
||||
已选: {{ queryParams.allEarNumbers.length }} 个
|
||||
</el-tag>
|
||||
|
||||
<!-- 清空按钮 -->
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="clearAllEarNumbers"
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
:icon="Delete"
|
||||
>
|
||||
清空全部
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 已选耳号展示区域(默认显示2个,可展开) -->
|
||||
<div
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
class="selected-ear-numbers-display"
|
||||
style="margin-top: 10px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in earNumberOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<!-- 显示前2个或全部耳号 -->
|
||||
<el-tag
|
||||
v-for="(tag, index) in displayedEarNumbers"
|
||||
:key="tag"
|
||||
closable
|
||||
@close="handleRemoveEarNumber(tag)"
|
||||
style="margin: 4px;"
|
||||
type="success"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
|
||||
<!-- 展开/收起按钮 -->
|
||||
<el-button
|
||||
v-if="queryParams.allEarNumbers.length > defaultShowCount"
|
||||
type="primary"
|
||||
link
|
||||
@click="toggleExpand"
|
||||
style="margin-left: 8px;"
|
||||
>
|
||||
{{ isExpanded ? '收起' : `展开剩余 ${queryParams.allEarNumbers.length - defaultShowCount} 个` }}
|
||||
<el-icon class="el-icon--right">
|
||||
<component :is="isExpanded ? ArrowUp : ArrowDown" />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="是否在群" prop="isInHerd">
|
||||
<!-- 其他表单项也添加 sticky-item 类 -->
|
||||
<el-form-item label="是否在群" prop="isInHerd" class="sticky-item">
|
||||
<el-select v-model="queryParams.isInHerd" placeholder="请选择" clearable style="width: 240px">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="断奶日期" style="width: 340px">
|
||||
<el-form-item label="断奶日期" style="width: 340px" class="sticky-item">
|
||||
<el-date-picker
|
||||
v-model="daterangeTime"
|
||||
value-format="YYYY-MM-DD"
|
||||
@@ -43,7 +120,7 @@
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="羊只类别" prop="sheepCategory">
|
||||
<el-form-item label="羊只类别" prop="sheepCategory" class="sticky-item">
|
||||
<el-select v-model="queryParams.sheepCategory" placeholder="请选择羊只类别" clearable style="width: 240px">
|
||||
<el-option label="种公羊" value="种公羊"></el-option>
|
||||
<el-option label="基础母羊" value="基础母羊"></el-option>
|
||||
@@ -52,21 +129,22 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="性别" prop="gender">
|
||||
<el-form-item label="性别" prop="gender" class="sticky-item">
|
||||
<el-select v-model="queryParams.gender" placeholder="请选择性别" clearable style="width: 240px">
|
||||
<el-option label="公" value="公"></el-option>
|
||||
<el-option label="母" value="母"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="是否留养" prop="status">
|
||||
|
||||
<el-form-item label="是否留养" prop="status" class="sticky-item">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择是否留养" clearable style="width: 240px">
|
||||
<el-option label="留养" value="1"></el-option>
|
||||
<el-option label="不留养" value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
|
||||
<!-- 搜索按钮不放 sticky,或者也可以放 -->
|
||||
<el-form-item class="sticky-item">
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
@@ -231,7 +309,29 @@
|
||||
|
||||
<script setup name="Weaning_record">
|
||||
import { listWeaning_record, getWeaning_record, delWeaning_record, addWeaning_record, updateWeaning_record, getSheepIdByEarNumber, searchEarNumbers } from "@/api/Weaning/weaning_record"
|
||||
import { ref, computed, nextTick } from 'vue'
|
||||
import { ArrowUp, ArrowDown, Plus, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
// 响应式数据
|
||||
const pasteInput = ref('') // 批量粘贴输入框
|
||||
const earNumberOptions = ref([]) // 耳号下拉选项
|
||||
const earNumberLoading = ref(false) // 耳号加载状态
|
||||
const isExpanded = ref(false) // 控制耳号展开/折叠状态
|
||||
const defaultShowCount = 2 // 默认显示的耳号数量
|
||||
|
||||
// 计算属性:控制显示的耳号列表
|
||||
const displayedEarNumbers = computed(() => {
|
||||
if (!queryParams.value.allEarNumbers || queryParams.value.allEarNumbers.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
// 如果展开或总数<=2,显示全部;否则只显示前2个
|
||||
if (isExpanded.value || queryParams.value.allEarNumbers.length <= defaultShowCount) {
|
||||
return queryParams.value.allEarNumbers
|
||||
} else {
|
||||
return queryParams.value.allEarNumbers.slice(0, defaultShowCount)
|
||||
}
|
||||
})
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const weaning_recordList = ref([])
|
||||
@@ -245,9 +345,6 @@ const total = ref(0)
|
||||
const title = ref("")
|
||||
const daterangeTime = ref([]) // 时间范围数组
|
||||
|
||||
// 远程搜索相关
|
||||
const earNumberOptions = ref([])
|
||||
const earNumberLoading = ref(false)
|
||||
|
||||
const data = reactive({
|
||||
form: {},
|
||||
@@ -299,27 +396,7 @@ function getList() {
|
||||
})
|
||||
}
|
||||
|
||||
/** 远程搜索耳号 */
|
||||
function searchEarNumber(query) {
|
||||
if (query !== '') {
|
||||
earNumberLoading.value = true
|
||||
searchEarNumbers(query).then(response => {
|
||||
earNumberOptions.value = response.data || []
|
||||
earNumberLoading.value = false
|
||||
}).catch(() => {
|
||||
earNumberOptions.value = []
|
||||
earNumberLoading.value = false
|
||||
})
|
||||
} else {
|
||||
earNumberOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
function cancel() {
|
||||
open.value = false
|
||||
reset()
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
function reset() {
|
||||
@@ -347,11 +424,10 @@ function handleQuery() {
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
daterangeTime.value = []
|
||||
queryParams.value.allEarNumbers = [] // 🔥 必须添加
|
||||
earNumberOptions.value = []
|
||||
isExpanded.value = false
|
||||
proxy.resetForm("queryRef")
|
||||
// 必须手动清空多选数组
|
||||
queryParams.value.allEarNumbers = []
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
@@ -434,14 +510,179 @@ function handleExport() {
|
||||
}, `weaning_record_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
|
||||
/** 处理粘贴事件 */
|
||||
function handlePaste(event) {
|
||||
nextTick(() => {
|
||||
handlePasteSubmit()
|
||||
})
|
||||
}
|
||||
|
||||
/** 处理粘贴内容提交 */
|
||||
function handlePasteSubmit() {
|
||||
if (!pasteInput.value || pasteInput.value.trim() === '') {
|
||||
return
|
||||
}
|
||||
|
||||
// 支持多种分隔符: 空格、换行、逗号、制表符
|
||||
const separators = /[\s,,\n\r\t]+/
|
||||
const earNumbers = pasteInput.value
|
||||
.trim()
|
||||
.split(separators)
|
||||
.filter(item => item.trim() !== '')
|
||||
.map(item => item.trim())
|
||||
|
||||
if (earNumbers.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// 去重并添加到已选列表
|
||||
const existingSet = new Set(queryParams.value.allEarNumbers || [])
|
||||
const newEarNumbers = []
|
||||
const duplicates = []
|
||||
|
||||
earNumbers.forEach(earNumber => {
|
||||
if (!existingSet.has(earNumber)) {
|
||||
newEarNumbers.push(earNumber)
|
||||
existingSet.add(earNumber)
|
||||
} else {
|
||||
duplicates.push(earNumber)
|
||||
}
|
||||
})
|
||||
|
||||
// 添加新耳号
|
||||
if (newEarNumbers.length > 0) {
|
||||
queryParams.value.allEarNumbers = [
|
||||
...(queryParams.value.allEarNumbers || []),
|
||||
...newEarNumbers
|
||||
]
|
||||
|
||||
const message = `成功添加 ${newEarNumbers.length} 个耳号,当前共 ${queryParams.value.allEarNumbers.length} 个` +
|
||||
(duplicates.length > 0 ? `,已忽略 ${duplicates.length} 个重复耳号` : '')
|
||||
|
||||
proxy.$modal.msgSuccess(message)
|
||||
} else if (duplicates.length > 0) {
|
||||
proxy.$modal.msgWarning(`所有耳号均已存在,当前共 ${queryParams.value.allEarNumbers.length} 个`)
|
||||
}
|
||||
|
||||
// 清空输入框
|
||||
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 {
|
||||
earNumberOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
/** 耳号选择变化处理 */
|
||||
function handleEarNumberChange(value) {
|
||||
queryParams.value.allEarNumbers = [...new Set(value)]
|
||||
console.log(`已选择 ${queryParams.value.allEarNumbers.length} 个耳号:`, queryParams.value.allEarNumbers)
|
||||
}
|
||||
|
||||
/** 切换展开/收起状态 */
|
||||
function toggleExpand() {
|
||||
isExpanded.value = !isExpanded.value
|
||||
}
|
||||
|
||||
/** 移除单个耳号 */
|
||||
function handleRemoveEarNumber(tag) {
|
||||
const index = queryParams.value.allEarNumbers.indexOf(tag)
|
||||
if (index > -1) {
|
||||
queryParams.value.allEarNumbers.splice(index, 1)
|
||||
proxy.$modal.msgSuccess('已移除该耳号')
|
||||
}
|
||||
|
||||
// 如果删除后剩余<=2个,自动收起
|
||||
if (queryParams.value.allEarNumbers.length <= defaultShowCount) {
|
||||
isExpanded.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 清空所有耳号 */
|
||||
function clearAllEarNumbers() {
|
||||
proxy.$modal.confirm('确定要清空所有已选择的耳号吗?').then(() => {
|
||||
queryParams.value.allEarNumbers = []
|
||||
pasteInput.value = ''
|
||||
earNumberOptions.value = []
|
||||
isExpanded.value = false // 重置展开状态
|
||||
proxy.$modal.msgSuccess('已清空所有耳号')
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
|
||||
|
||||
getList()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
/* 核心样式:让每个表单项粘性定位 */
|
||||
.sticky-search-form {
|
||||
position: relative;
|
||||
}
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
|
||||
.sticky-item {
|
||||
position: sticky;
|
||||
top: 0; /* 粘在视口顶部 */
|
||||
background: #fff; /* 白色背景,避免透明 */
|
||||
z-index: 100;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1); /* 轻微阴影区分 */
|
||||
align-self: flex-start; /* 重要:在 flex 布局中保持粘性 */
|
||||
}
|
||||
|
||||
/* 保持原有样式 */
|
||||
.selected-ear-numbers-display {
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
padding: 8px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed #dcdfe6;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
.selected-ear-numbers-display::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.selected-ear-numbers-display::-webkit-scrollbar-thumb {
|
||||
background-color: #dcdfe6;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.selected-ear-numbers-display::-webkit-scrollbar-track {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
/* 隐藏 el-select 的下拉箭头(可选) */
|
||||
:deep(.el-select__caret) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -78,6 +78,13 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="在群" :value="0" />
|
||||
<el-option label="离群" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
@@ -359,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'
|
||||
@@ -469,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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -762,7 +783,13 @@
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
proxy.download('biosafety/deworm/export', { ...queryParams }, `deworm_${Date.now()}.xlsx`)
|
||||
queryParams.ids = ids.value;
|
||||
try {
|
||||
proxy.download('biosafety/deworm/export', { ...queryParams }, `驱虫_${Date.now()}.xlsx`)
|
||||
} finally {
|
||||
queryParams.ids = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------ 药品/处方/下拉 ------------------ */
|
||||
|
||||
@@ -100,8 +100,13 @@
|
||||
<el-form-item label="治疗天数" prop="treatDay">
|
||||
<el-input v-model="queryParams.treatDay" placeholder="请输入治疗天数" clearable />
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="在群" :value="0" />
|
||||
<el-option label="离群" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
@@ -264,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([]) //自定义技术员数组变量
|
||||
@@ -320,6 +319,7 @@ const daterangeDatetime = ref([]) // 日期区间
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
ids: null,
|
||||
sheepNo: null,
|
||||
allEarNumbers: null,
|
||||
datetime: null,
|
||||
@@ -627,11 +627,13 @@ function handleDelete(row) {
|
||||
|
||||
/* ---------- 导出 ---------- */
|
||||
function handleExport() {
|
||||
proxy.download(
|
||||
'diagnosis/diagnosis/export',
|
||||
{ ...queryParams.value },
|
||||
`diagnosis_${new Date().getTime()}.xlsx`
|
||||
)
|
||||
queryParams.value.ids = ids.value;;
|
||||
try {
|
||||
proxy.download('diagnosis/diagnosis/export',{ ...queryParams.value },`诊疗_${new Date().getTime()}.xlsx`)
|
||||
} finally {
|
||||
queryParams.ids = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ---------- 弹窗取消 / 重置 ---------- */
|
||||
|
||||
@@ -11,21 +11,25 @@
|
||||
<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-form-item label="技术员">
|
||||
<el-select v-model="queryParams.technical" filterable clearable placeholder="请输入技术员姓名" style="width: 100%"
|
||||
<el-select v-model="queryParams.technician" filterable clearable placeholder="请输入技术员姓名" style="width: 100%"
|
||||
@change="handleTechnicalChange">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value">
|
||||
<span style="float: left">{{ item.label }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
<el-form-item label="消毒方式" prop="way">
|
||||
<el-select v-model="queryParams.way" clearable placeholder="请选择消毒方式" filterable style="width: 200px">
|
||||
@@ -108,15 +112,13 @@
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-form-item label="技术员">
|
||||
<el-select v-model="form.technical" filterable clearable placeholder="请输入技术员姓名" style="width: 100%"
|
||||
<el-select v-model="form.technician" filterable clearable placeholder="请输入技术员姓名" style="width: 100%"
|
||||
@change="handleTechnicalChange">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value">
|
||||
<span style="float: left">{{ item.label }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -212,16 +214,14 @@
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="技术员">
|
||||
<el-form-item label="技术员">
|
||||
<el-select v-model="editForm.technical" filterable clearable placeholder="请输入技术员姓名" style="width: 100%"
|
||||
<el-select v-model="editForm.technician" filterable clearable placeholder="请输入技术员姓名" style="width: 100%"
|
||||
@change="handleTechnicalChange">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value">
|
||||
<span style="float: left">{{ item.label }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -302,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'
|
||||
@@ -351,6 +351,7 @@ const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
sheepfoldId: null,
|
||||
sheepfoldIds: [], // 新增一个数组属性用于多选羊舍
|
||||
technician: null
|
||||
})
|
||||
|
||||
@@ -517,7 +518,13 @@ function handleDelete(row) {
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
proxy.download('biosafety/disinfect/export', { ...queryParams }, `消毒_${Date.now()}.xlsx`)
|
||||
queryParams.ids = ids.value;
|
||||
try {
|
||||
proxy.download('biosafety/disinfect/export', { ...queryParams }, `消毒_${Date.now()}.xlsx`)
|
||||
} finally {
|
||||
queryParams.ids = 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 }))
|
||||
})
|
||||
|
||||
@@ -81,6 +81,13 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="在群" :value="0" />
|
||||
<el-option label="离群" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
@@ -367,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([]) //自定义技术员数组变量
|
||||
@@ -794,7 +800,12 @@ function handleDelete(row) {
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
proxy.download('biosafety/health/export', { ...queryParams }, `保健_${Date.now()}.xlsx`)
|
||||
queryParams.ids = ids.value;
|
||||
try {
|
||||
proxy.download('biosafety/health/export', { ...queryParams }, `保健_${Date.now()}.xlsx`)
|
||||
} finally {
|
||||
queryParams.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------ 药品/处方/下拉 ------------------ */
|
||||
|
||||
@@ -79,6 +79,13 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="在群" :value="0" />
|
||||
<el-option label="离群" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
@@ -364,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([]) //自定义技术员数组变量
|
||||
@@ -413,7 +419,8 @@ const queryParams = reactive({
|
||||
pageSize: 20,
|
||||
sheepNo: null,
|
||||
allEarNumbers: [], // 修改:改为数组,支持多耳号
|
||||
technical: null,
|
||||
technician: null,
|
||||
ids: null,
|
||||
orderByColumn: null, // 新增
|
||||
isAsc: null // 新增
|
||||
})
|
||||
@@ -790,7 +797,12 @@ function handleDelete(row) {
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
proxy.download('biosafety/immunity/export', { ...queryParams }, `免疫_${Date.now()}.xlsx`)
|
||||
queryParams.ids = ids.value;
|
||||
try {
|
||||
proxy.download('biosafety/immunity/export', { ...queryParams }, `免疫_${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------ 药品/处方/下拉 ------------------ */
|
||||
|
||||
@@ -106,6 +106,13 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="在群" :value="0" />
|
||||
<el-option label="离群" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item>
|
||||
@@ -392,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()
|
||||
@@ -421,7 +421,7 @@ const technicalOptions = ref([]) //自定义技术员数组变量
|
||||
|
||||
// 获取技术员列表
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
getUserByPost({ postCode: '' })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
@@ -860,11 +860,12 @@ function handleDelete(row) {
|
||||
|
||||
/* 导出 */
|
||||
function handleExport() {
|
||||
proxy.download(
|
||||
'/biosafety/quarantine/export',
|
||||
queryParams,
|
||||
`检疫_${Date.now()}.xlsx`
|
||||
)
|
||||
queryParams.ids = ids.value;
|
||||
try {
|
||||
proxy.download('/biosafety/quarantine/export', queryParams, `检疫_${Date.now()}.xlsx`)
|
||||
} finally {
|
||||
queryParams.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
/* 跳转治疗 */
|
||||
|
||||
@@ -85,6 +85,13 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="在群" :value="0" />
|
||||
<el-option label="离群" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
@@ -459,7 +466,6 @@
|
||||
<el-row :gutter="20" style="margin-top:20px;">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="兽医">
|
||||
<el-input v-model="editForm.veterinarian" placeholder="请输入兽医姓名" />
|
||||
<el-select v-model="editForm.veterinarian" filterable clearable placeholder="请输入兽医姓名" style="width: 100%"
|
||||
@change="handleTechnicalChange">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value">
|
||||
@@ -522,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'
|
||||
@@ -531,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([]) //自定义技术员数组变量
|
||||
@@ -1022,7 +1027,13 @@ function handleDelete(row) {
|
||||
.then(() => { getList(); proxy.$modal.msgSuccess('删除成功') })
|
||||
}
|
||||
function handleExport() {
|
||||
proxy.download('treatment/treatment/export', { ...queryParams }, `治疗记录_${Date.now()}.xlsx`)
|
||||
queryParams.ids = ids.value;
|
||||
try {
|
||||
proxy.download('treatment/treatment/export', { ...queryParams }, `治疗记录_${Date.now()}.xlsx`)
|
||||
} finally {
|
||||
queryParams.ids = null;
|
||||
}
|
||||
|
||||
}
|
||||
function resetForm(formObj) {
|
||||
Object.assign(formObj, {
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="usageList" @selection-change="handleSelectionChange" max-height="650px">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="使用时间" align="center" prop="datetime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
|
||||
@@ -201,15 +202,15 @@
|
||||
|
||||
<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')
|
||||
|
||||
const ids = ref([]) // 选中项ID列表
|
||||
const usageList = ref([])
|
||||
const swMedicineUsageDetailsList = ref([])
|
||||
const open = ref(false)
|
||||
@@ -473,11 +474,13 @@ function rowSwMedicineUsageDetailsIndex({ rowIndex }) {
|
||||
return `row-${rowIndex}`
|
||||
}
|
||||
function handleExport() {
|
||||
proxy.download(
|
||||
'biosafety/usageInfo/export',
|
||||
{ ...queryParams.value },
|
||||
`药品使用记录_${new Date().getTime()}.xlsx`
|
||||
)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('biosafety/usageInfo/export',{ ...queryParams.value },`药品使用记录_${new Date().getTime()}.xlsx`)
|
||||
} finally {
|
||||
queryParams.ids = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 初始化 */
|
||||
|
||||
@@ -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">
|
||||
@@ -369,7 +454,8 @@
|
||||
<el-row :gutter="20" class="lamb-form-content">
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="`羔羊耳号`" :prop="`lambForms.${index}.lambEarNumber`">
|
||||
<el-input v-model="lamb.lambEarNumber" placeholder="请输入羔羊耳号" />
|
||||
<el-input v-model="lamb.lambEarNumber" placeholder="请输入羔羊耳号"
|
||||
@input="handleLambEarNumberInput(index)"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
@@ -451,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>
|
||||
@@ -538,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: {
|
||||
@@ -567,6 +665,64 @@ const data = reactive({
|
||||
}
|
||||
})
|
||||
|
||||
// 品种 ID 常量定义 (对应 ScEmbryoFlushServiceImpl)
|
||||
const VARIETY_IDS = {
|
||||
HUYANG: 1, // 湖羊
|
||||
DONGFULISHENG: 2, // 东佛里生
|
||||
HUIJIAO: 3, // 回交
|
||||
JIZA_1: 4, // 级杂一代
|
||||
JIZA_2: 5, // 级杂二代
|
||||
JIZA_3: 6, // 级杂三代
|
||||
SHIDAI_1: 7, // 一世代
|
||||
SHIDAI_2: 8, // 二世代
|
||||
SHIDAI_3: 9, // 三世代
|
||||
SHIDAI_4: 10 // 四世代
|
||||
};
|
||||
|
||||
/** * 品种计算核心逻辑 (参考后端 calculateEmbryoVarietyById)
|
||||
* @param {number} maleId 公羊品种ID
|
||||
* @param {number} femaleId 母羊品种ID
|
||||
* @returns {number|null} 羔羊品种ID
|
||||
*/
|
||||
function calculateLambBreedId(maleId, femaleId) {
|
||||
if (!maleId || !femaleId) return null;
|
||||
|
||||
// 湖羊 x 湖羊 -> 湖羊
|
||||
if (maleId === VARIETY_IDS.HUYANG && femaleId === VARIETY_IDS.HUYANG) return VARIETY_IDS.HUYANG;
|
||||
|
||||
// 东佛里生 x 东佛里生 -> 东佛里生
|
||||
if (maleId === VARIETY_IDS.DONGFULISHENG && femaleId === VARIETY_IDS.DONGFULISHENG) return VARIETY_IDS.DONGFULISHENG;
|
||||
|
||||
// 东佛里生 x 湖羊 -> 级杂一代
|
||||
if (maleId === VARIETY_IDS.DONGFULISHENG && femaleId === VARIETY_IDS.HUYANG) return VARIETY_IDS.JIZA_1;
|
||||
|
||||
// 东佛里生 x 级杂一代 -> 级杂二代
|
||||
if (maleId === VARIETY_IDS.DONGFULISHENG && femaleId === VARIETY_IDS.JIZA_1) return VARIETY_IDS.JIZA_2;
|
||||
|
||||
// 东佛里生 x 级杂二代 -> 级杂三代
|
||||
if (maleId === VARIETY_IDS.DONGFULISHENG && femaleId === VARIETY_IDS.JIZA_2) return VARIETY_IDS.JIZA_3;
|
||||
|
||||
// 东佛里生 x 级杂三代 -> 东佛里生
|
||||
if (maleId === VARIETY_IDS.DONGFULISHENG && femaleId === VARIETY_IDS.JIZA_3) return VARIETY_IDS.DONGFULISHENG;
|
||||
|
||||
// 湖羊 x 级杂三代 -> 回交
|
||||
if (maleId === VARIETY_IDS.HUYANG && femaleId === VARIETY_IDS.JIZA_3) return VARIETY_IDS.HUIJIAO;
|
||||
|
||||
// 湖羊 x 回交 -> 回交
|
||||
if (maleId === VARIETY_IDS.HUYANG && femaleId === VARIETY_IDS.HUIJIAO) return VARIETY_IDS.HUIJIAO;
|
||||
|
||||
// 世代计算规则
|
||||
const isMaleCapable = (maleId >= 3 && maleId <= 10);
|
||||
if (isMaleCapable) {
|
||||
if (femaleId === VARIETY_IDS.JIZA_2) return VARIETY_IDS.SHIDAI_1;
|
||||
if (femaleId === VARIETY_IDS.SHIDAI_1) return VARIETY_IDS.SHIDAI_2;
|
||||
if (femaleId === VARIETY_IDS.SHIDAI_2) return VARIETY_IDS.SHIDAI_3;
|
||||
if (femaleId === VARIETY_IDS.SHIDAI_3) return VARIETY_IDS.SHIDAI_4;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
|
||||
// 新增:获取技术员列表
|
||||
@@ -754,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() {
|
||||
// 清空相关联动字段
|
||||
@@ -763,15 +932,18 @@ 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
|
||||
}
|
||||
|
||||
/** 母羊耳号失焦处理 - 自动查询配种信息 */
|
||||
function handleEarNumberBlur() {
|
||||
const earNumber = form.value.femaleEarNumber
|
||||
if (!earNumber || earNumber.trim() === '') {
|
||||
return
|
||||
}
|
||||
|
||||
const earNumber = form.value.femaleEarNumber;
|
||||
if (!earNumber || earNumber.trim() === '') return;
|
||||
// 调用API查询配种信息
|
||||
getBreedingInfo(earNumber.trim()).then(response => {
|
||||
if (response.code === 200 && response.data) {
|
||||
@@ -784,7 +956,26 @@ 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);
|
||||
|
||||
// 临时存储这些信息,用于初始化羔羊列表
|
||||
form.value._calculatedLambBreedId = calculateLambBreedId(mVariety?.id, fVariety?.id);
|
||||
form.value._fatherLineage = breedingData.male_lineage || ''; // 确保后端返回了家系字段
|
||||
if (lambForms.value && lambForms.value.length > 0) {
|
||||
lambForms.value.forEach(lamb => {
|
||||
lamb.lineage = form.value._fatherLineage;
|
||||
lamb.lambBreed = form.value._calculatedLambBreedId;
|
||||
});
|
||||
}
|
||||
proxy.$modal.msgSuccess("已自动匹配父母品种及家系信息");
|
||||
proxy.$modal.msgSuccess("已自动填充配种信息")
|
||||
} else {
|
||||
proxy.$modal.msgWarning(response.msg || "未找到该母羊的配种记录")
|
||||
@@ -801,14 +992,24 @@ 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 })
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
@@ -834,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 = []
|
||||
@@ -867,6 +1074,8 @@ function handleSelectionChange(selection) {
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd() {
|
||||
reset()
|
||||
// 默认产羔日期为今天
|
||||
form.value.createTime = new Date().toISOString().split('T')[0]
|
||||
open.value = true
|
||||
title.value = "添加产羔记录"
|
||||
}
|
||||
@@ -886,21 +1095,21 @@ function handleUpdate(row) {
|
||||
|
||||
/** 产羔数量变化处理 */
|
||||
function handleLambsBornChange() {
|
||||
const count = parseInt(form.value.lambsBorn) || 0
|
||||
if (count > 0 && count <= 10) { // 限制最大数量
|
||||
showLambForms.value = true
|
||||
lambForms.value = Array.from({ length: count }, (_, index) => ({
|
||||
const count = parseInt(form.value.lambsBorn) || 0;
|
||||
if (count > 0 && count <= 10) {
|
||||
showLambForms.value = true;
|
||||
lambForms.value = Array.from({ length: count }, () => ({
|
||||
lambEarNumber: '',
|
||||
gender: '',
|
||||
isRetained: false,
|
||||
isRetained: true, // 默认留养
|
||||
birthWeight: null,
|
||||
lambBreed: null,
|
||||
lineage: '',
|
||||
birthday: ''
|
||||
}))
|
||||
lambBreed: form.value._calculatedLambBreedId, // 自动填充计算出的品种
|
||||
lineage: form.value._fatherLineage, // 随父亲家系
|
||||
birthday: form.value.createTime || new Date().toISOString().split('T')[0] // 随产羔日期
|
||||
}));
|
||||
} else {
|
||||
showLambForms.value = false
|
||||
lambForms.value = []
|
||||
showLambForms.value = false;
|
||||
lambForms.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -967,6 +1176,24 @@ function submitForm() {
|
||||
}
|
||||
})
|
||||
}
|
||||
/** 监听羔羊耳号输入,自动识别性别 */
|
||||
function handleLambEarNumberInput(index) {
|
||||
const lamb = lambForms.value[index]
|
||||
const earNumber = lamb.lambEarNumber
|
||||
|
||||
// 确保耳号长度至少有2位
|
||||
if (earNumber && earNumber.length >= 2) {
|
||||
// 获取第二个字符并转大写
|
||||
const secondChar = earNumber.charAt(1).toUpperCase()
|
||||
|
||||
if (secondChar === 'F') {
|
||||
lamb.gender = 'female' // 对应 <el-option label="母" value="female">
|
||||
} else if (secondChar === 'M') {
|
||||
lamb.gender = 'male' // 对应 <el-option label="公" value="male">
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -117,8 +119,9 @@ function getList() {
|
||||
|
||||
// 处理日期范围
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
queryParams.datetimeStart = dateRange.value[0];
|
||||
queryParams.datetimeEnd = dateRange.value[1];
|
||||
// 修改:手动拼接时间
|
||||
queryParams.datetimeStart = dateRange.value[0] + ' 00:00:00';
|
||||
queryParams.datetimeEnd = dateRange.value[1] + ' 23:59:59';
|
||||
} else {
|
||||
queryParams.datetimeStart = null;
|
||||
queryParams.datetimeEnd = null;
|
||||
@@ -181,8 +184,9 @@ function beforeUpload(file) {
|
||||
function handleExport() {
|
||||
// 导出前确认日期参数
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
queryParams.datetimeStart = dateRange.value[0];
|
||||
queryParams.datetimeEnd = dateRange.value[1];
|
||||
// 修改:手动拼接时间
|
||||
queryParams.datetimeStart = dateRange.value[0] + ' 00:00:00';
|
||||
queryParams.datetimeEnd = dateRange.value[1] + ' 23:59:59';
|
||||
} else {
|
||||
queryParams.datetimeStart = null;
|
||||
queryParams.datetimeEnd = null;
|
||||
@@ -219,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>
|
||||
@@ -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"
|
||||
@@ -218,8 +220,9 @@ function getList() {
|
||||
loading.value = true
|
||||
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
queryParams.datetimeStart = dateRange.value[0];
|
||||
queryParams.datetimeEnd = dateRange.value[1];
|
||||
// 修改:手动拼接时间,确保覆盖结束当天的全天时间
|
||||
queryParams.datetimeStart = dateRange.value[0] + ' 00:00:00';
|
||||
queryParams.datetimeEnd = dateRange.value[1] + ' 23:59:59';
|
||||
} else {
|
||||
queryParams.datetimeStart = null;
|
||||
queryParams.datetimeEnd = null;
|
||||
@@ -270,8 +273,9 @@ function uploadError(err) {
|
||||
|
||||
function handleExport() {
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
queryParams.datetimeStart = dateRange.value[0];
|
||||
queryParams.datetimeEnd = dateRange.value[1];
|
||||
// 修改:导出时也需要拼接时间
|
||||
queryParams.datetimeStart = dateRange.value[0] + ' 00:00:00';
|
||||
queryParams.datetimeEnd = dateRange.value[1] + ' 23:59:59';
|
||||
} else {
|
||||
queryParams.datetimeStart = null;
|
||||
queryParams.datetimeEnd = null;
|
||||
@@ -313,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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -1,28 +1,102 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
|
||||
|
||||
<el-form-item label="耳号" prop="manageTagsList">
|
||||
<el-select
|
||||
v-model="queryParams.manageTagsList"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="请输入耳号搜索"
|
||||
:remote-method="searchEarNumber"
|
||||
:loading="earNumberLoading"
|
||||
style="width: 240px"
|
||||
clearable
|
||||
@change="handleQuery"
|
||||
|
||||
<el-form-item label="母羊耳号" prop="allEarNumbers">
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
|
||||
<!-- 主选择器:不显示已选标签 -->
|
||||
<el-select
|
||||
v-model="queryParams.allEarNumbers"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="输入耳号搜索"
|
||||
:remote-method="searchEarNumber"
|
||||
:loading="earNumberLoading"
|
||||
allow-create
|
||||
default-first-option
|
||||
collapse-tags
|
||||
:max-collapse-tags="0"
|
||||
style="width: 300px"
|
||||
@change="handleEarNumberChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in earNumberOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<!-- 辅助粘贴输入框 -->
|
||||
<el-input
|
||||
v-model="pasteInput"
|
||||
placeholder="或粘贴多个耳号(空格/换行/逗号分隔)"
|
||||
style="width: 300px"
|
||||
@paste="handlePaste"
|
||||
@keyup.enter="handlePasteSubmit"
|
||||
clearable
|
||||
>
|
||||
<template #append>
|
||||
<el-button @click="handlePasteSubmit" :icon="Plus">添加</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<!-- 耳号计数显示 -->
|
||||
<el-tag
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="large"
|
||||
>
|
||||
已选: {{ queryParams.allEarNumbers.length }} 个
|
||||
</el-tag>
|
||||
|
||||
<!-- 清空按钮 -->
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="clearAllEarNumbers"
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
:icon="Delete"
|
||||
>
|
||||
清空全部
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 已选耳号展示区域(默认显示2个,可展开) -->
|
||||
<div
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
class="selected-ear-numbers-display"
|
||||
style="margin-top: 10px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in earNumberOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<!-- 显示前2个或全部耳号 -->
|
||||
<el-tag
|
||||
v-for="(tag, index) in displayedEarNumbers"
|
||||
:key="tag"
|
||||
closable
|
||||
@close="handleRemoveEarNumber(tag)"
|
||||
style="margin: 4px;"
|
||||
type="success"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
|
||||
<!-- 展开/收起按钮 -->
|
||||
<el-button
|
||||
v-if="queryParams.allEarNumbers.length > defaultShowCount"
|
||||
type="primary"
|
||||
link
|
||||
@click="toggleExpand"
|
||||
style="margin-left: 8px;"
|
||||
>
|
||||
{{ isExpanded ? '收起' : `展开剩余 ${queryParams.allEarNumbers.length - defaultShowCount} 个` }}
|
||||
<el-icon class="el-icon--right">
|
||||
<component :is="isExpanded ? ArrowUp : ArrowDown" />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="干奶日期" style="width: 308px">
|
||||
@@ -179,7 +253,30 @@ import { listDrymilk, getDrymilk, delDrymilk, addDrymilk, updateDrymilk, searchE
|
||||
import { getUserByPost } from '@/api/common/user' // 新增引入
|
||||
import { listUser } from "@/api/system/user";
|
||||
import axios from 'axios';
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { ref, computed, nextTick } from 'vue'
|
||||
import { ArrowUp, ArrowDown, Plus, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
// 响应式数据
|
||||
const pasteInput = ref('') // 批量粘贴输入框
|
||||
const earNumberOptions = ref([]) // 耳号下拉选项
|
||||
const earNumberLoading = ref(false) // 耳号加载状态
|
||||
const isExpanded = ref(false) // 控制耳号展开/折叠状态
|
||||
const defaultShowCount = 2 // 默认显示的耳号数量
|
||||
|
||||
// 计算属性:控制显示的耳号列表
|
||||
const displayedEarNumbers = computed(() => {
|
||||
if (!queryParams.value.allEarNumbers || queryParams.value.allEarNumbers.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
// 如果展开或总数<=2,显示全部;否则只显示前2个
|
||||
if (isExpanded.value || queryParams.value.allEarNumbers.length <= defaultShowCount) {
|
||||
return queryParams.value.allEarNumbers
|
||||
} else {
|
||||
return queryParams.value.allEarNumbers.slice(0, defaultShowCount)
|
||||
}
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
@@ -196,10 +293,6 @@ const dateRange = ref([])
|
||||
const sheepfoldOptions = ref([])
|
||||
const userOptions = ref([])
|
||||
|
||||
// 耳号搜索变量
|
||||
const earNumberLoading = ref(false)
|
||||
const earNumberOptions = ref([])
|
||||
|
||||
// 新增:技术员选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
@@ -208,7 +301,8 @@ const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
manageTags: null,
|
||||
manageTags: null,
|
||||
allEarNumbers: [], // ✅ 添加这一行!
|
||||
manageTagsList: [],
|
||||
technicianList: [], // 技术员多选列表
|
||||
tecahnician: null, // 兼容旧字段
|
||||
@@ -244,21 +338,122 @@ const fetchTechnicalList = () => {
|
||||
|
||||
/** 远程搜索耳号 */
|
||||
function searchEarNumber(query) {
|
||||
if (query) {
|
||||
earNumberLoading.value = true;
|
||||
searchEarNumbers(query).then(res => {
|
||||
earNumberLoading.value = false;
|
||||
const list = res.data || res.msg || res;
|
||||
earNumberOptions.value = Array.isArray(list) ? list : [];
|
||||
}).catch(err => {
|
||||
earNumberLoading.value = false;
|
||||
earNumberOptions.value = [];
|
||||
});
|
||||
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 {
|
||||
earNumberOptions.value = [];
|
||||
earNumberOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理粘贴事件 */
|
||||
function handlePaste(event) {
|
||||
nextTick(() => {
|
||||
handlePasteSubmit()
|
||||
})
|
||||
}
|
||||
|
||||
/** 处理粘贴内容提交 */
|
||||
function handlePasteSubmit() {
|
||||
if (!pasteInput.value || pasteInput.value.trim() === '') {
|
||||
return
|
||||
}
|
||||
|
||||
// 支持多种分隔符: 空格、换行、逗号、制表符
|
||||
const separators = /[\s,,\n\r\t]+/
|
||||
const earNumbers = pasteInput.value
|
||||
.trim()
|
||||
.split(separators)
|
||||
.filter(item => item.trim() !== '')
|
||||
.map(item => item.trim())
|
||||
|
||||
if (earNumbers.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// 去重并添加到已选列表
|
||||
const existingSet = new Set(queryParams.value.allEarNumbers || [])
|
||||
const newEarNumbers = []
|
||||
const duplicates = []
|
||||
|
||||
earNumbers.forEach(earNumber => {
|
||||
if (!existingSet.has(earNumber)) {
|
||||
newEarNumbers.push(earNumber)
|
||||
existingSet.add(earNumber)
|
||||
} else {
|
||||
duplicates.push(earNumber)
|
||||
}
|
||||
})
|
||||
|
||||
// 添加新耳号
|
||||
if (newEarNumbers.length > 0) {
|
||||
queryParams.value.allEarNumbers = [
|
||||
...(queryParams.value.allEarNumbers || []),
|
||||
...newEarNumbers
|
||||
]
|
||||
|
||||
const message = `成功添加 ${newEarNumbers.length} 个耳号,当前共 ${queryParams.value.allEarNumbers.length} 个` +
|
||||
(duplicates.length > 0 ? `,已忽略 ${duplicates.length} 个重复耳号` : '')
|
||||
|
||||
proxy.$modal.msgSuccess(message)
|
||||
} else if (duplicates.length > 0) {
|
||||
proxy.$modal.msgWarning(`所有耳号均已存在,当前共 ${queryParams.value.allEarNumbers.length} 个`)
|
||||
}
|
||||
|
||||
// 清空输入框
|
||||
pasteInput.value = ''
|
||||
}
|
||||
/** 耳号选择变化处理 */
|
||||
function handleEarNumberChange(value) {
|
||||
queryParams.value.allEarNumbers = [...new Set(value)]
|
||||
console.log(`已选择 ${queryParams.value.allEarNumbers.length} 个耳号:`, queryParams.value.allEarNumbers)
|
||||
}
|
||||
|
||||
/** 切换展开/收起状态 */
|
||||
function toggleExpand() {
|
||||
isExpanded.value = !isExpanded.value
|
||||
}
|
||||
|
||||
/** 移除单个耳号 */
|
||||
function handleRemoveEarNumber(tag) {
|
||||
const index = queryParams.value.allEarNumbers.indexOf(tag)
|
||||
if (index > -1) {
|
||||
queryParams.value.allEarNumbers.splice(index, 1)
|
||||
proxy.$modal.msgSuccess('已移除该耳号')
|
||||
}
|
||||
|
||||
// 如果删除后剩余<=2个,自动收起
|
||||
if (queryParams.value.allEarNumbers.length <= defaultShowCount) {
|
||||
isExpanded.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 清空所有耳号 */
|
||||
function clearAllEarNumbers() {
|
||||
proxy.$modal.confirm('确定要清空所有已选择的耳号吗?').then(() => {
|
||||
queryParams.value.allEarNumbers = []
|
||||
pasteInput.value = ''
|
||||
earNumberOptions.value = []
|
||||
isExpanded.value = false // 重置展开状态
|
||||
proxy.$modal.msgSuccess('已清空所有耳号')
|
||||
}).catch(() => {})
|
||||
}
|
||||
/** 查询干奶记录列表 */
|
||||
function getList() {
|
||||
loading.value = true
|
||||
@@ -314,14 +509,6 @@ function reset() {
|
||||
proxy.resetForm("drymilkRef")
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
dateRange.value = []
|
||||
queryParams.value.manageTagsList = []
|
||||
queryParams.value.technicianList = []
|
||||
earNumberOptions.value = []
|
||||
proxy.resetForm("queryRef")
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1
|
||||
@@ -398,10 +585,60 @@ function handleExport() {
|
||||
}
|
||||
proxy.download('drymilk/drymilk/export', params, `drymilk_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
queryParams.value.allEarNumbers = [] // 🔥 必须添加
|
||||
earNumberOptions.value = []
|
||||
isExpanded.value = false
|
||||
proxy.resetForm("queryRef")
|
||||
handleQuery()
|
||||
}
|
||||
// 初始化
|
||||
getList()
|
||||
getSheepfoldList()
|
||||
getUserList()
|
||||
fetchTechnicalList() // 初始化加载技术员列表
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 已选耳号展示区样式 */
|
||||
.selected-ear-numbers-display {
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
padding: 8px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed #dcdfe6;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.selected-ear-numbers-display::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.selected-ear-numbers-display::-webkit-scrollbar-thumb {
|
||||
background-color: #dcdfe6;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.selected-ear-numbers-display::-webkit-scrollbar-track {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.selected-ear-numbers-display .el-tag {
|
||||
margin: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selected-ear-numbers-display .el-tag:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 隐藏 el-select 的下拉箭头(可选) */
|
||||
:deep(.el-select__caret) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
724
src/views/embryodetail/embryodetail/index.vue
Normal file
724
src/views/embryodetail/embryodetail/index.vue
Normal file
@@ -0,0 +1,724 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- ===================== 搜索区域 ===================== -->
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="冲胚时间" style="width: 388px;">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="供体母号" prop="donorFemaleNo">
|
||||
<el-input v-model="queryParams.donorFemaleNo" placeholder="请输入供体母号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="供体父号" prop="donorMaleNo">
|
||||
<el-input v-model="queryParams.donorMaleNo" placeholder="请输入供体父号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- ===================== 操作按钮 ===================== -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['embryo:flush:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['embryo:flush:edit']">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['embryo:flush:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['embryo:flush:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<!-- ===================== 数据表格 ===================== -->
|
||||
<el-table v-loading="loading" :data="flushList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="冲胚时间" align="center" prop="flushTime" width="110">
|
||||
<template #default="scope">{{ parseTime(scope.row.flushTime, '{y}-{m}-{d}') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="胚胎品种" align="center" prop="embryoVariety" width="100" />
|
||||
<el-table-column label="供体母号" align="center" prop="donorFemaleNo" width="110" />
|
||||
<el-table-column label="母羊品种" align="center" prop="donorFemaleVariety" width="100" />
|
||||
<el-table-column label="供体父号" align="center" prop="donorMaleNo" width="110" />
|
||||
<el-table-column label="公羊品种" align="center" prop="donorMaleVariety" width="100" />
|
||||
<el-table-column label="胎龄(天)" align="center" prop="embryoAge" width="80" />
|
||||
<el-table-column label="A级" align="center" prop="gradeA" width="55" />
|
||||
<el-table-column label="B级" align="center" prop="gradeB" width="55" />
|
||||
<el-table-column label="C级" align="center" prop="gradeC" width="55" />
|
||||
<el-table-column label="16细胞" align="center" prop="gradeD" width="70" />
|
||||
<el-table-column label="未受精" align="center" prop="unfertilized" width="70" />
|
||||
<el-table-column label="退化" align="center" prop="degenerated" width="55" />
|
||||
<el-table-column label="冲胚数" align="center" prop="totalEmbryo" width="70" />
|
||||
<el-table-column label="有效胚" align="center" prop="validEmbryo" width="70" />
|
||||
<el-table-column label="移胚数" align="center" prop="transferred" width="70" />
|
||||
<el-table-column label="受体数" align="center" prop="recipientCnt" width="70" />
|
||||
<el-table-column label="胚胎类型" align="center" prop="embryoType" width="100" />
|
||||
<el-table-column label="胚胎来源" align="center" prop="embryoSource" width="80" />
|
||||
<el-table-column label="冲胚人" align="center" prop="flushOperator" width="80" />
|
||||
<el-table-column label="捡胚人" align="center" prop="collectOperator" width="80" />
|
||||
<el-table-column label="所在牧场" align="center" prop="ranchName" width="100" />
|
||||
<el-table-column label="备注" align="center" prop="remark" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['embryo:flush:edit']">修改</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['embryo:flush:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
:page-sizes="[20, 50, 100, 200, 500, 1000, 2000]"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- =====================================================================
|
||||
新增 / 修改 冲胚记录 Dialog
|
||||
===================================================================== -->
|
||||
<el-dialog :title="title" v-model="open" width="1000px" append-to-body>
|
||||
<el-form ref="flushRef" :model="form" :rules="rules" label-width="100px">
|
||||
|
||||
<!-- 基础信息 -->
|
||||
<el-divider content-position="left">基础信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="冲胚时间" prop="flushTime">
|
||||
<el-date-picker clearable v-model="form.flushTime" type="date"
|
||||
value-format="YYYY-MM-DD" placeholder="选择冲胚时间" style="width:100%"
|
||||
@change="handleFlushTimeChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="供体母号" prop="donorFemaleNo">
|
||||
<!-- 输入 + 从配种记录选择按钮 -->
|
||||
<el-input
|
||||
v-model="form.donorFemaleNo"
|
||||
placeholder="输入耳号或从配种记录选择"
|
||||
clearable
|
||||
style="width: calc(100% - 88px)"
|
||||
@change="handleDonorFemaleInputChange"
|
||||
/>
|
||||
<el-button
|
||||
type="primary" link style="margin-left:6px; white-space:nowrap"
|
||||
@click="openBreedRecordPicker">
|
||||
从配种记录选
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="母羊品种">
|
||||
<el-input v-model="form.donorFemaleVariety" disabled placeholder="自动填充" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="供体父号" prop="donorMaleNo">
|
||||
<el-select v-model="form.donorMaleNo" filterable clearable
|
||||
placeholder="请选择供体公羊" @change="handleDonorMaleChange" style="width:100%">
|
||||
<el-option v-for="item in donorMaleOptions" :key="item.manageTag"
|
||||
:label="item.manageTag" :value="item.manageTag">
|
||||
<span>{{ item.manageTag }}</span>
|
||||
<span style="float:right;color:#8492a6;font-size:12px">{{ item.variety }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="公羊品种">
|
||||
<el-input v-model="form.donorMaleVariety" disabled placeholder="自动填充" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="胚胎品种">
|
||||
<el-input v-model="form.embryoVariety" placeholder="自动计算/可修改" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="胎龄(天)">
|
||||
<el-input-number v-model="form.embryoAge" :min="0" controls-position="right"
|
||||
placeholder="自动计算" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="所在牧场">
|
||||
<el-input v-model="form.ranchName" disabled placeholder="自动填充" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 胚胎明细(替换原"胚胎等级"+"发育阶段"两个分区) -->
|
||||
<el-divider content-position="left">
|
||||
胚胎明细
|
||||
<span style="margin-left:8px;font-size:12px;color:#909399">
|
||||
共 {{ form.embryoDetails.length }} 枚 | 有效胚 {{ computedValidEmbryo }} 枚
|
||||
</span>
|
||||
</el-divider>
|
||||
|
||||
<!-- 快速添加按钮 -->
|
||||
<div style="margin-bottom:10px;display:flex;flex-wrap:wrap;gap:8px;">
|
||||
<el-button size="small" type="primary" @click="addEmbryo('A')">+ A级</el-button>
|
||||
<el-button size="small" type="success" @click="addEmbryo('B')">+ B级</el-button>
|
||||
<el-button size="small" type="warning" @click="addEmbryo('C')">+ C级</el-button>
|
||||
<el-button size="small" type="info" @click="addEmbryo('16细胞')">+ 16细胞</el-button>
|
||||
<el-button size="small" type="danger" plain @click="addEmbryo('未受精')">+ 未受精</el-button>
|
||||
<el-button size="small" type="danger" plain @click="addEmbryo('退化')">+ 退化</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 胚胎明细表格 -->
|
||||
<el-table :data="form.embryoDetails" border size="small" max-height="300"
|
||||
style="width:100%;margin-bottom:8px;"
|
||||
:row-class-name="embryoRowClass">
|
||||
<el-table-column label="序号" width="60" align="center">
|
||||
<template #default="scope">{{ scope.$index + 1 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="胚胎等级" width="130" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.embryoGrade" size="small" style="width:100%"
|
||||
@change="onGradeChange(scope.row)">
|
||||
<el-option label="A级" value="A" />
|
||||
<el-option label="B级" value="B" />
|
||||
<el-option label="C级" value="C" />
|
||||
<el-option label="16细胞" value="16细胞" />
|
||||
<el-option label="未受精" value="未受精" />
|
||||
<el-option label="退化" value="退化" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="去向" width="150" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.destination" size="small" style="width:100%">
|
||||
<el-option label="移植" value="移植" />
|
||||
<el-option label="冷冻保存" value="冷冻保存" />
|
||||
<el-option label="遗弃" value="遗弃" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="存储方式" align="center">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.storageMethod" size="small" style="width:100%"
|
||||
clearable placeholder="选择存储方式">
|
||||
<el-option label="胚胎保存液" value="胚胎保存液" />
|
||||
<el-option label="液氮冷冻" value="液氮冷冻" />
|
||||
<el-option label="PBS缓冲液" value="PBS缓冲液" />
|
||||
<el-option label="其他" value="其他" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="70" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="danger" icon="Delete" @click="removeEmbryo(scope.$index)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="form.embryoDetails.length === 0"
|
||||
style="text-align:center;color:#909399;padding:12px;border:1px dashed #e0e0e0;border-radius:4px;">
|
||||
暂无胚胎明细,请点击上方按钮添加
|
||||
</div>
|
||||
|
||||
<!-- 统计信息(只读,自动计算) -->
|
||||
<el-divider content-position="left">统计信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="冲胚数">
|
||||
<el-input :value="form.embryoDetails.length" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="有效胚">
|
||||
<el-input :value="computedValidEmbryo" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="移胚数" title="由配种记录使用后自动同步">
|
||||
<el-input :value="form.transferred || 0" disabled placeholder="自动同步" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="受体数" title="由配种记录使用后自动同步">
|
||||
<el-input :value="form.recipientCnt || 0" disabled placeholder="自动同步" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 其他信息 -->
|
||||
<el-divider content-position="left">其他信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="胚胎类型" prop="embryoType">
|
||||
<el-select v-model="form.embryoType" placeholder="请选择" style="width:100%">
|
||||
<el-option label="体内胚胎冻胚" value="体内胚胎冻胚" />
|
||||
<el-option label="体内胚胎鲜胚" value="体内胚胎鲜胚" />
|
||||
<el-option label="体外胚胎冻胚" value="体外胚胎冻胚" />
|
||||
<el-option label="体外胚胎鲜胚" value="体外胚胎鲜胚" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="胚胎来源" prop="embryoSource">
|
||||
<el-select v-model="form.embryoSource" placeholder="请选择" style="width:100%">
|
||||
<el-option label="自繁" value="自繁" />
|
||||
<el-option label="购入" value="购入" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="冲胚人" prop="flushOperator">
|
||||
<el-input v-model="form.flushOperator" placeholder="请输入冲胚人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="捡胚人" prop="collectOperator">
|
||||
<el-input v-model="form.collectOperator" placeholder="请输入捡胚人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" :rows="1" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- =====================================================================
|
||||
从配种记录选择供体母羊 Dialog
|
||||
展示:配种类型 = 供体母羊配种(breedType=1) 的记录
|
||||
显示:配种日期 / 供体母羊耳号 / 供体公羊耳号
|
||||
===================================================================== -->
|
||||
<el-dialog title="选择供体母羊(从配种记录)" v-model="breedPickerOpen" width="700px" append-to-body>
|
||||
<!-- 搜索 -->
|
||||
<el-row :gutter="10" style="margin-bottom:10px;">
|
||||
<el-col :span="10">
|
||||
<el-input v-model="breedPickerQuery.eweManageTags" placeholder="母羊耳号搜索" clearable @keyup.enter="loadBreedRecords" />
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-button type="primary" @click="loadBreedRecords">搜索</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table
|
||||
v-loading="breedPickerLoading"
|
||||
:data="breedPickerList"
|
||||
highlight-current-row
|
||||
@current-change="onBreedPickerSelect"
|
||||
size="small"
|
||||
max-height="360">
|
||||
<el-table-column label="配种日期" align="center" prop="createTime" width="110">
|
||||
<template #default="scope">{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="供体母羊耳号" align="center" prop="eweManageTags" />
|
||||
<el-table-column label="母羊品种" align="center" prop="eweVariety" />
|
||||
<el-table-column label="供体公羊耳号" align="center" prop="donorRamNo" />
|
||||
<el-table-column label="公羊品种" align="center" prop="donorRamVariety" />
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="breedPickerTotal > 0"
|
||||
:total="breedPickerTotal"
|
||||
v-model:page="breedPickerQuery.pageNum"
|
||||
v-model:limit="breedPickerQuery.pageSize"
|
||||
@pagination="loadBreedRecords"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button type="primary" :disabled="!selectedBreedRow" @click="confirmBreedPicker">确认选择</el-button>
|
||||
<el-button @click="breedPickerOpen = false">取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Flush">
|
||||
import { listFlush, getFlush, delFlush, addFlush, updateFlush,
|
||||
getDonorInfo, getDonorFemaleList, getDonorMaleList, getSheepInfo,
|
||||
calculateEmbryoVariety } from "@/api/embryo/flush"
|
||||
// 注意:listBreedRecord 来自配种记录 API,需要在该 API 文件中导出此函数
|
||||
// 参考路径: @/api/produce/breed/breedRecord
|
||||
// 若路径不同,请自行调整
|
||||
import { listBreeding_records } from "@/api/Breeding_records/Breeding_records"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
// ============================
|
||||
// 列表页状态
|
||||
// ============================
|
||||
const flushList = ref([])
|
||||
const open = ref(false)
|
||||
const loading = ref(true)
|
||||
const showSearch = ref(true)
|
||||
const ids = ref([])
|
||||
const single = ref(true)
|
||||
const multiple = ref(true)
|
||||
const total = ref(0)
|
||||
const title = ref("")
|
||||
const dateRange = ref([])
|
||||
const donorMaleOptions = ref([])
|
||||
const matingDateCache = ref(null)
|
||||
|
||||
// ============================
|
||||
// 表单 & 规则
|
||||
// ============================
|
||||
const data = reactive({
|
||||
form: {
|
||||
id: null,
|
||||
flushTime: null,
|
||||
donorFemaleNo: null,
|
||||
donorFemaleVariety: null,
|
||||
donorMaleNo: null,
|
||||
donorMaleVariety: null,
|
||||
embryoVariety: null,
|
||||
embryoAge: null,
|
||||
gradeA: 0, gradeB: 0, gradeC: 0, gradeD: 0,
|
||||
unfertilized: 0, degenerated: 0,
|
||||
totalEmbryo: 0, validEmbryo: 0,
|
||||
transferred: 0, recipientCnt: 0,
|
||||
embryoType: null,
|
||||
embryoSource: '自繁',
|
||||
flushOperator: null,
|
||||
collectOperator: null,
|
||||
ranchId: null, ranchName: null,
|
||||
remark: null,
|
||||
embryoDetails: [] // ← 胚胎明细列表
|
||||
},
|
||||
queryParams: {
|
||||
pageNum: 1, pageSize: 10,
|
||||
donorFemaleNo: null, donorMaleNo: null
|
||||
},
|
||||
rules: {
|
||||
flushTime: [{ required: true, message: "冲胚时间不能为空", trigger: "blur" }],
|
||||
donorFemaleNo: [{ required: true, message: "供体母号不能为空", trigger: "change" }],
|
||||
embryoType: [{ required: true, message: "胚胎类型不能为空", trigger: "change" }],
|
||||
embryoSource: [{ required: true, message: "胚胎来源不能为空", trigger: "change" }],
|
||||
flushOperator: [{ required: true, message: "冲胚人不能为空", trigger: "blur" }],
|
||||
collectOperator: [{ required: true, message: "捡胚人不能为空", trigger: "blur" }]
|
||||
}
|
||||
})
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
|
||||
// ============================
|
||||
// 配种记录选择弹窗状态
|
||||
// ============================
|
||||
const breedPickerOpen = ref(false)
|
||||
const breedPickerLoading = ref(false)
|
||||
const breedPickerList = ref([])
|
||||
const breedPickerTotal = ref(0)
|
||||
const selectedBreedRow = ref(null)
|
||||
const breedPickerQuery = reactive({
|
||||
pageNum: 1, pageSize: 10,
|
||||
breedType: 1, // 固定查询"供体母羊配种"
|
||||
eweManageTags: null
|
||||
})
|
||||
|
||||
// ============================
|
||||
// 计算属性:有效胚数量(A+B+C+16细胞)
|
||||
// ============================
|
||||
const computedValidEmbryo = computed(() => {
|
||||
return form.value.embryoDetails.filter(d =>
|
||||
['A', 'B', 'C', '16细胞'].includes(d.embryoGrade)
|
||||
).length
|
||||
})
|
||||
|
||||
// ============================
|
||||
// 列表操作
|
||||
// ============================
|
||||
function getList() {
|
||||
loading.value = true
|
||||
listFlush(proxy.addDateRange(queryParams.value, dateRange.value, 'FlushTime')).then(res => {
|
||||
flushList.value = res.rows
|
||||
total.value = res.total
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleQuery() { queryParams.value.pageNum = 1; getList() }
|
||||
function resetQuery() { dateRange.value = []; proxy.resetForm("queryRef"); handleQuery() }
|
||||
function handleSelectionChange(sel) {
|
||||
ids.value = sel.map(i => i.id)
|
||||
single.value = sel.length !== 1
|
||||
multiple.value = !sel.length
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 表单通用
|
||||
// ============================
|
||||
function cancel() { open.value = false; reset() }
|
||||
|
||||
function reset() {
|
||||
form.value = {
|
||||
id: null,
|
||||
flushTime: proxy.parseTime(new Date(), '{y}-{m}-{d}'),
|
||||
donorFemaleNo: null, donorFemaleVariety: null,
|
||||
donorMaleNo: null, donorMaleVariety: null,
|
||||
embryoVariety: null, embryoAge: null,
|
||||
gradeA: 0, gradeB: 0, gradeC: 0, gradeD: 0,
|
||||
unfertilized: 0, degenerated: 0,
|
||||
totalEmbryo: 0, validEmbryo: 0,
|
||||
transferred: 0, recipientCnt: 0,
|
||||
embryoType: null, embryoSource: '自繁',
|
||||
flushOperator: null, collectOperator: null,
|
||||
ranchId: null, ranchName: null,
|
||||
remark: null,
|
||||
embryoDetails: []
|
||||
}
|
||||
matingDateCache.value = null
|
||||
proxy.resetForm("flushRef")
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 新增 / 修改
|
||||
// ============================
|
||||
function handleAdd() {
|
||||
reset()
|
||||
loadDonorMaleList()
|
||||
open.value = true
|
||||
title.value = "添加冲胚记录"
|
||||
}
|
||||
|
||||
function handleUpdate(row) {
|
||||
reset()
|
||||
loadDonorMaleList()
|
||||
const _id = row.id || ids.value
|
||||
getFlush(_id).then(res => {
|
||||
form.value = { ...res.data, embryoDetails: res.data.embryoDetails || [] }
|
||||
open.value = true
|
||||
title.value = "修改冲胚记录"
|
||||
})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 胚胎明细行操作
|
||||
// ============================
|
||||
|
||||
/** 添加胚胎行 */
|
||||
function addEmbryo(grade) {
|
||||
const isWaste = ['未受精', '退化'].includes(grade)
|
||||
form.value.embryoDetails.push({
|
||||
embryoGrade: grade,
|
||||
destination: isWaste ? '遗弃' : '移植',
|
||||
storageMethod: isWaste ? '' : '胚胎保存液',
|
||||
embryoVariety: form.value.embryoVariety || null
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除胚胎行 */
|
||||
function removeEmbryo(index) {
|
||||
form.value.embryoDetails.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 切换等级时同步默认去向 */
|
||||
function onGradeChange(row) {
|
||||
const isWaste = ['未受精', '退化'].includes(row.embryoGrade)
|
||||
row.destination = isWaste ? '遗弃' : '移植'
|
||||
row.storageMethod = isWaste ? '' : (row.storageMethod || '胚胎保存液')
|
||||
}
|
||||
|
||||
/** 行颜色 */
|
||||
function embryoRowClass({ row }) {
|
||||
if (['未受精', '退化'].includes(row.embryoGrade)) return 'row-waste'
|
||||
if (row.destination === '冷冻保存') return 'row-frozen'
|
||||
return ''
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 供体母号相关
|
||||
// ============================
|
||||
|
||||
/** 手动输入耳号后触发 */
|
||||
function handleDonorFemaleInputChange(val) {
|
||||
if (!val) {
|
||||
form.value.donorFemaleVariety = null
|
||||
form.value.donorMaleNo = null
|
||||
form.value.donorMaleVariety = null
|
||||
form.value.embryoVariety = null
|
||||
form.value.ranchId = null
|
||||
form.value.ranchName = null
|
||||
matingDateCache.value = null
|
||||
return
|
||||
}
|
||||
getDonorInfo(val).then(res => {
|
||||
const info = res.data || {}
|
||||
form.value.donorFemaleVariety = info.donorFemaleVariety || null
|
||||
form.value.donorMaleNo = info.donorMaleNo || form.value.donorMaleNo
|
||||
form.value.donorMaleVariety = info.donorMaleVariety || null
|
||||
form.value.embryoVariety = info.embryoVariety || null
|
||||
form.value.ranchId = info.ranchId || null
|
||||
form.value.ranchName = info.ranchName || null
|
||||
matingDateCache.value = info.matingDate || null
|
||||
calculateEmbryoAge()
|
||||
updateEmbryoVariety()
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 从配种记录选择弹窗 */
|
||||
function openBreedRecordPicker() {
|
||||
breedPickerQuery.pageNum = 1
|
||||
breedPickerQuery.eweManageTags = null
|
||||
selectedBreedRow.value = null
|
||||
breedPickerList.value = []
|
||||
breedPickerOpen.value = true
|
||||
loadBreedRecords()
|
||||
}
|
||||
|
||||
function loadBreedRecords() {
|
||||
breedPickerLoading.value = true
|
||||
listBreedRecord({ ...breedPickerQuery }).then(res => {
|
||||
breedPickerList.value = res.rows || []
|
||||
breedPickerTotal.value = res.total || 0
|
||||
breedPickerLoading.value = false
|
||||
}).catch(() => { breedPickerLoading.value = false })
|
||||
}
|
||||
|
||||
function onBreedPickerSelect(row) {
|
||||
selectedBreedRow.value = row
|
||||
}
|
||||
|
||||
function confirmBreedPicker() {
|
||||
if (!selectedBreedRow.value) return
|
||||
const row = selectedBreedRow.value
|
||||
form.value.donorFemaleNo = row.eweManageTags
|
||||
form.value.donorFemaleVariety = row.eweVariety || null
|
||||
form.value.donorMaleNo = row.donorRamNo || form.value.donorMaleNo
|
||||
form.value.donorMaleVariety = row.donorRamVariety || null
|
||||
// 配种日期 → 计算胎龄
|
||||
matingDateCache.value = row.createTime || null
|
||||
calculateEmbryoAge()
|
||||
updateEmbryoVariety()
|
||||
breedPickerOpen.value = false
|
||||
|
||||
// 同步查一次牧场等信息
|
||||
getDonorInfo(row.eweManageTags).then(res => {
|
||||
const info = res.data || {}
|
||||
form.value.ranchId = info.ranchId || null
|
||||
form.value.ranchName = info.ranchName || null
|
||||
if (!form.value.embryoVariety && info.embryoVariety) {
|
||||
form.value.embryoVariety = info.embryoVariety
|
||||
}
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 供体父号
|
||||
// ============================
|
||||
function handleDonorMaleChange(val) {
|
||||
if (!val) { form.value.donorMaleVariety = null; updateEmbryoVariety(); return }
|
||||
const found = donorMaleOptions.value.find(i => i.manageTag === val)
|
||||
if (found) {
|
||||
form.value.donorMaleVariety = found.variety
|
||||
} else {
|
||||
getSheepInfo(val).then(res => {
|
||||
if (res.data) form.value.donorMaleVariety = res.data.variety
|
||||
})
|
||||
}
|
||||
updateEmbryoVariety()
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 胎龄 & 胚胎品种
|
||||
// ============================
|
||||
function handleFlushTimeChange() { calculateEmbryoAge() }
|
||||
|
||||
function calculateEmbryoAge() {
|
||||
if (matingDateCache.value && form.value.flushTime) {
|
||||
const diff = new Date(form.value.flushTime) - new Date(matingDateCache.value)
|
||||
const days = Math.floor(diff / 86400000)
|
||||
form.value.embryoAge = days > 0 ? days : 0
|
||||
} else {
|
||||
form.value.embryoAge = null
|
||||
}
|
||||
}
|
||||
|
||||
function updateEmbryoVariety() {
|
||||
const m = form.value.donorMaleVariety
|
||||
const f = form.value.donorFemaleVariety
|
||||
if (m && f) {
|
||||
calculateEmbryoVariety(m, f).then(res => {
|
||||
form.value.embryoVariety = res.data
|
||||
// 同步更新明细行的胚胎品种
|
||||
form.value.embryoDetails.forEach(d => { d.embryoVariety = res.data })
|
||||
})
|
||||
} else {
|
||||
form.value.embryoVariety = null
|
||||
}
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 下拉列表加载
|
||||
// ============================
|
||||
function loadDonorMaleList() {
|
||||
getDonorMaleList().then(res => { donorMaleOptions.value = res.data || [] }).catch(() => {})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 提交
|
||||
// ============================
|
||||
function submitForm() {
|
||||
proxy.$refs["flushRef"].validate(valid => {
|
||||
if (!valid) return
|
||||
if (form.value.embryoDetails.length === 0) {
|
||||
proxy.$modal.msgWarning("请至少添加一条胚胎明细")
|
||||
return
|
||||
}
|
||||
// 提交前同步明细中的胚胎品种
|
||||
form.value.embryoDetails.forEach(d => {
|
||||
if (!d.embryoVariety) d.embryoVariety = form.value.embryoVariety
|
||||
})
|
||||
|
||||
const api = form.value.id != null ? updateFlush : addFlush
|
||||
api(form.value).then(() => {
|
||||
proxy.$modal.msgSuccess(form.value.id != null ? "修改成功" : "新增成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 删除 & 导出
|
||||
// ============================
|
||||
function handleDelete(row) {
|
||||
const _ids = row.id || ids.value
|
||||
proxy.$modal.confirm('是否确认删除所选的冲胚记录?').then(() => delFlush(_ids)).then(() => {
|
||||
getList()
|
||||
proxy.$modal.msgSuccess("删除成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
proxy.download('embryo/flush/export', { ...queryParams.value }, `冲胚记录_${Date.now()}.xlsx`)
|
||||
}
|
||||
|
||||
// 初始化
|
||||
getList()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 废弃/退化行浅红色背景 */
|
||||
:deep(.row-waste) { background-color: #fff0f0; }
|
||||
/* 冷冻保存行浅蓝色背景 */
|
||||
:deep(.row-frozen) { background-color: #f0f7ff; }
|
||||
</style>
|
||||
@@ -3,20 +3,24 @@
|
||||
<!-- 查询+导出区域 -->
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" label-width="68px">
|
||||
<el-form-item label="管理耳号" prop="bsManageTags">
|
||||
<el-select
|
||||
v-model="queryParams.bsManageTags"
|
||||
placeholder="请选择管理耳号"
|
||||
clearable
|
||||
@change="handleQuery"
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tagOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="queryParams.bsManageTags"
|
||||
placeholder="请输入耳号关键词"
|
||||
clearable
|
||||
filterable
|
||||
remote
|
||||
:remote-method="remoteSearchTag"
|
||||
:loading="loadingTag"
|
||||
@change="handleQuery"
|
||||
style="width: 220px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tagOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
|
||||
@@ -96,10 +100,16 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Pedigree">
|
||||
import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
|
||||
import { listPedigree, getPedigree } from "@/api/fileManagement/pedigree"
|
||||
import { ref, reactive, toRefs, getCurrentInstance, onMounted, watch } from 'vue' // 新增 onMounted, watch
|
||||
import { useRoute, useRouter } from 'vue-router' // 新增
|
||||
import request from '@/utils/request'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const route = useRoute() // 新增
|
||||
const router = useRouter() // 新增(可选,如需在节点点击时同步路由)
|
||||
|
||||
const loadingTag = ref(false) // 远程搜索加载状态
|
||||
|
||||
// 管理耳号下拉选项
|
||||
const tagOptions = ref([])
|
||||
@@ -107,6 +117,28 @@ const tagOptions = ref([])
|
||||
const pedigreeData = ref({})
|
||||
const loading = ref(false)
|
||||
|
||||
|
||||
/** 远程模糊搜索耳号 */
|
||||
function remoteSearchTag(query) {
|
||||
if (query) {
|
||||
loadingTag.value = true
|
||||
request({
|
||||
url: '/sheep_file/sheep_file/searchEarNumbers',
|
||||
method: 'get',
|
||||
params: { query: query }
|
||||
}).then(res => {
|
||||
loadingTag.value = false
|
||||
tagOptions.value = res.data || []
|
||||
}).catch(() => {
|
||||
loadingTag.value = false
|
||||
tagOptions.value = []
|
||||
})
|
||||
} else {
|
||||
// 输入框清空时,清空下拉选项
|
||||
tagOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 查询参数
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
@@ -116,6 +148,23 @@ const data = reactive({
|
||||
}
|
||||
})
|
||||
const { queryParams } = toRefs(data)
|
||||
// ========== 新增:路由参数初始化 ==========
|
||||
onMounted(() => {
|
||||
const tag = route.query.bsManageTags
|
||||
if (tag) {
|
||||
queryParams.value.bsManageTags = tag
|
||||
getList() // 自动加载系谱数据
|
||||
}
|
||||
})
|
||||
|
||||
// 监听路由参数变化(当从列表页再次跳转时触发)
|
||||
watch(() => route.query.bsManageTags, (newTag) => {
|
||||
if (newTag) {
|
||||
queryParams.value.bsManageTags = newTag
|
||||
getList()
|
||||
}
|
||||
})
|
||||
// =======================================
|
||||
|
||||
/** 性别转换:数字转文字 */
|
||||
function getGenderText(gender) {
|
||||
@@ -128,14 +177,14 @@ function getGenderText(gender) {
|
||||
}
|
||||
|
||||
/** 初始化耳号下拉 */
|
||||
function initTagOptions() {
|
||||
listPedigree({ pageSize: 9999 }).then(response => {
|
||||
tagOptions.value = response.rows.map(item => ({
|
||||
label: item.bsManageTags,
|
||||
value: item.bsManageTags
|
||||
}))
|
||||
})
|
||||
}
|
||||
// function initTagOptions() {
|
||||
// listPedigree({ pageSize: 9999 }).then(response => {
|
||||
// tagOptions.value = response.rows.map(item => ({
|
||||
// label: item.bsManageTags,
|
||||
// value: item.bsManageTags
|
||||
// }))
|
||||
// })
|
||||
// }
|
||||
|
||||
/** 根据耳号查询单只羊数据 */
|
||||
async function getSheepByTag(tag) {
|
||||
@@ -231,6 +280,7 @@ function resetQuery() {
|
||||
proxy.resetForm("queryRef")
|
||||
queryParams.value.bsManageTags = null
|
||||
pedigreeData.value = {}
|
||||
tagOptions.value = [] // 👈 新增:重置时清空搜索选项
|
||||
}
|
||||
function handleExport() {
|
||||
if (!queryParams.value.bsManageTags) {
|
||||
@@ -243,7 +293,7 @@ function handleExport() {
|
||||
}
|
||||
|
||||
// 初始化
|
||||
initTagOptions()
|
||||
// initTagOptions()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="胚胎编号" prop="code">
|
||||
<el-input v-model="queryParams.code" placeholder="请输入胚胎编号" clearable @keyup.enter="handleQuery"
|
||||
@@ -56,67 +57,71 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="embryoList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
|
||||
<el-table-column label="胚胎编号" align="center" prop="code" width="130px" fixed="fixed" />
|
||||
<el-table-column label="冻胚日期" align="center" prop="freezeDate" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.freezeDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="供体公羊耳号" align="center" prop="drId" width="130px" />
|
||||
<el-table-column label="供体公羊品种" align="center" prop="drBreed" width="130px" />
|
||||
<el-table-column label="供体母羊耳号" align="center" prop="deId" width="130px" />
|
||||
<el-table-column label="供体母羊品种" align="center" prop="deBreed" width="130px" />
|
||||
<el-table-column label="胚胎品种" align="center" prop="embBreed" />
|
||||
<el-table-column label="胚胎阶段等级" align="center" prop="grade" width="130px" />
|
||||
<el-table-column label="胚胎数量" align="center" prop="qty" width="130px" sortable />
|
||||
<el-table-column label="是否性控" align="center" width="80">
|
||||
<template #default="scope">
|
||||
{{ scope.row.sexCtl === 1 ? '是' : '否' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '正常' ? 'primary'
|
||||
: scope.row.status === '销售' ? 'success'
|
||||
: scope.row.status === '自用' ? 'warning'
|
||||
: 'danger'">
|
||||
{{ scope.row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="技术员" align="center" prop="tech" />
|
||||
<el-table-column label="液氮罐ID" align="center" prop="tankId" />
|
||||
<el-table-column label="提桶ID" align="center" prop="bucketId" />
|
||||
<el-table-column label="冷冻架ID" align="center" prop="rackId" />
|
||||
<el-table-column label="出库日期" align="center" prop="outDate" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.outDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="废弃原因" align="center" prop="discardTxt" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="160px">
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="embryoList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
|
||||
<el-table-column label="胚胎编号" align="center" prop="code" width="130px" fixed="fixed" />
|
||||
<el-table-column label="冻胚日期" align="center" prop="freezeDate" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.freezeDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="供体公羊耳号" align="center" prop="drId" width="130px" />
|
||||
<el-table-column label="供体公羊品种" align="center" prop="drBreed" width="130px" />
|
||||
<el-table-column label="供体母羊耳号" align="center" prop="deId" width="130px" />
|
||||
<el-table-column label="供体母羊品种" align="center" prop="deBreed" width="130px" />
|
||||
<el-table-column label="胚胎品种" align="center" prop="embBreed" />
|
||||
<el-table-column label="胚胎阶段等级" align="center" prop="grade" width="130px" />
|
||||
<el-table-column label="胚胎数量" align="center" prop="qty" width="130px" sortable />
|
||||
<el-table-column label="是否性控" align="center" width="80">
|
||||
<template #default="scope">
|
||||
{{ scope.row.sexCtl === 1 ? '是' : '否' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '正常' ? 'primary'
|
||||
: scope.row.status === '销售' ? 'success'
|
||||
: scope.row.status === '自用' ? 'warning'
|
||||
: 'danger'">
|
||||
{{ scope.row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="技术员" align="center" prop="tech" />
|
||||
<el-table-column label="液氮罐ID" align="center" prop="tankId" />
|
||||
<el-table-column label="提桶ID" align="center" prop="bucketId" />
|
||||
<el-table-column label="冷冻架ID" align="center" prop="rackId" />
|
||||
<el-table-column label="出库日期" align="center" prop="outDate" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.outDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="废弃原因" align="center" prop="discardTxt" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="160px">
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['frozen:embryo:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['frozen:embryo:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['frozen:embryo:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</div>
|
||||
<!-- 添加或修改冻胚库存对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="900px" append-to-body>
|
||||
<el-form ref="embryoRef" :model="form" :rules="rules" label-width="120px">
|
||||
@@ -471,9 +476,15 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('frozen/embryo/export', {
|
||||
...queryParams.value
|
||||
}, `embryo_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
|
||||
try {
|
||||
proxy.download('frozen/embryo/export',
|
||||
{ ...queryParams.value },
|
||||
`冻胚记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 失焦或点击“查询” */
|
||||
|
||||
@@ -99,7 +99,11 @@
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户名称" prop="custName">
|
||||
<el-input v-model="form.custName" placeholder="请输入客户名称" />
|
||||
<!-- <el-input v-model="form.custName" placeholder="请输入客户名称" /> -->
|
||||
<el-select v-model="form.custName" placeholder="请选择客户" filterable clearable style="width: 100%"
|
||||
@change="handleCustomerChange">
|
||||
<el-option v-for="item in userDict" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
@@ -239,14 +243,14 @@
|
||||
|
||||
<script setup name="Sale">
|
||||
import { listSale, getSale, delSale, addSale, updateSale } from "@/api/frozen/sale"
|
||||
import { reactive } from "vue"
|
||||
import { onMounted, reactive } from "vue"
|
||||
import { ref } from "vue"
|
||||
import { getSaleCodeDict } from "../../../api/frozen/sale"
|
||||
import { computed } from "vue"
|
||||
import { listCustomer } from "../../../api/sale/customer/customer"
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { frozen_sale_item_type } = proxy.useDict('frozen_sale_item_type')
|
||||
|
||||
const saleList = ref([])
|
||||
const ddSaleItemList = ref([])
|
||||
const open = ref(false)
|
||||
@@ -316,6 +320,26 @@
|
||||
})
|
||||
}
|
||||
|
||||
// =============== 用户字典数据 =================
|
||||
const userDict = ref([])
|
||||
|
||||
const userMap = computed(() => {
|
||||
return new Map(userDict.value.map(u => [u.id, u]))
|
||||
})
|
||||
|
||||
const handleCustomerChange = (val) => {
|
||||
const user = userMap.value.get(val)
|
||||
|
||||
if (user) {
|
||||
form.value.custPhone = user.phone || ''
|
||||
form.value.custAddr = (user.province + user.city + user.district + user.address) || ''
|
||||
} else {
|
||||
form.value.custPhone = ''
|
||||
form.value.custAddr = ''
|
||||
}
|
||||
}
|
||||
|
||||
// =============== End =================
|
||||
// 取消按钮
|
||||
function cancel() {
|
||||
open.value = false
|
||||
@@ -465,4 +489,10 @@
|
||||
}, `sale_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
getList()
|
||||
onMounted(() => {
|
||||
// 加载客户列表
|
||||
listCustomer({ pageNum: 1, pageSize: 1000 }).then(r => {
|
||||
userDict.value = r.rows
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="冻精号" prop="code">
|
||||
<el-input v-model="queryParams.code" placeholder="请输入冻精号/公羊耳号" clearable @keyup.enter="handleQuery"
|
||||
@@ -52,62 +53,67 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="spermList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
|
||||
<el-table-column label="冻精号" align="center" prop="code" width="130px" fixed="fixed" />
|
||||
<el-table-column label="冻精日期" align="center" prop="freezeDt" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.freezeDt, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="冻精品种" align="center" prop="breed" />
|
||||
<el-table-column label="生产批次" align="center" prop="batch" width="130px" />
|
||||
<el-table-column label="规格" align="center" prop="spec" />
|
||||
<el-table-column label="数量" align="center" prop="qty" sortable />
|
||||
<el-table-column label="是否性控" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.sexCtl === 1 ? '是' : '否' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="stat">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.stat === '正常' ? 'primary'
|
||||
: scope.row.stat === '销售' ? 'success'
|
||||
: scope.row.stat === '自用' ? 'warning'
|
||||
: 'danger'">
|
||||
{{ scope.row.stat }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="技术员" align="center" prop="tech" />
|
||||
<el-table-column label="液氮罐ID" align="center" prop="tankId" />
|
||||
<el-table-column label="提桶ID" align="center" prop="bucketId" />
|
||||
<el-table-column label="冷冻架ID" align="center" prop="rackId" />
|
||||
<el-table-column label="出库日期" align="center" prop="outDt" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.outDt, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="废弃原因" align="center" prop="discardTxt" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="160px">
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['sperm:sperm:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['frozen:sperm:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="spermList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="主键" align="center" prop="id" /> -->
|
||||
<el-table-column label="冻精号" align="center" prop="code" width="130px" fixed="fixed" />
|
||||
<el-table-column label="冻精日期" align="center" prop="freezeDt" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.freezeDt, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="冻精品种" align="center" prop="breed" />
|
||||
<el-table-column label="生产批次" align="center" prop="batch" width="130px" />
|
||||
<el-table-column label="规格" align="center" prop="spec" />
|
||||
<el-table-column label="数量" align="center" prop="qty" sortable />
|
||||
<el-table-column label="是否性控" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.sexCtl === 1 ? '是' : '否' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="stat">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.stat === '正常' ? 'primary'
|
||||
: scope.row.stat === '销售' ? 'success'
|
||||
: scope.row.stat === '自用' ? 'warning'
|
||||
: 'danger'">
|
||||
{{ scope.row.stat }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="技术员" align="center" prop="tech" />
|
||||
<el-table-column label="液氮罐ID" align="center" prop="tankId" />
|
||||
<el-table-column label="提桶ID" align="center" prop="bucketId" />
|
||||
<el-table-column label="冷冻架ID" align="center" prop="rackId" />
|
||||
<el-table-column label="出库日期" align="center" prop="outDt" width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.outDt, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="废弃原因" align="center" prop="discardTxt" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="160px">
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['sperm:sperm:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['frozen:sperm: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" />
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改冻精库存对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="700px" append-to-body>
|
||||
@@ -500,11 +506,16 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('sperm/sperm/export', {
|
||||
...queryParams.value
|
||||
}, `sperm_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
queryParams.value.ids = ids.value;
|
||||
|
||||
try {
|
||||
proxy.download('sperm/sperm/export', {
|
||||
...queryParams.value
|
||||
}, `冻精记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
// 废弃
|
||||
function handleDiscard() {
|
||||
if (!ids.value.length) return proxy.$modal.msgWarning('请选择记录')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<!-- <el-form-item label="创建时间" style="width: 308px">
|
||||
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
|
||||
@@ -122,67 +123,77 @@
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="body_measureList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" width="100" fixed />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" width="100" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" width="100" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="测量日期" align="center" prop="measureDate" width="120">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.measureDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="测量时羊只类别" align="center" prop="sheepTypeName" width="100" />
|
||||
<el-table-column label="性别" align="center" prop="gender" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ genderMap[scope.row.gender] || '未知' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="胎次" align="center" prop="parity" width="100" />
|
||||
<el-table-column label="出生体重(kg)" align="center" prop="birthWeight" width="150" sortable />
|
||||
<el-table-column label="断奶体重(kg)" align="center" prop="weaningWeight" width="150" sortable />
|
||||
<el-table-column label="当前体重(kg)" align="center" prop="currentWeight" width="150" sortable />
|
||||
<el-table-column label="体高" align="center" prop="height" width="100" sortable />
|
||||
<el-table-column label="胸围" align="center" prop="bust" width="100" sortable />
|
||||
<el-table-column label="体斜长" align="center" prop="bodyLength" width="150" sortable />
|
||||
<el-table-column label="管围" align="center" prop="pipeLength" width="100" sortable />
|
||||
<el-table-column label="胸深" align="center" prop="chestDepth" width="100" sortable />
|
||||
<el-table-column label="臀高" align="center" prop="hipHeight" width="100" sortable />
|
||||
<el-table-column label="尻宽" align="center" prop="rumpWidth" width="100" sortable />
|
||||
<el-table-column label="尻高" align="center" prop="rumpHeignt" width="100" sortable />
|
||||
<el-table-column label="腰角宽" align="center" prop="hipWidth" width="150" sortable />
|
||||
<el-table-column label="十字部高" align="center" prop="hipCrossHeight" width="150" sortable />
|
||||
<el-table-column label="繁育状态" align="center" prop="breedStatusName" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.breedStatusName || '未设置' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="泌乳天数" align="center" prop="lactationDay" width="150" sortable />
|
||||
<el-table-column label="怀孕天数" align="center" prop="gestationDay" width="150" sortable />
|
||||
<el-table-column label="配后天数" align="center" prop="postMatingDay" width="150" sortable />
|
||||
<el-table-column label="备注" align="center" prop="comment" width="100" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" width="100" />
|
||||
|
||||
<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} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" min-width="130">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="body_measureList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" width="100" fixed />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" width="100" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" width="100" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="测量日期" align="center" prop="measureDate" width="120">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.measureDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="测量时羊只类别" align="center" prop="sheepTypeName" width="100" />
|
||||
<el-table-column label="性别" align="center" prop="gender" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ genderMap[scope.row.gender] || '未知' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="月龄" align="center" prop="monthAge" width="80" sortable />
|
||||
<el-table-column label="胎次" align="center" prop="parity" width="100" />
|
||||
<el-table-column label="出生体重(kg)" align="center" prop="birthWeight" width="150" sortable />
|
||||
<el-table-column label="断奶体重(kg)" align="center" prop="weaningWeight" width="150" sortable />
|
||||
<el-table-column label="当前体重(kg)" align="center" prop="currentWeight" width="150" sortable />
|
||||
<el-table-column label="体高" align="center" prop="height" width="100" sortable />
|
||||
<el-table-column label="胸围" align="center" prop="bust" width="100" sortable />
|
||||
<el-table-column label="体斜长" align="center" prop="bodyLength" width="150" sortable />
|
||||
<el-table-column label="管围" align="center" prop="pipeLength" width="100" sortable />
|
||||
<el-table-column label="胸深" align="center" prop="chestDepth" width="100" sortable />
|
||||
<el-table-column label="臀高" align="center" prop="hipHeight" width="100" sortable />
|
||||
<el-table-column label="尻宽" align="center" prop="rumpWidth" width="100" sortable />
|
||||
<el-table-column label="尻高" align="center" prop="rumpHeignt" width="100" sortable />
|
||||
<el-table-column label="腰角宽" align="center" prop="hipWidth" width="150" sortable />
|
||||
<el-table-column label="十字部高" align="center" prop="hipCrossHeight" width="150" sortable />
|
||||
<el-table-column label="乳房深度" align="center" prop="breastDepth" width="100" />
|
||||
<el-table-column label="乳头位置" align="center" prop="breastPosition" width="100" />
|
||||
<el-table-column label="乳头长度" align="center" prop="breastLength" width="100" />
|
||||
<el-table-column label="乳房附着" align="center" prop="breastAdbere" width="100" />
|
||||
<el-table-column label="乳房间隔度" align="center" prop="breastSpacing" width="100" />
|
||||
<el-table-column label="乳房评分" align="center" prop="breastScore" width="100" sortable />
|
||||
<el-table-column label="繁育状态" align="center" prop="breedStatusName" width="100">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.breedStatusName || '未设置' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="泌乳天数" align="center" prop="lactationDay" width="150" sortable />
|
||||
<el-table-column label="怀孕天数" align="center" prop="gestationDay" width="150" sortable />
|
||||
<el-table-column label="配后天数" align="center" prop="postMatingDay" width="150" sortable />
|
||||
<el-table-column label="体况评分" align="center" prop="bodyScore" width="100" sortable />
|
||||
<el-table-column label="技术员" align="center" prop="technician" width="100" />
|
||||
<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} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" width="180" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" min-width="130">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['body_measure:body_measure:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['body_measure:body_measure:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['body_measure:body_measure:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改体尺测量对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="700px" append-to-body>
|
||||
@@ -253,8 +264,8 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注" prop="comment" v-if="!isAdd">
|
||||
<el-input v-model="form.comment" placeholder="请输入备注" :disabled="!isAdd" clearable type="textarea" rows="3" />
|
||||
<el-form-item label="备注" prop="comment">
|
||||
<el-input v-model="form.comment" placeholder="请输入备注" clearable type="textarea" rows="3" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -423,16 +434,13 @@ function onManageTagsBlur() {
|
||||
getSheepByManageTags(tag).then(res => {
|
||||
if (res.code === 200 && res.data) {
|
||||
form.value.sheepId = res.data.id;
|
||||
form.value.comment = res.data.comment || "";
|
||||
} else {
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = null;
|
||||
proxy.$modal.msgWarning("未找到该管理耳号对应的羊只");
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error("耳号验证失败:", err);
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = null;
|
||||
proxy.$modal.msgError("查询失败,请重试");
|
||||
});
|
||||
}
|
||||
@@ -565,11 +573,13 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('body_measure/body_measure/export', {
|
||||
...queryParams.value
|
||||
}, `body_measure_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('body_measure/body_measure/export', { ...queryParams.value }, `体尺测量记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
const sheepfoldOptions = ref([])
|
||||
function getSheepfoldOptions() {
|
||||
@@ -595,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())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="事件日期" style="width: 308px">
|
||||
<el-date-picker v-model="daterangeDatetime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
|
||||
@@ -40,7 +41,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="品种" prop="varietyId">
|
||||
<!-- <el-form-item label="品种" prop="varietyId">
|
||||
<el-select v-model="queryParams.varietyId" placeholder="请选择品种" clearable style="min-width:150px">
|
||||
<el-option v-for="item in varietyOptions" :key="item.id" :label="item.variety" :value="item.id" />
|
||||
</el-select>
|
||||
@@ -49,6 +50,15 @@
|
||||
<el-select v-model="queryParams.sheepfold" placeholder="请选择羊舍" style="min-width:150px" clearable>
|
||||
<el-option v-for="item in sheepfoldOptions" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="体况评分" prop="score">
|
||||
<el-input-number v-model="queryParams.score" :min="0" :max="5" :step="0.1" :precision="1" placeholder="请输入评分"
|
||||
style="width: 150px" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="max-width: 160px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
@@ -82,39 +92,44 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="body_scoreList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100px" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" />
|
||||
<el-table-column label="事件日期" align="center" prop="datetime" min-width="120px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="体况评分" align="center" prop="score" min-width="100px" sortable />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" min-width="100px" />
|
||||
<el-table-column label="备注" align="center" prop="comment" min-width="130px" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="150px" fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="body_scoreList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100px" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" />
|
||||
<el-table-column label="事件日期" align="center" prop="datetime" min-width="120px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.datetime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="体况评分" align="center" prop="score" min-width="100px" sortable />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" min-width="100px" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="130px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" min-width="130px" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="150px"
|
||||
fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['body_score:body_score:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['body_score:body_score:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['body_score:body_score:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
<!-- 添加或修改体况评分对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="body_scoreRef" :model="form" :rules="rules" label-width="80px">
|
||||
@@ -122,24 +137,39 @@
|
||||
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" :disabled="!isAdd"
|
||||
clearable />
|
||||
</el-form-item>
|
||||
<!-- 新增弹窗已选耳号展示区 -->
|
||||
<div v-if="batchTags.length" class="selected-ear-numbers">
|
||||
<el-tag v-for="(tag, idx) in batchTags" :key="tag" closable @close="removeBatchTag(idx)" style="margin:4px"
|
||||
type="success">
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
|
||||
<el-button type="primary" link @click="clearBatchTags">
|
||||
一键清空 ({{ batchTags.length }})
|
||||
</el-button>
|
||||
</div>
|
||||
<el-form-item label="事件日期" prop="datetime">
|
||||
<el-date-picker clearable v-model="form.datetime" type="date" value-format="YYYY-MM-DD" placeholder="请选择事件日期"
|
||||
:disabled="!isAdd">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="体况评分" prop="score">
|
||||
<el-input v-model="form.score" placeholder="请输入体况评分" :disabled="!isAdd" />
|
||||
<el-input-number v-model="form.score" :min="1" :max="5" :step="0.1" :precision="1" :disabled="!isAdd"
|
||||
controls-position="right" style="width: 150px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="羊舍" v-if="!isAdd">
|
||||
<el-select v-model="form.sheepfold" disabled>
|
||||
<el-option v-for="item in sheepfoldList" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" v-if="!isAdd">
|
||||
<el-input v-model="form.comment" disabled type="textarea" rows="2" />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAdd" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" :disabled="!isAdd" clearable filterable
|
||||
style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.comment" placeholder="请填写备注" type="textarea" rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -156,8 +186,9 @@
|
||||
import { listBody_score, getBody_score, delBody_score, addBody_score, updateBody_score, searchEarNumbers } from "@/api/produce/bodyManage/body_score"
|
||||
import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/sheepfold_management'
|
||||
import { checkSheepByManageTags, getVarietyOptions } from "@/api/produce/other/fixHoof"
|
||||
import { getCurrentInstance, ref, reactive, toRefs } from 'vue'
|
||||
import { getCurrentInstance, ref, reactive, toRefs, computed } from 'vue'
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
import { nextTick } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
const { proxy } = getCurrentInstance()
|
||||
@@ -175,14 +206,11 @@ const daterangeDatetime = ref([])
|
||||
const daterangeCreateTime = ref([])
|
||||
const sheepfoldList = ref([])
|
||||
const isAdd = ref(false)
|
||||
const batchTags = ref([]) // 本次要新增的多条耳号
|
||||
const batchSheep = ref([]) // 对应的羊只对象
|
||||
const pasteText = ref('')
|
||||
const isExpanded = ref(false)
|
||||
const defaultShowCount = 2
|
||||
const displayedEarTags = computed(() => {
|
||||
const list = queryParams.value.manageTagsList
|
||||
if (isExpanded.value || list.length <= defaultShowCount) return list
|
||||
return list.slice(0, defaultShowCount)
|
||||
})
|
||||
const defaultShowCount = 2 // 默认展示条数
|
||||
const data = reactive({
|
||||
form: {
|
||||
id: null,
|
||||
@@ -221,8 +249,33 @@ const data = reactive({
|
||||
})
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
/* 计算:控制实际展示的耳号 */
|
||||
const displayedEarTags = computed(() => {
|
||||
const list = queryParams.value.manageTagsList
|
||||
if (isExpanded.value || list.length <= defaultShowCount) return list
|
||||
return list.slice(0, defaultShowCount)
|
||||
})
|
||||
const earOptions = ref([])
|
||||
const earLoading = ref(false)
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
/** 查询体况评分列表 */
|
||||
function getList() {
|
||||
loading.value = true
|
||||
@@ -235,6 +288,12 @@ function getList() {
|
||||
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0]
|
||||
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1]
|
||||
}
|
||||
if (queryParams.value.technician) {
|
||||
queryParams.value.params["technician"] = queryParams.value.technician
|
||||
}
|
||||
if (queryParams.value.score !== null && queryParams.value.score !== undefined && queryParams.value.score !== '') {
|
||||
queryParams.value.params["score"] = queryParams.value.score
|
||||
}
|
||||
listBody_score(queryParams.value).then(response => {
|
||||
body_scoreList.value = response.rows
|
||||
total.value = response.total
|
||||
@@ -243,33 +302,49 @@ function getList() {
|
||||
}
|
||||
|
||||
|
||||
function onManageTagsBlur() {
|
||||
const tag = form.value.manageTags?.trim();
|
||||
if (!tag) {
|
||||
form.value.sheepId = null;
|
||||
form.value.sheepfold = null;
|
||||
form.value.comment = null;
|
||||
return;
|
||||
async function onManageTagsBlur() {
|
||||
const raw = form.value.manageTags?.trim()
|
||||
if (!raw) return
|
||||
|
||||
//按分隔符拆
|
||||
const separators = /[\p{White_Space},,]+/u
|
||||
const tags = [...new Set(raw.split(separators).filter(v => v))]
|
||||
|
||||
if (tags.length === 1) {
|
||||
const sheep = await checkSheepByManageTags(tags[0]).then(r => r.data).catch(() => null)
|
||||
if (sheep) {
|
||||
batchTags.value = [tags[0]]
|
||||
batchSheep.value = [sheep]
|
||||
form.value.sheepId = sheep.id
|
||||
form.value.sheepfold = sheep.sheepfoldId
|
||||
} else {
|
||||
proxy.$modal.msgWarning('未找到该耳号对应羊只')
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.sheepId = null
|
||||
form.value.sheepfold = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
checkSheepByManageTags(tag).then(res => {
|
||||
if (res.code === 200 && res.data) {
|
||||
form.value.sheepId = res.data.id;
|
||||
form.value.sheepfold = res.data.sheepfoldId;
|
||||
form.value.comment = res.data.comment || '';
|
||||
//批量校验
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
for (const tag of tags) {
|
||||
const sheep = await checkSheepByManageTags(tag).then(r => r.data).catch(() => null)
|
||||
if (sheep) {
|
||||
batchTags.value.push(tag)
|
||||
batchSheep.value.push(sheep)
|
||||
} else {
|
||||
form.value.sheepId = null;
|
||||
form.value.sheepfold = null;
|
||||
form.value.comment = null;
|
||||
proxy.$modal.msgWarning("未找到该管理耳号对应的羊只");
|
||||
proxy.$modal.msgWarning(`耳号 ${tag} 未找到对应羊只,已跳过`)
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error("耳号验证失败:", err);
|
||||
form.value.sheepId = null;
|
||||
form.value.sheepfold = null;
|
||||
form.value.comment = null;
|
||||
proxy.$modal.msgError("查询失败,请重试");
|
||||
});
|
||||
}
|
||||
|
||||
if (!batchTags.value.length) return // 全部无效
|
||||
// 把合法耳号重新拼回输入框,用半角空格分隔
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
form.value.sheepId = batchSheep.value[0].id
|
||||
form.value.sheepfold = batchSheep.value[0].sheepfoldId
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
@@ -291,14 +366,17 @@ function reset() {
|
||||
form.value = {
|
||||
id: null,
|
||||
sheepId: null,
|
||||
manageTags: null,
|
||||
datetime: null,
|
||||
score: null,
|
||||
score: 0,
|
||||
sheepfold: null,
|
||||
comment: null,
|
||||
technician: null,
|
||||
createBy: null,
|
||||
createTime: null
|
||||
}
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
proxy.resetForm("body_scoreRef")
|
||||
}
|
||||
|
||||
@@ -314,6 +392,8 @@ function resetQuery() {
|
||||
daterangeCreateTime.value = []
|
||||
queryParams.value.varietyId = null
|
||||
queryParams.value.manageTagsList = []
|
||||
queryParams.value.score = null
|
||||
queryParams.value.technician = null
|
||||
queryParams.value.isDelete = null
|
||||
proxy.resetForm("queryRef")
|
||||
handleQuery()
|
||||
@@ -349,27 +429,69 @@ function handleUpdate(row) {
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
proxy.$refs["body_scoreRef"].validate(valid => {
|
||||
if (valid) {
|
||||
if (!form.value.id && !form.value.sheepId) {
|
||||
proxy.$modal.msgError("请输入有效的管理耳号");
|
||||
return;
|
||||
}
|
||||
if (form.value.id != null) {
|
||||
updateBody_score(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("修改成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
} else {
|
||||
addBody_score(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("新增成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
if (batchTags.value.length === 0) {
|
||||
proxy.$modal.msgError('请输入至少一个有效耳号')
|
||||
return
|
||||
}
|
||||
|
||||
// 表单校验(评分、日期、技术员)
|
||||
if (!form.value.score) {
|
||||
proxy.$modal.msgError('请输入体况评分')
|
||||
return
|
||||
}
|
||||
if (!form.value.datetime) {
|
||||
proxy.$modal.msgError('请选择事件日期')
|
||||
return
|
||||
}
|
||||
if (!form.value.technician) {
|
||||
proxy.$modal.msgError('请输入技术员')
|
||||
return
|
||||
}
|
||||
|
||||
// 批量新增
|
||||
Promise.all(
|
||||
batchTags.value.map((tag, idx) =>
|
||||
addBody_score({
|
||||
sheepId: batchSheep.value[idx].id,
|
||||
manageTags: tag,
|
||||
datetime: form.value.datetime,
|
||||
score: form.value.score,
|
||||
technician: form.value.technician,
|
||||
sheepfold: batchSheep.value[idx].sheepfoldId,
|
||||
comment: form.value.comment || ''
|
||||
})
|
||||
)
|
||||
).then(() => {
|
||||
proxy.$modal.msgSuccess(`成功新增 ${batchTags.value.length} 条体况评分`)
|
||||
open.value = false
|
||||
getList()
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
/* 删除单个批量耳号 */
|
||||
function removeBatchTag(idx) {
|
||||
batchTags.value.splice(idx, 1)
|
||||
batchSheep.value.splice(idx, 1)
|
||||
// 实时回写输入框,保持可视化
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
// 如果删完了,清空回显
|
||||
if (batchTags.value.length === 0) {
|
||||
form.value.sheepId = null
|
||||
form.value.sheepfold = null
|
||||
} else {
|
||||
// 回显第一只的信息
|
||||
form.value.sheepId = batchSheep.value[0].id
|
||||
form.value.sheepfold = batchSheep.value[0].sheepfoldId
|
||||
}
|
||||
}
|
||||
|
||||
/* 一键清空批量耳号 */
|
||||
function clearBatchTags() {
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.manageTags = ''
|
||||
form.value.sheepId = null
|
||||
form.value.sheepfold = null
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
@@ -385,11 +507,13 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('body_score/body_score/export', {
|
||||
...queryParams.value
|
||||
}, `body_score_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('body_score/body_score/export', { ...queryParams.value }, `体况评分记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载品种数据
|
||||
const varietyOptions = ref([])
|
||||
function loadVarietyOptions() {
|
||||
@@ -397,13 +521,30 @@ 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 = []
|
||||
}
|
||||
@@ -412,6 +553,7 @@ function removeEarNumber(tag) {
|
||||
const idx = queryParams.value.manageTagsList.indexOf(tag)
|
||||
if (idx > -1) queryParams.value.manageTagsList.splice(idx, 1)
|
||||
}
|
||||
|
||||
function handlePaste() {
|
||||
nextTick(() => handlePasteSubmit())
|
||||
}
|
||||
@@ -443,9 +585,11 @@ function toggleExpand() {
|
||||
function handleEarChange(val) {
|
||||
queryParams.value.manageTagsList = [...new Set(val)]
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadVarietyOptions()
|
||||
getSheepfoldOptions()
|
||||
fetchTechnicalList()
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<!-- <el-form-item label="创建时间" style="width: 308px">
|
||||
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
|
||||
@@ -44,7 +45,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="品种" prop="varietyId">
|
||||
<!-- <el-form-item label="品种" prop="varietyId">
|
||||
<el-select v-model="queryParams.varietyId" placeholder="请选择品种" clearable style="min-width:150px">
|
||||
<el-option v-for="item in varietyOptions" :key="item.id" :label="item.variety" :value="item.id" />
|
||||
</el-select>
|
||||
@@ -53,6 +54,16 @@
|
||||
<el-select v-model="queryParams.sheepfoldId" placeholder="请选择羊舍" style="min-width:150px" clearable>
|
||||
<el-option v-for="item in sheepfoldOptions" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="乳房评分" prop="score">
|
||||
<el-select v-model="queryParams.score" placeholder="请选择评分" clearable style="width: 120px">
|
||||
<el-option v-for="num in 9" :key="num" :label="num" :value="num" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="max-width: 160px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
@@ -85,44 +96,51 @@
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
<el-table v-loading="loading" :data="breast_ratingList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100px" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate" min-width="120px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" min-width="120px" />
|
||||
<el-table-column label="乳房深度" align="center" prop="depth" min-width="150px" sortable />
|
||||
<el-table-column label="乳房长度" align="center" prop="length" min-width="150px" sortable />
|
||||
<el-table-column label="乳房位置" align="center" prop="position" />
|
||||
<el-table-column label="乳房附着" align="center" prop="adbere" />
|
||||
<el-table-column label="乳房间隔度" align="center" prop="spacing" min-width="120px" />
|
||||
<el-table-column label="乳房评分" align="center" prop="score" min-width="150px" sortable />
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="150">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="120px" fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="breast_ratingList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100px" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate" min-width="120px">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="乳房深度" align="center" prop="depth" min-width="150px" sortable />
|
||||
<el-table-column label="乳房位置" align="center" prop="position" />
|
||||
<el-table-column label="乳房长度" align="center" prop="length" min-width="150px" sortable />
|
||||
<el-table-column label="乳房附着" align="center" prop="adbere" />
|
||||
<el-table-column label="乳房间隔度" align="center" prop="spacing" min-width="120px" />
|
||||
<el-table-column label="乳房评分" align="center" prop="score" min-width="150px" sortable />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" min-width="120px" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="150">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="120px"
|
||||
fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['breast_rating:breast_rating:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['breast_rating:breast_rating:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['breast_rating:breast_rating:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改乳房评分对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="550px" append-to-body>
|
||||
<el-form ref="breast_ratingRef" :model="form" :rules="rules" label-width="115px">
|
||||
@@ -130,34 +148,59 @@
|
||||
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" clearable
|
||||
:disabled="!isAdd" />
|
||||
</el-form-item>
|
||||
<!-- 新增弹窗已选耳号展示区 -->
|
||||
<div v-if="batchTags.length" class="selected-ear-numbers">
|
||||
<el-tag v-for="(tag, idx) in batchTags" :key="tag" closable @close="removeBatchTag(idx)" style="margin:4px"
|
||||
type="success">
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
<el-button type="primary" link @click="clearBatchTags">
|
||||
一键清空 ({{ batchTags.length }})
|
||||
</el-button>
|
||||
</div>
|
||||
<el-form-item label="事件日期" prop="eventDate">
|
||||
<el-date-picker clearable v-model="form.eventDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择事件日期"
|
||||
:disabled="!isAdd">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="乳房深度" prop="depth">
|
||||
<el-input v-model="form.depth" placeholder="请输入乳房深度" :disabled="!isAdd" />
|
||||
<el-select v-model="form.depth" placeholder="请选择乳房深度" :disabled="!isAdd" clearable style="width: 100%">
|
||||
<el-option v-for="num in 9" :key="num" :label="num" :value="num" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="乳房长度" prop="length">
|
||||
<el-input v-model="form.length" placeholder="请输入乳房长度" :disabled="!isAdd" />
|
||||
<el-select v-model="form.length" placeholder="请选择乳房长度" :disabled="!isAdd" clearable style="width: 100%">
|
||||
<el-option v-for="num in 9" :key="num" :label="num" :value="num" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="乳房位置" prop="position">
|
||||
<el-input v-model="form.position" placeholder="请输入乳房位置" :disabled="!isAdd" />
|
||||
<el-select v-model="form.position" placeholder="请选择乳房位置" :disabled="!isAdd" clearable style="width: 100%">
|
||||
<el-option v-for="num in 9" :key="num" :label="num" :value="num" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="乳房附着" prop="adbere">
|
||||
<el-input v-model="form.adbere" placeholder="请输入乳房附着" :disabled="!isAdd" />
|
||||
<el-select v-model="form.adbere" placeholder="请选择乳房附着" :disabled="!isAdd" clearable style="width: 100%">
|
||||
<el-option v-for="num in 9" :key="num" :label="num" :value="num" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="乳房间隔度" prop="spacing">
|
||||
<el-input v-model="form.spacing" placeholder="请输入乳房间隔度" :disabled="!isAdd" />
|
||||
<el-select v-model="form.spacing" placeholder="请选择乳房间隔度" :disabled="!isAdd" clearable style="width: 100%">
|
||||
<el-option v-for="num in 9" :key="num" :label="num" :value="num" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="乳房评分" prop="score">
|
||||
<el-input v-model="form.score" placeholder="请输入乳房评分" :disabled="!isAdd" />
|
||||
</el-form-item>
|
||||
<el-form-item label="羊只备注" v-if="!isAdd">
|
||||
<el-input v-model="form.comment" type="textarea" :rows="2" placeholder="羊只备注" :disabled="!isAdd" />
|
||||
<el-select v-model="form.score" placeholder="请选择乳房评分" :disabled="!isAdd" clearable style="width: 100%">
|
||||
<el-option v-for="num in 9" :key="num" :label="num" :value="num" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAdd" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" :disabled="!isAdd" clearable filterable
|
||||
style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.comment" type="textarea" :rows="2" placeholder="备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -177,6 +220,7 @@ import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/
|
||||
import { getCurrentInstance, reactive, ref } from "vue"
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
import { nextTick } from 'vue'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
import dayjs from 'dayjs'
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
@@ -195,11 +239,8 @@ const isAdd = ref(false)
|
||||
const pasteText = ref('')
|
||||
const isExpanded = ref(false)
|
||||
const defaultShowCount = 2
|
||||
const displayedEarTags = computed(() => {
|
||||
const list = queryParams.value.manageTagsList
|
||||
if (isExpanded.value || list.length <= defaultShowCount) return list
|
||||
return list.slice(0, defaultShowCount)
|
||||
})
|
||||
const batchTags = ref([]) // 本次要新增的多条耳号
|
||||
const batchSheep = ref([]) // 对应的羊只对象
|
||||
const data = reactive({
|
||||
form: {
|
||||
id: null,
|
||||
@@ -219,7 +260,8 @@ const data = reactive({
|
||||
pageSize: 20,
|
||||
manageTags: null,
|
||||
manageTagsList: [],
|
||||
isDelete: null
|
||||
isDelete: null,
|
||||
score: null,
|
||||
},
|
||||
rules: {
|
||||
manageTags: [
|
||||
@@ -229,17 +271,41 @@ const data = reactive({
|
||||
{ required: true, message: '请选择事件日期', trigger: 'blur' }
|
||||
],
|
||||
score: [
|
||||
{ required: true, message: '请输入乳房评分', trigger: 'blur' }
|
||||
{ required: true, message: '请输入乳房评分', trigger: 'change' }
|
||||
],
|
||||
technician: [
|
||||
{ required: true, message: '请输入技术员', trigger: 'blur' }
|
||||
{ required: true, message: '请输入技术员', trigger: 'change' }
|
||||
],
|
||||
}
|
||||
})
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
const earOptions = ref([])
|
||||
const earLoading = ref(false)
|
||||
const displayedEarTags = computed(() => {
|
||||
const list = queryParams.value.manageTagsList
|
||||
if (isExpanded.value || list.length <= defaultShowCount) return list
|
||||
return list.slice(0, defaultShowCount)
|
||||
})
|
||||
|
||||
const technicalOptions = ref([])
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
|
||||
/** 查询乳房评分列表 */
|
||||
function getList() {
|
||||
loading.value = true
|
||||
@@ -252,7 +318,12 @@ function getList() {
|
||||
queryParams.value.params["beginCreateTime"] = daterangeCreateTime.value[0]
|
||||
queryParams.value.params["endCreateTime"] = daterangeCreateTime.value[1]
|
||||
}
|
||||
|
||||
if (queryParams.value.technician) {
|
||||
queryParams.value.params["technician"] = queryParams.value.technician
|
||||
}
|
||||
if (queryParams.value.score !== null && queryParams.value.score !== undefined && queryParams.value.score !== '') {
|
||||
queryParams.value.params["score"] = queryParams.value.score
|
||||
}
|
||||
listBreast_rating(queryParams.value).then(response => {
|
||||
breast_ratingList.value = response.rows
|
||||
total.value = response.total
|
||||
@@ -261,28 +332,47 @@ function getList() {
|
||||
}
|
||||
|
||||
// 根据耳号查询羊只信息
|
||||
function onManageTagsBlur() {
|
||||
const tag = form.value.manageTags?.trim();
|
||||
if (!tag) {
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = null;
|
||||
return;
|
||||
async function onManageTagsBlur() {
|
||||
const raw = form.value.manageTags?.trim()
|
||||
if (!raw) return
|
||||
|
||||
// 1. 先按分隔符拆
|
||||
const separators = /[\p{White_Space},,]+/u
|
||||
const tags = [...new Set(raw.split(separators).filter(v => v))]
|
||||
|
||||
// 2. 只有一条 → 走老逻辑
|
||||
if (tags.length === 1) {
|
||||
const sheep = await checkSheepByManageTags(tags[0]).then(r => r.data).catch(() => null)
|
||||
if (sheep) {
|
||||
batchTags.value = [tags[0]]
|
||||
batchSheep.value = [sheep]
|
||||
form.value.sheepId = sheep.id
|
||||
} else {
|
||||
proxy.$modal.msgWarning('未找到该耳号对应羊只')
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.sheepId = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
checkSheepByManageTags(tag).then(res => {
|
||||
if (res.code === 200 && res.data) {
|
||||
form.value.sheepId = res.data.id;
|
||||
form.value.comment = res.data.comment || '';
|
||||
// 3. 多条 → 批量校验
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
for (const tag of tags) {
|
||||
const sheep = await checkSheepByManageTags(tag).then(r => r.data).catch(() => null)
|
||||
if (sheep) {
|
||||
batchTags.value.push(tag)
|
||||
batchSheep.value.push(sheep)
|
||||
} else {
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = null;
|
||||
proxy.$modal.msgWarning("未找到该耳号对应的羊只");
|
||||
proxy.$modal.msgWarning(`耳号 ${tag} 未找到对应羊只,已跳过`)
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error("耳号查询失败:", err);
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (!batchTags.value.length) return // 全部无效
|
||||
// 把合法耳号重新拼回输入框,用半角空格分隔
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
form.value.sheepId = batchSheep.value[0].id
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
@@ -290,7 +380,6 @@ function cancel() {
|
||||
open.value = false
|
||||
reset()
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
function reset() {
|
||||
form.value = {
|
||||
@@ -308,6 +397,8 @@ function reset() {
|
||||
createBy: null,
|
||||
createTime: null
|
||||
}
|
||||
batchTags.value = [] // 新增:清空批量耳号
|
||||
batchSheep.value = [] // 新增:清空羊只对象
|
||||
proxy.resetForm("breast_ratingRef")
|
||||
}
|
||||
|
||||
@@ -323,6 +414,8 @@ function resetQuery() {
|
||||
daterangeEventDate.value = []
|
||||
queryParams.value.manageTagsList = []
|
||||
queryParams.value.isDelete = null
|
||||
queryParams.value.score = null
|
||||
queryParams.value.technician = null
|
||||
proxy.resetForm("queryRef")
|
||||
handleQuery()
|
||||
}
|
||||
@@ -357,29 +450,61 @@ function handleUpdate(row) {
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
// 先校验表单(走 rules 规则)
|
||||
proxy.$refs["breast_ratingRef"].validate(valid => {
|
||||
if (valid) {
|
||||
if (!form.value.sheepId) {
|
||||
proxy.$modal.msgError("请输入有效的管理耳号");
|
||||
return;
|
||||
}
|
||||
if (form.value.id) {
|
||||
updateBreast_rating(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("修改成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
} else {
|
||||
addBreast_rating(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("新增成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
}
|
||||
if (!valid) return // 校验不通过,直接返回
|
||||
|
||||
if (batchTags.value.length === 0) {
|
||||
proxy.$modal.msgError('请输入至少一个有效耳号')
|
||||
return
|
||||
}
|
||||
|
||||
// 批量新增
|
||||
Promise.all(
|
||||
batchTags.value.map((tag, idx) =>
|
||||
addBreast_rating({
|
||||
sheepId: batchSheep.value[idx].id,
|
||||
manageTags: tag,
|
||||
eventDate: form.value.eventDate,
|
||||
depth: form.value.depth,
|
||||
length: form.value.length,
|
||||
position: form.value.position,
|
||||
adbere: form.value.adbere,
|
||||
spacing: form.value.spacing,
|
||||
score: form.value.score,
|
||||
technician: form.value.technician,
|
||||
comment: form.value.comment
|
||||
})
|
||||
)
|
||||
).then(() => {
|
||||
proxy.$modal.msgSuccess(`成功新增 ${batchTags.value.length} 条乳房评分`)
|
||||
open.value = false
|
||||
getList()
|
||||
}).catch(() => { })
|
||||
})
|
||||
}
|
||||
|
||||
/* 删除单个批量耳号 */
|
||||
function removeBatchTag(idx) {
|
||||
batchTags.value.splice(idx, 1)
|
||||
batchSheep.value.splice(idx, 1)
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
if (batchTags.value.length === 0) {
|
||||
form.value.sheepId = null
|
||||
form.value.comment = null
|
||||
} else {
|
||||
form.value.sheepId = batchSheep.value[0].id
|
||||
}
|
||||
}
|
||||
|
||||
/* 一键清空批量耳号 */
|
||||
function clearBatchTags() {
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.manageTags = ''
|
||||
form.value.sheepId = null
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const _ids = row.id || ids.value
|
||||
@@ -393,11 +518,13 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('breast_rating/breast_rating/export', {
|
||||
...queryParams.value
|
||||
}, `breast_rating_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('breast_rating/breast_rating/export', { ...queryParams.value }, `乳况评分记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
const sheepfoldOptions = ref([])
|
||||
function getSheepfoldOptions() {
|
||||
@@ -413,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 = []
|
||||
@@ -462,6 +604,7 @@ function handleEarChange(val) {
|
||||
onMounted(() => {
|
||||
loadVarietyOptions()
|
||||
getSheepfoldOptions()
|
||||
fetchTechnicalList()
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
v-hasPermi="['produce:add_sheep:import']">导入</el-button>
|
||||
<el-button type="warning" icon="Upload" @click="handleExportForm">下载模板</el-button>
|
||||
|
||||
|
||||
<!-- 新增/编辑表单 -->
|
||||
<el-form :model="form" ref="formRef" label-position="left" label-width="120px" style="margin-top:15px"
|
||||
:rules="rules">
|
||||
@@ -15,14 +14,6 @@
|
||||
<el-input v-model="form.earNumber" placeholder="请输入耳号" @blur="handleEarNumberBlur" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="入群日期" prop="joinDate">
|
||||
<el-date-picker v-model="form.joinDate" type="date" placeholder="选择入群日期" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="牧场" prop="ranchId">
|
||||
<el-select v-model="form.ranchId" placeholder="请选择牧场" clearable @change="handleRanchChange" required>
|
||||
@@ -30,6 +21,9 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="羊舍" prop="sheepfold">
|
||||
<el-select v-model="form.sheepfold" placeholder="请选择羊舍" clearable :disabled="!form.ranchId">
|
||||
@@ -37,45 +31,50 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="父号" prop="father">
|
||||
<el-input v-model="form.father" placeholder="请输入父号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="母号" prop="mother">
|
||||
<el-input v-model="form.mother" placeholder="请输入母号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="外祖父" prop="grandpa">
|
||||
<el-input v-model="form.grandpa" placeholder="请输入外祖父耳号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="外祖母" prop="grandma">
|
||||
<el-input v-model="form.grandma" placeholder="请输入外祖母耳号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="出生体重(kg)" prop="bornWeight">
|
||||
<el-input v-model="form.bornWeight" placeholder="请输入出生体重" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="断奶体重(kg)" prop="weaningWeight">
|
||||
<el-input v-model="form.weaningWeight" placeholder="请输入断奶体重" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker v-model="form.birthday" type="date" placeholder="选择出生日期" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="胎次" prop="parity">
|
||||
<el-input-number v-model="form.parity" :min="0" label="胎次" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
@@ -88,6 +87,14 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="胎次" prop="parity">
|
||||
<el-input-number v-model="form.parity" :min="0" label="胎次" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="品种" prop="varietyId">
|
||||
<el-select v-model="form.varietyId" placeholder="请选择品种" clearable>
|
||||
@@ -95,9 +102,6 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="羊只类别" prop="typeId">
|
||||
<el-select v-model="form.typeId" placeholder="请选择羊只类别" clearable>
|
||||
@@ -105,11 +109,21 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" />
|
||||
<el-form-item label="入群日期" prop="joinDate">
|
||||
<el-date-picker v-model="form.joinDate" type="date" placeholder="选择入群日期" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="10">
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" clearable filterable style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
@@ -130,7 +144,7 @@
|
||||
<el-dialog title="导入羊只信息" v-model="importOpen" width="400px" append-to-body>
|
||||
<el-upload ref="uploadRef" :limit="1" accept=".xlsx,.xls" :action="importUrl" :headers="headers"
|
||||
:auto-upload="false" :on-success="handleImportSuccess" :on-error="handleImportError" drag>
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
@@ -154,7 +168,7 @@ import { listRanch } from '@/api/produce/manage_sheep/trans_group'
|
||||
import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/sheepfold_management'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { UploadFilled } from '@element-plus/icons-vue'
|
||||
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const form = ref({
|
||||
@@ -172,12 +186,35 @@ const form = ref({
|
||||
joinDate: '',
|
||||
comment: '',
|
||||
technician: '',
|
||||
weaningWeight: ''
|
||||
weaningWeight: '',
|
||||
grandpa: '',
|
||||
grandma: '',
|
||||
})
|
||||
const formRef = ref(null)
|
||||
const sheepfoldOptions = ref([])
|
||||
const varietyOptions = ref([])
|
||||
const ranchOptions = ref([])
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
|
||||
const rules = {
|
||||
earNumber: [
|
||||
{ required: true, message: '请输入耳号', trigger: 'blur' },
|
||||
@@ -186,12 +223,10 @@ const rules = {
|
||||
ranchId: [{ required: true, message: '请选择牧场', trigger: 'change' }],
|
||||
sheepfold: [{ required: true, message: '请选择羊舍', trigger: 'change' }],
|
||||
bornWeight: [{ required: true, message: '请输入出生体重', trigger: 'change' }],
|
||||
weaningWeight: [{ required: true, message: '请输入断奶体重', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '请选择出生日期', trigger: 'change' }],
|
||||
gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
|
||||
varietyId: [{ required: true, message: '请选择品种', trigger: 'change' }],
|
||||
joinDate: [{ required: true, message: '请选择入群日期', trigger: 'change' }],
|
||||
technician: [{ required: true, message: '请输入技术员', trigger: 'change' }],
|
||||
}
|
||||
|
||||
// 校验耳号是否存在
|
||||
@@ -331,7 +366,9 @@ function resetForm() {
|
||||
typeId: null,
|
||||
joinDate: '',
|
||||
comment: '',
|
||||
technician: ''
|
||||
technician: '',
|
||||
grandpa: '',
|
||||
grandma: '',
|
||||
}
|
||||
}
|
||||
//下载模板
|
||||
@@ -380,6 +417,7 @@ onMounted(() => {
|
||||
loadSheepTypeList()
|
||||
loadRanchList()
|
||||
getVarietyOptions()
|
||||
fetchTechnicalList()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="事件日期" style="width: 308px">
|
||||
<el-date-picker v-model="daterangeEventDate" type="daterange" range-separator="-" start-placeholder="开始日期"
|
||||
@@ -64,8 +65,9 @@
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="queryParams.technician" placeholder="请输入技术员" clearable style="max-width: 160px"
|
||||
@keyup.enter="handleQuery" />
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="max-width: 160px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
@@ -99,38 +101,41 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="changeCommentList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="新备注" align="center" prop="newComment" />
|
||||
<el-table-column label="原备注" align="center" prop="oldComment" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</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)"
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="changeCommentList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="新备注" align="center" prop="newComment" />
|
||||
<el-table-column label="原备注" align="center" prop="oldComment" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['changeComment:changeComment:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['changeComment:changeComment:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['changeComment:changeComment:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
<!-- 添加或修改改备注对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="changeCommentRef" :model="form" :rules="rules" label-width="80px">
|
||||
@@ -152,14 +157,17 @@
|
||||
<el-input v-model="form.newComment" placeholder="请输入新备注" :disabled="!isAddMode" />
|
||||
</el-form-item>
|
||||
<el-form-item label="原备注" prop="oldComment">
|
||||
<el-input v-model="form.oldComment" placeholder="自动回显,多只羊只回显第一只" disabled />
|
||||
<el-input v-model="form.oldComment" placeholder="页面自动获取展示" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="事件日期" prop="eventDate">
|
||||
<el-date-picker v-model="form.eventDate" type="date" placeholder="请选择事件日期" value-format="YYYY-MM-DD"
|
||||
:disabled="!isAddMode" />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAddMode" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" :disabled="!isAddMode" clearable filterable
|
||||
style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -179,6 +187,7 @@ import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/
|
||||
import dayjs from 'dayjs'
|
||||
import { nextTick } from 'vue'
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const changeCommentList = ref([])
|
||||
@@ -198,6 +207,27 @@ const isExpanded = ref(false) // 折叠状态
|
||||
const defaultShowCount = 2 // 默认展示条数
|
||||
const batchTags = ref([]) // 本次要新增的多条耳号
|
||||
const batchSheep = ref([]) // 对应的羊只对象
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
|
||||
/* 计算:控制实际展示的耳号 */
|
||||
const displayedEarTags = computed(() => {
|
||||
const list = queryParams.value.manageTagsList
|
||||
@@ -410,11 +440,13 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('changeComment/changeComment/export', {
|
||||
...queryParams.value
|
||||
}, `changeComment_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('changeComment/changeComment/export', { ...queryParams.value }, `改备注记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
const sheepfoldOptions = ref([])
|
||||
function getSheepfoldOptions() {
|
||||
@@ -422,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
|
||||
}
|
||||
}
|
||||
|
||||
/* 清空所有耳号 */
|
||||
@@ -489,10 +535,9 @@ function clearBatchTags() {
|
||||
form.value.oldComment = ''
|
||||
}
|
||||
|
||||
/* 计算属性:实时显示已选数量(可选) */
|
||||
const batchCount = computed(() => batchTags.value.length)
|
||||
onMounted(() => {
|
||||
getSheepfoldOptions();
|
||||
fetchTechnicalList();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="事件日期" style="width: 300px">
|
||||
<el-date-picker v-model="daterangeEventDate" type="daterange" range-separator="-" start-placeholder="开始日期"
|
||||
@@ -59,8 +60,9 @@
|
||||
style="max-width: 160px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="queryParams.technician" placeholder="请输入技术员" clearable @keyup.enter="handleQuery"
|
||||
style="max-width: 160px;" />
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="max-width: 160px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="inGroup">
|
||||
<el-select v-model="queryParams.inGroup" placeholder="全部" clearable style="width:120px">
|
||||
@@ -100,45 +102,50 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="changeEarList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="耳号类型" align="center" prop="earType">
|
||||
<template #default="scope">
|
||||
{{ scope.row.earType === 0 ? '电子耳号' : '管理耳号' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="新耳号" align="center" prop="newTag" />
|
||||
<el-table-column label="旧耳号" align="center" prop="oldTag" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<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)"
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="changeEarList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="耳号类型" align="center" prop="earType">
|
||||
<template #default="scope">
|
||||
{{ scope.row.earType === 0 ? '电子耳号' : '管理耳号' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="新耳号" align="center" prop="newTag" />
|
||||
<el-table-column label="旧耳号" align="center" prop="oldTag" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['changeEar:changeEar:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['changeEar:changeEar:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['changeEar:changeEar:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改修改电子耳号记录对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="changeEarRef" :model="form" :rules="rules" label-width="80px">
|
||||
@@ -155,10 +162,13 @@
|
||||
<el-input v-model="form.newTag" placeholder="请输入新耳号/电子耳号" @blur="checkNewTagExists" :disabled="!isAddMode" />
|
||||
</el-form-item>
|
||||
<el-form-item label="旧耳号" prop="oldTag">
|
||||
<el-input v-model="form.oldTag" placeholder="请输入旧耳号/电子耳号" disabled />
|
||||
<el-input v-model="form.oldTag" placeholder="自动获取" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAddMode" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" :disabled="!isAddMode" clearable filterable
|
||||
style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="事件日期" prop="eventDate">
|
||||
<el-date-picker v-model="form.eventDate" type="date" placeholder="请选择事件日期" value-format="YYYY-MM-DD"
|
||||
@@ -184,8 +194,28 @@ import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/
|
||||
import dayjs from 'dayjs'
|
||||
import { nextTick } from 'vue'
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
const { proxy } = getCurrentInstance()
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
const changeEarList = ref([])
|
||||
const open = ref(false)
|
||||
const loading = ref(true)
|
||||
@@ -240,9 +270,6 @@ const data = reactive({
|
||||
],
|
||||
eventDate: [
|
||||
{ required: true, message: "请选择事件日期", trigger: "change" }
|
||||
],
|
||||
comment: [
|
||||
{ required: true, message: "请输入备注", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
})
|
||||
@@ -417,7 +444,6 @@ function fetchOldTag() {
|
||||
if (!earNumber || earType === null) {
|
||||
form.value.oldTag = '';
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = '';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -429,20 +455,16 @@ function fetchOldTag() {
|
||||
if (!sheep || !sheep.id) {
|
||||
form.value.oldTag = '';
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = '';
|
||||
proxy.$modal.warning("未找到对应的羊只");
|
||||
return;
|
||||
}
|
||||
|
||||
form.value.oldTag = oldTag;
|
||||
form.value.sheepId = sheep.id;
|
||||
|
||||
form.value.comment = sheep.comment || '';
|
||||
}).catch(error => {
|
||||
console.error("查询失败:", error);
|
||||
form.value.oldTag = '';
|
||||
form.value.sheepId = null;
|
||||
form.value.comment = '';
|
||||
proxy.$modal.error("查询耳号失败,请重试");
|
||||
});
|
||||
}
|
||||
@@ -460,9 +482,12 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('changeEar/changeEar/export', {
|
||||
...queryParams.value
|
||||
}, `changeEar_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('changeEar/changeEar/export', { ...queryParams.value }, `改耳号记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
@@ -472,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() {
|
||||
@@ -531,6 +573,7 @@ function removeEarNumber(tag) {
|
||||
onMounted(() => {
|
||||
getSheepfoldOptions();
|
||||
getList();
|
||||
fetchTechnicalList();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="事件日期" style="width: 308px">
|
||||
<el-date-picker v-model="daterangeEventDate" type="daterange" range-separator="-" start-placeholder="开始日期"
|
||||
@@ -67,8 +68,9 @@
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="queryParams.technician" placeholder="请输入技术员" clearable style="max-width: 160px"
|
||||
@keyup.enter="handleQuery" />
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="max-width: 160px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
@@ -102,39 +104,43 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="changeVarietyList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="品种" align="center" prop="varietyOld" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="新品种" align="center" prop="varietyNew" />
|
||||
<el-table-column label="旧品种" align="center" prop="varietyOld" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建日期" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<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)"
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="changeVarietyList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="品种" align="center" prop="varietyOld" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="新品种" align="center" prop="varietyNew" />
|
||||
<el-table-column label="旧品种" align="center" prop="varietyOld" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建日期" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['changeVariety:changeVariety:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['changeVariety:changeVariety:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['changeVariety:changeVariety:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改改品种记录对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
@@ -156,7 +162,13 @@
|
||||
</el-button>
|
||||
</div>
|
||||
<el-form-item label="原品种" prop="varietyOld">
|
||||
<el-input v-model="form.varietyOld" placeholder="请输入原品种" disabled />
|
||||
<span v-if="batchSheep.length === 0" class="placeholder-text">请输入耳号后自动获取</span>
|
||||
<div v-else class="variety-old-list">
|
||||
<el-tag v-for="(sheep, idx) in batchSheep" :key="sheep.id" type="warning" effect="plain" size="small"
|
||||
style="margin: 2px 4px 2px 0;">
|
||||
{{ sheep.varietyName || '未知品种' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="新品种" prop="varietyNew">
|
||||
<el-select v-model="form.varietyNew" placeholder="请选择新品种" clearable filterable :disabled="!isAdd">
|
||||
@@ -168,10 +180,13 @@
|
||||
:disabled="!isAdd" />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" :disabled="!isAdd" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" :disabled="!isAdd" clearable filterable
|
||||
style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="comment" v-if="!isAdd">
|
||||
<el-input v-model="form.comment" placeholder="请输入备注" :disabled="!isAdd" />
|
||||
<el-form-item label="备注" prop="comment">
|
||||
<el-input v-model="form.comment" placeholder="请填写备注" type="textarea" rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -191,8 +206,28 @@ import { listVariety } from '@/api/fileManagement/variety'
|
||||
import dayjs from 'dayjs'
|
||||
import { nextTick } from 'vue'
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
const { proxy } = getCurrentInstance()
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
const changeVarietyList = ref([])
|
||||
const open = ref(false)
|
||||
const loading = ref(true)
|
||||
@@ -384,7 +419,7 @@ function submitForm() {
|
||||
varietyNew: form.value.varietyNew,
|
||||
eventDate: form.value.eventDate,
|
||||
technician: form.value.technician,
|
||||
comment: sheep.comment || ""
|
||||
comment: form.value.comment || ''
|
||||
}
|
||||
return addChangeVariety(submitData)
|
||||
})
|
||||
@@ -413,11 +448,17 @@ function handleDelete(row) {
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download('changeVariety/changeVariety/export', {
|
||||
...queryParams.value
|
||||
}, `changeVariety_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
queryParams.value.ids = ids.value;
|
||||
|
||||
try {
|
||||
proxy.download('changeVariety/changeVariety/export',
|
||||
{ ...queryParams.value },
|
||||
`改品种记录_${Date.now()}.xlsx`
|
||||
);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
const sheepfoldOptions = ref([])
|
||||
@@ -426,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() {
|
||||
@@ -513,7 +571,6 @@ async function onManageTagsBlur() {
|
||||
if (!batchTags.value.length) { // 全部无效
|
||||
form.value.varietyOld = ""
|
||||
form.value.sheepId = null
|
||||
form.value.comment = ""
|
||||
return
|
||||
}
|
||||
|
||||
@@ -524,7 +581,6 @@ async function onManageTagsBlur() {
|
||||
const firstSheep = batchSheep.value[0]
|
||||
form.value.varietyOld = firstSheep.varietyName || ""
|
||||
form.value.sheepId = firstSheep.id
|
||||
form.value.comment = firstSheep.comment || ""
|
||||
}
|
||||
|
||||
// 删除单个批量耳号
|
||||
@@ -551,6 +607,7 @@ function clearBatchTags() {
|
||||
onMounted(() => {
|
||||
loadVarietyOptions();
|
||||
getSheepfoldOptions();
|
||||
fetchTechnicalList();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
@@ -566,4 +623,34 @@ onMounted(() => {
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.variety-old-list {
|
||||
min-height: 32px;
|
||||
/* 与el-input高度一致 */
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
padding: 4px 8px;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
display: block;
|
||||
min-height: 32px;
|
||||
line-height: 32px;
|
||||
padding: 0 8px;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
color: #c0c4cc;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="转群日期" style="width: 308px">
|
||||
<el-date-picker v-model="daterangeTransDate" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
|
||||
@@ -77,7 +78,8 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员">
|
||||
<el-select v-model="queryParams.technician" filterable allow-create clearable placeholder="请输入或选择技术员">
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="min-width:150px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
@@ -95,50 +97,55 @@
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd"
|
||||
v-hasPermi="['trans_group:trans_group:add']">新增</el-button>
|
||||
v-hasPermi="['produce:trans_group:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
|
||||
v-hasPermi="['trans_group:trans_group:remove']">删除</el-button>
|
||||
v-hasPermi="['produce:trans_group:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport"
|
||||
v-hasPermi="['trans_group:trans_group:export']">导出</el-button>
|
||||
v-hasPermi="['produce:trans_group:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="trans_groupList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventTypeText" />
|
||||
<el-table-column label="转群日期" align="center" prop="transDate" min-width="120" />
|
||||
<el-table-column label="转入羊舍" align="center" prop="foldToName" min-width="130" />
|
||||
<el-table-column label="转出羊舍" align="center" prop="foldFromName" min-width="130" />
|
||||
<!-- <el-table-column label="羊只类别" align="center" prop="sheepTypeName" /> -->
|
||||
<el-table-column label="转群原因" align="center" prop="reasonText" min-width="120" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="120">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" min-width="120" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="160" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['trans_group:trans_group:remove']">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="trans_groupList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventTypeText" />
|
||||
<el-table-column label="转群日期" align="center" prop="transDate" min-width="120" />
|
||||
<el-table-column label="转入羊舍" align="center" prop="foldToName" min-width="130" />
|
||||
<el-table-column label="转出羊舍" align="center" prop="foldFromName" min-width="130" />
|
||||
<!-- <el-table-column label="羊只类别" align="center" prop="sheepTypeName" /> -->
|
||||
<el-table-column label="转群原因" align="center" prop="reasonText" min-width="120" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="120">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" min-width="120" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="160" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['produce:trans_group:remove']">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改转群记录对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="700px" append-to-body>
|
||||
<el-form ref="trans_groupRef" :model="form" :rules="rules" label-width="80px">
|
||||
@@ -200,7 +207,12 @@
|
||||
style="width: 100%" required />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" clearable filterable style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="comment">
|
||||
<el-input v-model="form.comment" placeholder="请填写备注" type="textarea" rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -210,8 +222,6 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -224,10 +234,29 @@ import request from '@/utils/request'
|
||||
import dayjs from 'dayjs'
|
||||
import { nextTick } from 'vue'
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { trans_group_reason, trans_group_event_type } = proxy.useDict('trans_group_reason', 'status', 'trans_group_event_type');
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
const trans_groupList = ref([]);
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
@@ -268,6 +297,7 @@ const data = reactive({
|
||||
eventType: null,
|
||||
transDate: null,
|
||||
currentFoldAllEars: ref([]),
|
||||
comment: null,
|
||||
},
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
@@ -347,7 +377,9 @@ async function handleSheepFilter() {
|
||||
let isOnlyTypeOrCombined = false;
|
||||
|
||||
if (!ranchId) {
|
||||
form.value.manageTags = [];
|
||||
form.value.manageTags = '';
|
||||
batchTags.value = [];
|
||||
batchSheep.value = [];
|
||||
sheepOptions.value = [];
|
||||
proxy.$message.warning("请先选择牧场");
|
||||
return;
|
||||
@@ -360,25 +392,33 @@ async function handleSheepFilter() {
|
||||
} else if (foldFrom && sheepTypeId) {
|
||||
isOnlyTypeOrCombined = true;
|
||||
} else {
|
||||
form.value.manageTags = [];
|
||||
form.value.manageTags = '';
|
||||
batchTags.value = [];
|
||||
batchSheep.value = [];
|
||||
sheepOptions.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOnlySheepfold) {
|
||||
const list = await loadSheepBySheepfoldOnly(foldFrom, ranchId);
|
||||
if (list.length === 0) {
|
||||
const sheepList = await loadSheepBySheepfoldOnly(foldFrom, ranchId);
|
||||
if (sheepList.length === 0) {
|
||||
proxy.$message.info('当前转出羊舍暂无羊只');
|
||||
form.value.manageTags = [];
|
||||
form.value.manageTags = '';
|
||||
batchTags.value = [];
|
||||
batchSheep.value = [];
|
||||
return;
|
||||
}
|
||||
form.value.manageTags = [...list];
|
||||
await loadSheepInfo();
|
||||
// 关键修改:填充 batchTags 和 batchSheep,和手动输入保持一致
|
||||
batchTags.value = sheepList.map(s => s.manageTags);
|
||||
batchSheep.value = sheepList;
|
||||
form.value.manageTags = batchTags.value.join(' ');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOnlyTypeOrCombined) {
|
||||
form.value.manageTags = [];
|
||||
form.value.manageTags = '';
|
||||
batchTags.value = [];
|
||||
batchSheep.value = [];
|
||||
let loadedSheep = [];
|
||||
|
||||
if (foldFrom && sheepTypeId) {
|
||||
@@ -388,9 +428,10 @@ async function handleSheepFilter() {
|
||||
}
|
||||
|
||||
if (loadedSheep.length > 0) {
|
||||
const list = loadedSheep.map(s => s.manageTags);
|
||||
form.value.manageTags = [...list];
|
||||
await loadSheepInfo();
|
||||
// 关键修改:填充 batchTags 和 batchSheep,和手动输入保持一致
|
||||
batchTags.value = loadedSheep.map(s => s.manageTags);
|
||||
batchSheep.value = loadedSheep;
|
||||
form.value.manageTags = batchTags.value.join(' ');
|
||||
} else {
|
||||
proxy.$message.info("未查询到符合条件的耳号");
|
||||
}
|
||||
@@ -455,6 +496,8 @@ async function loadSheepBySheepfoldOnly(sheepfoldId, ranchId) {
|
||||
id: sheep.id,
|
||||
manageTags: sheep.manageTags || '未知耳号',
|
||||
sheepfoldId: Number(sheepfoldId),
|
||||
sheepTypeId: sheep.typeId, // 确保有 typeId
|
||||
varietyId: sheep.varietyId, // 确保有 varietyId
|
||||
})).filter(item => item.manageTags);
|
||||
|
||||
if (newSheepList.length === 0) {
|
||||
@@ -463,8 +506,7 @@ async function loadSheepBySheepfoldOnly(sheepfoldId, ranchId) {
|
||||
return [];
|
||||
}
|
||||
sheepOptions.value = newSheepList;
|
||||
|
||||
return newSheepList.map(s => s.manageTags);
|
||||
return newSheepList; // 返回完整对象数组,不只是 manageTags
|
||||
} catch (error) {
|
||||
console.error('根据羊舍加载耳号失败:', error);
|
||||
const errorMsg = error.response?.data?.msg || '加载羊舍耳号失败,请重试';
|
||||
@@ -487,6 +529,8 @@ async function loadSheepBySheepfoldAndType(sheepfoldId, typeId) {
|
||||
id: sheep.id,
|
||||
manageTags: sheep.manageTags,
|
||||
sheepfoldId: sheepfoldId,
|
||||
sheepTypeId: sheep.typeId || typeId, // 确保有 typeId
|
||||
varietyId: sheep.varietyId, // 确保有 varietyId
|
||||
}));
|
||||
|
||||
sheepOptions.value = formattedSheep;
|
||||
@@ -517,7 +561,9 @@ async function loadSheepByTypeOnly(typeId, ranchId) {
|
||||
const formattedSheep = filtered.map(s => ({
|
||||
id: s.id,
|
||||
manageTags: s.manageTags,
|
||||
sheepfoldId: s.sheepfoldId
|
||||
sheepfoldId: s.sheepfoldId,
|
||||
sheepTypeId: s.typeId || typeId, // 确保有 typeId
|
||||
varietyId: s.varietyId, // 确保有 varietyId
|
||||
}));
|
||||
sheepOptions.value = formattedSheep;
|
||||
return formattedSheep;
|
||||
@@ -528,6 +574,7 @@ async function loadSheepByTypeOnly(typeId, ranchId) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//加载羊只信息
|
||||
async function loadSheepInfo() {
|
||||
const tags = form.value.manageTags;
|
||||
@@ -582,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 = [];
|
||||
@@ -642,7 +711,8 @@ async function handleUpdate(row) {
|
||||
reason: Number(d.reason || 0),
|
||||
status: Number(d.status || 0),
|
||||
varietyId: Number(d.varietyId || 0),
|
||||
isEdit: true
|
||||
isEdit: true,
|
||||
comment: d.comment || '',
|
||||
};
|
||||
|
||||
form.value = formData;
|
||||
@@ -692,7 +762,7 @@ function submitForm() {
|
||||
reason: form.value.reason,
|
||||
transDate: form.value.transDate,
|
||||
technician: form.value.technician,
|
||||
comment: sheep.comment || ''
|
||||
comment: form.value.comment || ''
|
||||
})
|
||||
})
|
||||
).then(() => {
|
||||
@@ -717,11 +787,12 @@ function handleDelete(row) {
|
||||
}
|
||||
//导出
|
||||
function handleExport() {
|
||||
proxy.download(
|
||||
'/produce/manage_sheep/trans_group/export',
|
||||
{ ...queryParams.value },
|
||||
`trans_group_${Date.now()}.xlsx`
|
||||
);
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('/produce/manage_sheep/trans_group/export', { ...queryParams.value }, `转群记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
@@ -859,18 +930,18 @@ function removeBatchTag(idx) {
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
}
|
||||
|
||||
// 一键清空批量耳号(和改备注一致)
|
||||
// 一键清空批量耳号
|
||||
function clearBatchTags() {
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.manageTags = ''
|
||||
form.value.oldComment = ''
|
||||
}
|
||||
onMounted(() => {
|
||||
loadSheepfold();
|
||||
loadRanchList();
|
||||
getVarietyOptions();
|
||||
loadSheepTypeList();
|
||||
fetchTechnicalList();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<!-- 查询表单 -->
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="转场日期" style="width: 308px">
|
||||
@@ -90,10 +91,8 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="queryParams.technician" filterable allow-create clearable placeholder="请输入或选择技术员"
|
||||
style="min-width:150px">
|
||||
<!-- 如果有字典可以放开下面这行,没有就纯输入 -->
|
||||
<!-- <el-option v-for="item in technicianOptions" :key="item" :label="item" :value="item" /> -->
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="min-width:150px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
@@ -112,7 +111,7 @@
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd"
|
||||
v-hasPermi="['transition_info:transition_info:add']">新增</el-button>
|
||||
v-hasPermi="['produce:transition_info:add']">新增</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
|
||||
@@ -120,63 +119,68 @@
|
||||
</el-col> -->
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
|
||||
v-hasPermi="['transition_info:transition_info:remove']">删除</el-button>
|
||||
v-hasPermi="['produce:transition_info:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport"
|
||||
v-hasPermi="['transition_info:transition_info:export']">导出</el-button>
|
||||
v-hasPermi="['produce:transition_info:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="transition_infoList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" min-width="120" />
|
||||
<el-table-column label="转场日期" align="center" prop="transitionDate" min-width="150">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.transitionDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="转场类型" align="center" prop="transTypeText" />
|
||||
<el-table-column label="转入牧场" align="center" prop="transTo" min-width="120" />
|
||||
<el-table-column label="转出牧场" align="center" prop="transFrom" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" min-width="120" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="130">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="当前状态" align="center" prop="status" min-width="120">
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="transition_infoList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="管理耳号" align="center" prop="manageTags" min-width="100" fixed />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" min-width="120" />
|
||||
<el-table-column label="转场日期" align="center" prop="transitionDate" min-width="150">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.transitionDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="转场类型" align="center" prop="transTypeText" />
|
||||
<el-table-column label="转入牧场" align="center" prop="transTo" min-width="120" />
|
||||
<el-table-column label="转出牧场" align="center" prop="transFrom" />
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" min-width="120" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" min-width="130">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="当前状态" align="center" prop="status" min-width="120">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.status === 0">待审批</span>
|
||||
<span v-else-if="scope.row.status === 1 || scope.row.status === 2">审批完成</span>
|
||||
<span v-else>未知状态</span>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="操作" align="center" min-width="180" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleApprove(scope.row)"
|
||||
v-hasPermi="['transition_info:transition_info:approve']" :disabled="scope.row.status !== 0">审批</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['transition_info:transition_info:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<el-table-column label="操作" align="center" min-width="180" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleApprove(scope.row)"
|
||||
v-hasPermi="['produce:transition_info:approve']" :disabled="scope.row.status !== 0">审批</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['produce:transition_info:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 新增/修改 -->
|
||||
<el-dialog :title="title" v-model="open" width="700px" append-to-body>
|
||||
<el-form ref="transition_infoRef" :model="form" :rules="rules" label-width="80px">
|
||||
@@ -231,7 +235,13 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" clearable filterable style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="comment">
|
||||
<el-input v-model="form.comment" placeholder="请填写备注" type="textarea" rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -296,10 +306,29 @@ import { listTransition_info, getTransition_info, delTransition_info, addTransit
|
||||
import { checkSheepByManageTags, getSheepBySheepfoldId } from '@/api/produce/other/fixHoof'
|
||||
import request from '@/utils/request'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { status, trans_type } = proxy.useDict('status', 'trans_type')
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
const transition_infoList = ref([])
|
||||
const open = ref(false)
|
||||
const loading = ref(true)
|
||||
@@ -341,6 +370,7 @@ const data = reactive({
|
||||
transType: null,
|
||||
transitionDate: null,
|
||||
technician: null,
|
||||
comment: null,
|
||||
tagDetails: {}
|
||||
},
|
||||
queryParams: {
|
||||
@@ -415,6 +445,7 @@ function reset() {
|
||||
transType: null,
|
||||
technician: null,
|
||||
createBy: null,
|
||||
comment: null,
|
||||
tagDetails: {}
|
||||
};
|
||||
batchTags.value = [];
|
||||
@@ -549,11 +580,12 @@ async function loadSheepInfo() {
|
||||
|
||||
// 导出
|
||||
function handleExport() {
|
||||
proxy.download(
|
||||
'/produce/manage_sheep/transition_info/export',
|
||||
{ ...queryParams.value },
|
||||
`transition_info_${Date.now()}.xlsx`
|
||||
);
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('/produce/manage_sheep/transition_info/export', { ...queryParams.value }, `转场记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 审批
|
||||
@@ -667,7 +699,8 @@ async function handleUpdate(row) {
|
||||
getTransition_info(_id).then(response => {
|
||||
form.value = {
|
||||
...response.data,
|
||||
manageTags: [response.data.manageTags]
|
||||
manageTags: [response.data.manageTags],
|
||||
comment: response.data.comment || ''
|
||||
};
|
||||
open.value = true;
|
||||
title.value = "修改转场";
|
||||
@@ -700,7 +733,7 @@ async function submitForm() {
|
||||
eventType: form.value.eventType,
|
||||
transitionDate: form.value.transitionDate,
|
||||
technician: form.value.technician,
|
||||
comment: batchSheep.value[idx].comment || '',
|
||||
comment: form.value.comment || '',
|
||||
status: 0,
|
||||
}))
|
||||
|
||||
@@ -736,17 +769,36 @@ 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) {
|
||||
sheepOptions.value = [];
|
||||
form.value.manageTags = [];
|
||||
batchTags.value = []; // 清空
|
||||
batchSheep.value = []; // 清空
|
||||
form.value.manageTags = '';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -754,9 +806,23 @@ async function handleRanchChange(ranchName) {
|
||||
if (!matched) return;
|
||||
|
||||
const res = await getSheepByRanchId(matched.id);
|
||||
sheepOptions.value = (res.data || []).map(s => ({ id: s.id, manageTags: s.manageTags }));
|
||||
form.value.manageTags = (res.data || []).map(s => s.manageTags);
|
||||
await loadSheepInfo();
|
||||
const sheepList = (res.data || []).map(s => ({
|
||||
id: s.id,
|
||||
manageTags: s.manageTags,
|
||||
varietyId: s.varietyId, // 确保有品种ID
|
||||
varietyName: s.varietyName || '', // 确保有品种名
|
||||
ranchId: s.ranchId
|
||||
}));
|
||||
|
||||
// 关键修改:填充 batchTags 和 batchSheep,和手动输入保持一致
|
||||
batchTags.value = sheepList.map(s => s.manageTags);
|
||||
batchSheep.value = sheepList;
|
||||
form.value.manageTags = batchTags.value.join(' ');
|
||||
|
||||
// 自动填充转出牧场(当前选中的牧场)
|
||||
form.value.transFrom = ranchName;
|
||||
|
||||
sheepOptions.value = sheepList;
|
||||
}
|
||||
/* 粘贴事件 */
|
||||
function handlePaste() {
|
||||
@@ -888,6 +954,7 @@ onMounted(() => {
|
||||
getVarietyOptions();
|
||||
loadSheepOptions();
|
||||
loadSheepTypeList();
|
||||
fetchTechnicalList();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<!-- 搜索区域 -->
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="事件日期" style="width: 308px">
|
||||
@@ -41,7 +42,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="羊舍" prop="sheepfold">
|
||||
<!-- <el-form-item label="羊舍" prop="sheepfold">
|
||||
<el-select v-model="queryParams.sheepfold" placeholder="请选择羊舍" style="min-width:150px" clearable>
|
||||
<el-option v-for="item in sheepfoldOptions" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
|
||||
</el-select>
|
||||
@@ -50,6 +51,11 @@
|
||||
<el-select v-model="queryParams.varietyId" placeholder="请选择品种" style="min-width:150px" clearable>
|
||||
<el-option v-for="item in varietyOptions" :key="item.id" :label="item.variety" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="max-width: 160px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
@@ -86,64 +92,77 @@
|
||||
</el-row>
|
||||
|
||||
<!-- 列表表格 -->
|
||||
<el-table v-loading="loading" :data="castrateList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate" width="130">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</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)"
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="castrateList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="去势日期" align="center" prop="eventDate" width="130">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<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="['produce:castrate:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['produce:castrate:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['produce:castrate: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" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 新增/修改弹窗 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="castrateRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="管理耳号" prop="manageTags">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable allow-create
|
||||
style="width: 100%; flex:1;" @change="loadSheepInfo" @blur="loadSheepInfo">
|
||||
<el-option v-for="sheep in sheepOptions" :key="sheep.id" :label="sheep.manageTags"
|
||||
:value="sheep.manageTags" />
|
||||
</el-select>
|
||||
<span v-if="form.manageTags?.length > 0" class="tag-count">
|
||||
已选 {{ form.manageTags.length }} 个
|
||||
</span>
|
||||
</div>
|
||||
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" clearable />
|
||||
</el-form-item>
|
||||
<!-- 新增弹窗已选耳号展示区 -->
|
||||
<div v-if="batchTags.length" class="selected-ear-numbers">
|
||||
<el-tag v-for="(tag, idx) in batchTags" :key="tag" closable @close="removeBatchTag(idx)" style="margin:4px"
|
||||
type="success">
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
<el-button type="primary" link @click="clearBatchTags">
|
||||
一键清空 ({{ batchTags.length }})
|
||||
</el-button>
|
||||
</div>
|
||||
<el-form-item label="事件日期" prop="eventDate">
|
||||
<el-date-picker v-model="form.eventDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择事件日期" />
|
||||
</el-form-item>
|
||||
<el-form-item label="羊舍" prop="sheepfold">
|
||||
<el-select v-model="form.sheepfold" placeholder="请选择羊舍" clearable @change="loadSheepBySheepfold">
|
||||
<el-option v-for="fold in sheepfoldOptions" :key="fold.id" :label="fold.sheepfoldName" :value="fold.id" />
|
||||
<el-select v-model="form.sheepfold" placeholder="请选择或输入羊舍" clearable filterable
|
||||
:filter-method="filterSheepfold" @change="loadSheepBySheepfold">
|
||||
<el-option v-for="fold in filteredSheepfoldOptions" :key="fold.id" :label="fold.sheepfoldName"
|
||||
:value="fold.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" />
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" clearable filterable style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="事件日期" prop="eventDate">
|
||||
<el-date-picker v-model="form.eventDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择事件日期" />
|
||||
<el-form-item label="备注" prop="comment">
|
||||
<el-input v-model="form.comment" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -161,6 +180,7 @@ import { listCastrate, getCastrate, delCastrate, addCastrate, searchEarNumbers }
|
||||
import { checkSheepByManageTags, getVarietyOptions, getSheepBySheepfoldId } from '@/api/produce/other/fixHoof'
|
||||
import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/sheepfold_management'
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
import { nextTick } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
const { proxy } = getCurrentInstance()
|
||||
@@ -175,9 +195,13 @@ const multiple = ref(true)
|
||||
const total = ref(0)
|
||||
const title = ref('')
|
||||
const daterangeCreateTime = ref([])
|
||||
const sheepOptions = ref([])
|
||||
const filteredSheepfoldOptions = ref([])
|
||||
const varietyOptions = ref([])
|
||||
const daterangeEventDate = ref([])
|
||||
const batchTags = ref([]) // 本次要新增的多条耳号
|
||||
const batchSheep = ref([]) // 对应的羊只对象
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
const pasteText = ref('')
|
||||
const isExpanded = ref(false)
|
||||
const defaultShowCount = 2
|
||||
@@ -194,6 +218,7 @@ const data = reactive({
|
||||
technician: null,
|
||||
tagDetails: {},
|
||||
eventDate: null,
|
||||
comment: null,
|
||||
},
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
@@ -225,84 +250,81 @@ const data = reactive({
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
const earOptions = ref([])
|
||||
const earLoading = ref(false)
|
||||
//通过羊舍获取羊只
|
||||
// 羊舍变化处理:自动加载该羊舍下所有公羊(清空已有)
|
||||
function loadSheepBySheepfold() {
|
||||
const sheepfoldId = form.value.sheepfold;
|
||||
const sheepfoldId = form.value.sheepfold
|
||||
if (!sheepfoldId) {
|
||||
sheepOptions.value = [];
|
||||
return;
|
||||
// 清空羊舍时,不清空耳号
|
||||
return
|
||||
}
|
||||
|
||||
// 清空已有耳号
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.manageTags = ''
|
||||
|
||||
getSheepBySheepfoldId(sheepfoldId)
|
||||
.then(res => {
|
||||
let sheepList = res.data || [];
|
||||
sheepList = sheepList.filter(sheep => sheep.gender === 2);
|
||||
let sheepList = res.data || []
|
||||
sheepList = sheepList.filter(sheep => sheep.gender === 2)
|
||||
|
||||
if (sheepList.length === 0) {
|
||||
proxy.$modal.msgInfo('该羊舍下暂无性别为公的羊只');
|
||||
sheepOptions.value = [];
|
||||
return;
|
||||
proxy.$modal.msgInfo('该羊舍下暂无公羊')
|
||||
return
|
||||
}
|
||||
|
||||
sheepOptions.value = sheepList.map(sheep => ({
|
||||
id: sheep.id,
|
||||
manageTags: sheep.manageTags,
|
||||
gender: sheep.gender
|
||||
}));
|
||||
// 填充该羊舍所有公羊
|
||||
for (const sheep of sheepList) {
|
||||
batchTags.value.push(sheep.manageTags)
|
||||
batchSheep.value.push(sheep)
|
||||
}
|
||||
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
proxy.$modal.msgSuccess(`已加载 ${batchTags.value.length} 只公羊`)
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载羊舍耳号失败', error);
|
||||
proxy.$modal.msgError('加载耳号失败,请重试');
|
||||
sheepOptions.value = [];
|
||||
});
|
||||
console.error('加载羊舍耳号失败', error)
|
||||
proxy.$modal.msgError('加载耳号失败,请重试')
|
||||
})
|
||||
}
|
||||
|
||||
// 输入耳号后校验并获取品种/羊舍等信息
|
||||
async function loadSheepInfo() {
|
||||
const tags = form.value.manageTags;
|
||||
if (!tags || tags.length === 0) return;
|
||||
// 输入耳号后校验并追加(不清空已有)
|
||||
async function onManageTagsBlur() {
|
||||
const raw = form.value.manageTags?.trim()
|
||||
if (!raw) return
|
||||
|
||||
const tagDetails = {};
|
||||
const validResults = [];
|
||||
// 按分隔符拆分
|
||||
const separators = /[\p{White_Space},,]+/u
|
||||
const newTags = [...new Set(raw.split(separators).filter(v => v))]
|
||||
|
||||
for (const tag of tags) {
|
||||
try {
|
||||
const { data: sheepData } = await checkSheepByManageTags(tag.trim());
|
||||
// 过滤掉已存在的
|
||||
const existTags = new Set(batchTags.value)
|
||||
const tagsToAdd = newTags.filter(tag => !existTags.has(tag))
|
||||
|
||||
if (!sheepData) {
|
||||
validResults.push(false);
|
||||
proxy.$modal.msgError(`耳号 ${tag} 不存在`);
|
||||
} else if (sheepData.gender !== 2) {
|
||||
validResults.push(false);
|
||||
proxy.$modal.msgError(`耳号 ${tag} 对应的羊只性别不是公,无法添加`);
|
||||
} else {
|
||||
validResults.push(true);
|
||||
tagDetails[tag] = {
|
||||
sheepId: sheepData.id,
|
||||
gender: sheepData.gender,
|
||||
sheepfoldId: sheepData.sheepfoldId,
|
||||
varietyId: sheepData.varietyId,
|
||||
comment: sheepData.comment || ''
|
||||
};
|
||||
if (validResults.length === 1) {
|
||||
form.value.sheepfold = sheepData.sheepfoldId;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`耳号 ${tag} 校验失败`, error);
|
||||
validResults.push(false);
|
||||
proxy.$modal.msgError(`耳号 ${tag} 校验异常,请重试`);
|
||||
if (tagsToAdd.length === 0) {
|
||||
// 全部已存在,回写现有
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
return
|
||||
}
|
||||
|
||||
// 校验并追加新耳号
|
||||
for (const tag of tagsToAdd) {
|
||||
const sheep = await checkSheepByManageTags(tag).then(r => r.data).catch(() => null)
|
||||
if (!sheep) {
|
||||
proxy.$modal.msgWarning(`耳号 ${tag} 不存在,已跳过`)
|
||||
continue
|
||||
}
|
||||
if (Number(sheep.gender)) {
|
||||
proxy.$modal.msgWarning(`耳号 ${tag} 不是公羊,已跳过`)
|
||||
continue
|
||||
}
|
||||
batchTags.value.push(tag)
|
||||
batchSheep.value.push(sheep)
|
||||
}
|
||||
|
||||
form.value.manageTags = tags.filter((_, index) => validResults[index]);
|
||||
form.value.tagDetails = tagDetails;
|
||||
|
||||
if (validResults.includes(false)) {
|
||||
proxy.$message.warning('部分耳号不符合条件(不存在或非公羊),已自动过滤');
|
||||
}
|
||||
// 回写所有耳号
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
}
|
||||
|
||||
/** 查询列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
@@ -319,7 +341,9 @@ function getList() {
|
||||
q.params.beginEventDate = daterangeEventDate.value[0];
|
||||
q.params.endEventDate = daterangeEventDate.value[1];
|
||||
}
|
||||
|
||||
if (q.technician) {
|
||||
q.params.technician = q.technician;
|
||||
}
|
||||
listCastrate(q).then(res => {
|
||||
castrateList.value = res.rows;
|
||||
console.log("后端返回的列表数据:", res.rows);
|
||||
@@ -342,13 +366,16 @@ function cancel() {
|
||||
function reset() {
|
||||
form.value = {
|
||||
id: null,
|
||||
manageTags: [],
|
||||
manageTags: null,
|
||||
sheepfold: null,
|
||||
technician: null,
|
||||
eventDate: null
|
||||
};
|
||||
sheepOptions.value = [];
|
||||
proxy.resetForm('castrateRef');
|
||||
eventDate: null,
|
||||
comment: null
|
||||
}
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
filteredSheepfoldOptions.value = sheepfoldOptions.value
|
||||
proxy.resetForm('castrateRef')
|
||||
}
|
||||
|
||||
//搜索
|
||||
@@ -362,6 +389,7 @@ function resetQuery() {
|
||||
daterangeCreateTime.value = []
|
||||
daterangeEventDate.value = []
|
||||
queryParams.value.manageTagsList = []
|
||||
queryParams.value.technician = null
|
||||
queryParams.value.isDelete = null
|
||||
proxy.resetForm('queryRef')
|
||||
handleQuery()
|
||||
@@ -428,49 +456,52 @@ async function validateAllTags() {
|
||||
|
||||
//提交
|
||||
function submitForm() {
|
||||
proxy.$refs.castrateRef.validate(valid => {
|
||||
if (!valid) return;
|
||||
if (batchTags.value.length === 0) {
|
||||
proxy.$modal.msgError('请输入至少一个有效耳号')
|
||||
return
|
||||
}
|
||||
if (!form.value.technician) {
|
||||
proxy.$modal.msgError('请输入技术员')
|
||||
return
|
||||
}
|
||||
if (!form.value.eventDate) {
|
||||
proxy.$modal.msgError('请选择事件日期')
|
||||
return
|
||||
}
|
||||
|
||||
const allTags = form.value.manageTags;
|
||||
const tagDetails = form.value.tagDetails || {};
|
||||
|
||||
if (!allTags || allTags.length === 0) {
|
||||
proxy.$modal.msgError('请选择有效的公羊耳号');
|
||||
return;
|
||||
}
|
||||
|
||||
const invalidTags = allTags.filter(tag => {
|
||||
const details = tagDetails[tag];
|
||||
return !details || details.gender !== 2;
|
||||
});
|
||||
if (invalidTags.length > 0) {
|
||||
proxy.$modal.msgError(`耳号 ${invalidTags.join(',')} 性别不符合要求,无法提交`);
|
||||
return;
|
||||
}
|
||||
|
||||
const requests = allTags.map(tag => {
|
||||
const details = tagDetails[tag];
|
||||
return addCastrate({
|
||||
// 批量新增
|
||||
Promise.all(
|
||||
batchTags.value.map((tag, idx) =>
|
||||
addCastrate({
|
||||
sheepId: batchSheep.value[idx].id,
|
||||
manageTags: tag,
|
||||
sheepId: details.sheepId,
|
||||
sheepfold: details.sheepfoldId || form.value.sheepfold,
|
||||
sheepfold: batchSheep.value[idx].sheepfoldId,
|
||||
varietyId: batchSheep.value[idx].varietyId,
|
||||
technician: form.value.technician,
|
||||
varietyId: details.varietyId,
|
||||
comment: details.comment,
|
||||
eventDate: form.value.eventDate
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(requests)
|
||||
.then(() => {
|
||||
proxy.$modal.msgSuccess('新增成功');
|
||||
open.value = false;
|
||||
getList();
|
||||
eventDate: form.value.eventDate,
|
||||
comment: form.value.comment || ''
|
||||
})
|
||||
.catch(error => {
|
||||
proxy.$modal.msgError(`新增失败:${error.message}`);
|
||||
});
|
||||
});
|
||||
)
|
||||
).then(() => {
|
||||
proxy.$modal.msgSuccess(`成功新增 ${batchTags.value.length} 条去势记录`)
|
||||
open.value = false
|
||||
getList()
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
/* 删除单个批量耳号 */
|
||||
function removeBatchTag(idx) {
|
||||
batchTags.value.splice(idx, 1)
|
||||
batchSheep.value.splice(idx, 1)
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
// 不再自动更新羊舍
|
||||
}
|
||||
|
||||
/* 一键清空批量耳号 */
|
||||
function clearBatchTags() {
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.manageTags = ''
|
||||
}
|
||||
|
||||
//删除
|
||||
@@ -486,22 +517,69 @@ function handleDelete(row) {
|
||||
|
||||
//导出
|
||||
function handleExport() {
|
||||
proxy.download('/produce/other/castrate/export', { ...queryParams.value }, `castrate_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('/produce/other/castrate/export', { ...queryParams.value }, `去势记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
const sheepfoldOptions = ref([])
|
||||
function getSheepfoldOptions() {
|
||||
listSheepfold({ pageNum: 1, pageSize: 9999 }).then(res => {
|
||||
sheepfoldOptions.value = res.rows
|
||||
filteredSheepfoldOptions.value = res.rows
|
||||
})
|
||||
}
|
||||
function searchEarNumber(query) {
|
||||
if (!query) { earOptions.value = []; return }
|
||||
// 羊舍模糊过滤
|
||||
function filterSheepfold(query) {
|
||||
if (!query) {
|
||||
filteredSheepfoldOptions.value = sheepfoldOptions.value
|
||||
return
|
||||
}
|
||||
filteredSheepfoldOptions.value = sheepfoldOptions.value.filter(fold =>
|
||||
fold.sheepfoldName.includes(query)
|
||||
)
|
||||
}
|
||||
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 = []
|
||||
@@ -546,6 +624,7 @@ function handleEarChange(val) {
|
||||
onMounted(() => {
|
||||
getSheepfoldOptions()
|
||||
getVarietyOptions()
|
||||
fetchTechnicalList()
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="app-container"
|
||||
style="height: calc(100vh - 84px); display: flex; flex-direction: column; overflow: hidden;">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="事件日期" style="width: 308px">
|
||||
<el-date-picker v-model="daterangeEventDate" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
|
||||
@@ -40,7 +41,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="羊舍" prop="sheepfold">
|
||||
<!-- <el-form-item label="羊舍" prop="sheepfold">
|
||||
<el-select v-model="queryParams.sheepfold" placeholder="请选择羊舍" style="min-width:150px" clearable>
|
||||
<el-option v-for="item in sheepfoldOptions" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
|
||||
</el-select>
|
||||
@@ -49,6 +50,11 @@
|
||||
<el-select v-model="queryParams.varietyId" placeholder="请选择品种" style="min-width:150px" clearable>
|
||||
<el-option v-for="item in varietyOptions" :key="item.id" :label="item.variety" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="queryParams.technician" placeholder="请选择技术员" clearable filterable style="max-width: 160px">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否在群" prop="isDelete">
|
||||
<el-select v-model="queryParams.isDelete" placeholder="全部" clearable style="min-width:120px">
|
||||
@@ -66,85 +72,98 @@
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd"
|
||||
v-hasPermi="['fixHoof:fixHoof:add']">新增</el-button>
|
||||
v-hasPermi="['produce:fixHoof:add']">新增</el-button>
|
||||
</el-col>
|
||||
<!-- 按需添加 是否需要修改功能 -->
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
|
||||
v-hasPermi="['fixHoof:fixHoof:edit']">修改</el-button>
|
||||
v-hasPermi="['produce:fixHoof:edit']">修改</el-button>
|
||||
</el-col> -->
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
|
||||
v-hasPermi="['fixHoof:fixHoof:remove']">删除</el-button>
|
||||
v-hasPermi="['produce:fixHoof:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport"
|
||||
v-hasPermi="['fixHoof:fixHoof:export']">导出</el-button>
|
||||
v-hasPermi="['produce:fixHoof:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="fixHoofList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="事件日期" align="center" prop="eventDate" width="130">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</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="['fixHoof:fixHoof:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['fixHoof:fixHoof:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
<div style="flex: 1; overflow: hidden;">
|
||||
<el-table v-loading="loading" :data="fixHoofList" @selection-change="handleSelectionChange" height="100%"
|
||||
style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="耳号" align="center" prop="manageTags" />
|
||||
<el-table-column label="品种" align="center" prop="varietyName" />
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="120" />
|
||||
<el-table-column label="修蹄日期" align="center" prop="eventDate" width="130">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.eventDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="羊舍" align="center" prop="sheepfoldName" />
|
||||
<el-table-column label="技术员" align="center" prop="technician" />
|
||||
<el-table-column label="创建人" align="center" prop="createBy" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="comment" />
|
||||
<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="['produce:fixHoof:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['produce:fixHoof:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink: 0; padding: 10px 0;">
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" :page-sizes="[20, 50, 100, 200, 500, 1000, 2000]" />
|
||||
</div>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="fixHoofRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="耳号" prop="manageTags">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable allow-create
|
||||
style="width: 100%; flex:1;" @change="loadSheepInfo">
|
||||
<el-option v-for="sheep in sheepOptions" :key="sheep.id" :label="sheep.manageTags"
|
||||
:value="sheep.manageTags" />
|
||||
</el-select>
|
||||
<span v-if="form.manageTags?.length > 0" class="tag-count">
|
||||
已选 {{ form.manageTags.length }} 个
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="羊舍" prop="sheepfolds">
|
||||
<el-select v-model="form.sheepfold" filterable style="width: 100%" @change="loadSheepBySheepfold">
|
||||
<el-option v-for="fold in sheepfoldOptions" :key="fold.id" :label="fold.sheepfoldName" :value="fold.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-input v-model="form.technician" placeholder="请输入技术员" />
|
||||
<el-form-item label="管理耳号" prop="manageTags">
|
||||
<el-input v-model="form.manageTags" placeholder="请输入管理耳号" @blur="onManageTagsBlur" clearable />
|
||||
</el-form-item>
|
||||
<!-- 新增弹窗已选耳号展示区 -->
|
||||
<div v-if="batchTags.length" class="selected-ear-numbers">
|
||||
<el-tag v-for="(tag, idx) in batchTags" :key="tag" closable @close="removeBatchTag(idx)" style="margin:4px"
|
||||
type="success">
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
<el-button type="primary" link @click="clearBatchTags">
|
||||
一键清空 ({{ batchTags.length }})
|
||||
</el-button>
|
||||
</div>
|
||||
<el-form-item label="事件日期" prop="eventDate">
|
||||
<el-date-picker v-model="form.eventDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择事件日期"
|
||||
clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="羊舍" prop="sheepfold">
|
||||
<el-select v-model="form.sheepfold" placeholder="请选择羊舍" clearable filterable :filter-method="filterSheepfold"
|
||||
@change="loadSheepBySheepfold">
|
||||
<el-option v-for="fold in filteredSheepfoldOptions" :key="fold.id" :label="fold.sheepfoldName"
|
||||
:value="fold.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术员" prop="technician">
|
||||
<el-select v-model="form.technician" placeholder="请选择技术员" clearable filterable style="width: 100%">
|
||||
<el-option v-for="item in technicalOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="comment">
|
||||
<el-input v-model="form.comment" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
@@ -162,6 +181,7 @@ import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/
|
||||
import { Plus, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
|
||||
import { nextTick } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { getUserByPost } from '@/api/common/user'
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const fixHoofList = ref([])
|
||||
@@ -175,7 +195,11 @@ const total = ref(0)
|
||||
const title = ref('')
|
||||
const daterangeCreateTime = ref([])
|
||||
const varietyOptions = ref([])
|
||||
const sheepOptions = ref([])
|
||||
const filteredSheepfoldOptions = ref([])
|
||||
const batchTags = ref([]) // 本次要新增的多条耳号
|
||||
const batchSheep = ref([]) // 对应的羊只对象
|
||||
// 技术员下拉选项
|
||||
const technicalOptions = ref([])
|
||||
const daterangeEventDate = ref([])
|
||||
const pasteText = ref('')
|
||||
const isExpanded = ref(false)
|
||||
@@ -207,9 +231,6 @@ const data = reactive({
|
||||
manageTags: [
|
||||
{ required: true, message: '请输入管理耳号', trigger: 'blur' }
|
||||
],
|
||||
sheepfold: [
|
||||
{ required: true, message: '请选择羊舍', trigger: 'change' }
|
||||
],
|
||||
technician: [
|
||||
{ required: true, message: '请输入技术员', trigger: 'blur' }
|
||||
],
|
||||
@@ -222,73 +243,79 @@ const data = reactive({
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
const earOptions = ref([])
|
||||
const earLoading = ref(false)
|
||||
//根据羊舍获取羊只
|
||||
// 羊舍变化处理:自动加载该羊舍下所有羊(清空已有)
|
||||
function loadSheepBySheepfold() {
|
||||
const currentSheepfoldId = form.value.sheepfold;
|
||||
const sheepfoldId = form.value.sheepfold
|
||||
if (!sheepfoldId) return
|
||||
|
||||
if (!currentSheepfoldId) {
|
||||
sheepOptions.value = [];
|
||||
return;
|
||||
}
|
||||
// 清空已有耳号
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.manageTags = ''
|
||||
|
||||
getSheepBySheepfoldId(currentSheepfoldId)
|
||||
getSheepBySheepfoldId(sheepfoldId)
|
||||
.then(res => {
|
||||
const newSheepList = res.data || [];
|
||||
sheepOptions.value = newSheepList.map(sheep => ({
|
||||
id: sheep.id,
|
||||
manageTags: sheep.manageTags,
|
||||
sheepfoldId: currentSheepfoldId
|
||||
}));
|
||||
const sheepList = res.data || []
|
||||
if (sheepList.length === 0) {
|
||||
proxy.$modal.msgInfo('该羊舍下暂无羊只')
|
||||
return
|
||||
}
|
||||
|
||||
// 填充该羊舍所有羊
|
||||
for (const sheep of sheepList) {
|
||||
batchTags.value.push(sheep.manageTags)
|
||||
batchSheep.value.push(sheep)
|
||||
}
|
||||
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
proxy.$modal.msgSuccess(`已加载 ${batchTags.value.length} 只羊`)
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载新羊舍耳号失败', error);
|
||||
proxy.$modal.msgError('切换羊舍失败,请重试');
|
||||
sheepOptions.value = [];
|
||||
});
|
||||
console.error('加载羊舍耳号失败', error)
|
||||
proxy.$modal.msgError('加载耳号失败,请重试')
|
||||
})
|
||||
}
|
||||
|
||||
async function loadSheepInfo() {
|
||||
const tags = form.value.manageTags;
|
||||
if (!tags || tags.length === 0) return;
|
||||
function filterSheepfold(query) {
|
||||
if (!query) {
|
||||
filteredSheepfoldOptions.value = sheepfoldOptions.value
|
||||
return
|
||||
}
|
||||
filteredSheepfoldOptions.value = sheepfoldOptions.value.filter(fold =>
|
||||
fold.sheepfoldName.includes(query)
|
||||
)
|
||||
}
|
||||
// 输入耳号后校验并追加(不清空已有)
|
||||
async function onManageTagsBlur() {
|
||||
const raw = form.value.manageTags?.trim()
|
||||
if (!raw) return
|
||||
|
||||
const tagDetails = {};
|
||||
const validResults = [];
|
||||
const validTags = [];
|
||||
// 按分隔符拆分
|
||||
const separators = /[\p{White_Space},,]+/u
|
||||
const newTags = [...new Set(raw.split(separators).filter(v => v))]
|
||||
|
||||
for (const tag of tags) {
|
||||
try {
|
||||
const { data: sheepData } = await checkSheepByManageTags(tag.trim());
|
||||
if (!sheepData) {
|
||||
validResults.push(false);
|
||||
proxy.$modal.msgError(`耳号 ${tag} 不存在`);
|
||||
} else {
|
||||
validResults.push(true);
|
||||
validTags.push(tag);
|
||||
tagDetails[tag] = {
|
||||
comment: sheepData.comment || '',
|
||||
varietyId: sheepData.varietyId,
|
||||
sheepfoldId: sheepData.sheepfoldId,
|
||||
sheepId: sheepData.id
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取耳号信息失败:', error);
|
||||
proxy.$modal.msgError(`耳号 ${tag} 验证失败`);
|
||||
validResults.push(false);
|
||||
// 过滤掉已存在的
|
||||
const existTags = new Set(batchTags.value)
|
||||
const tagsToAdd = newTags.filter(tag => !existTags.has(tag))
|
||||
|
||||
if (tagsToAdd.length === 0) {
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
return
|
||||
}
|
||||
|
||||
// 校验并追加新耳号
|
||||
for (const tag of tagsToAdd) {
|
||||
const sheep = await checkSheepByManageTags(tag).then(r => r.data).catch(() => null)
|
||||
if (!sheep) {
|
||||
proxy.$modal.msgWarning(`耳号 ${tag} 不存在,已跳过`)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (validResults.includes(false)) {
|
||||
form.value.manageTags = tags.filter((_, index) => validResults[index]);
|
||||
proxy.$message.warning('部分耳号不合法,已过滤');
|
||||
batchTags.value.push(tag)
|
||||
batchSheep.value.push(sheep)
|
||||
}
|
||||
|
||||
form.value.tagDetails = tagDetails;
|
||||
|
||||
if (validTags.length > 0) {
|
||||
const firstValidTag = validTags[0];
|
||||
const firstSheepfoldId = tagDetails[firstValidTag].sheepfoldId;
|
||||
form.value.sheepfold = firstSheepfoldId;
|
||||
}
|
||||
// 回写所有耳号
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
}
|
||||
|
||||
//获取修蹄列表
|
||||
@@ -307,7 +334,9 @@ function getList() {
|
||||
q.params.beginEventDate = daterangeEventDate.value[0]
|
||||
q.params.endEventDate = daterangeEventDate.value[1]
|
||||
}
|
||||
|
||||
if (q.technician) {
|
||||
q.params.technician = q.technician
|
||||
}
|
||||
listFixHoof(q).then(res => {
|
||||
fixHoofList.value = res.rows
|
||||
total.value = res.total
|
||||
@@ -328,13 +357,15 @@ function cancel() {
|
||||
function reset() {
|
||||
form.value = {
|
||||
id: null,
|
||||
manageTags: '',
|
||||
sheepfold: null,
|
||||
manageTags: [],
|
||||
varietyId: null,
|
||||
varietyName: null,
|
||||
eventDate: null
|
||||
technician: null,
|
||||
eventDate: null,
|
||||
comment: null
|
||||
}
|
||||
sheepOptions.value = [];
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
filteredSheepfoldOptions.value = sheepfoldOptions.value
|
||||
proxy.resetForm('fixHoofRef')
|
||||
}
|
||||
|
||||
@@ -350,6 +381,7 @@ function resetQuery() {
|
||||
daterangeEventDate.value = []
|
||||
queryParams.value.varietyId = null
|
||||
queryParams.value.manageTagsList = []
|
||||
queryParams.value.technician = null
|
||||
queryParams.value.isDelete = null
|
||||
proxy.resetForm('queryRef')
|
||||
handleQuery()
|
||||
@@ -384,40 +416,53 @@ function handleUpdate(row) {
|
||||
|
||||
//提交
|
||||
function submitForm() {
|
||||
proxy.$refs.fixHoofRef.validate(valid => {
|
||||
if (!valid) return;
|
||||
if (batchTags.value.length === 0) {
|
||||
proxy.$modal.msgError('请输入至少一个有效耳号')
|
||||
return
|
||||
}
|
||||
if (!form.value.technician) {
|
||||
proxy.$modal.msgError('请选择技术员')
|
||||
return
|
||||
}
|
||||
if (!form.value.eventDate) {
|
||||
proxy.$modal.msgError('请选择事件日期')
|
||||
return
|
||||
}
|
||||
|
||||
const allTags = form.value.manageTags;
|
||||
const tagDetails = form.value.tagDetails || {};
|
||||
if (!allTags || allTags.length === 0) {
|
||||
proxy.$modal.msgError('请选择至少一个耳号');
|
||||
return;
|
||||
}
|
||||
const fixHoofList = batchTags.value.map((tag, idx) => ({
|
||||
manageTags: tag,
|
||||
sheepId: batchSheep.value[idx].id,
|
||||
sheepfold: batchSheep.value[idx].sheepfoldId,
|
||||
varietyId: batchSheep.value[idx].varietyId,
|
||||
technician: form.value.technician,
|
||||
eventDate: form.value.eventDate,
|
||||
comment: form.value.comment || ''
|
||||
}))
|
||||
|
||||
const fixHoofList = allTags.map(tag => {
|
||||
const details = tagDetails[tag] || {};
|
||||
return {
|
||||
...form.value,
|
||||
manageTags: tag,
|
||||
comment: details.comment || '',
|
||||
sheepId: details.sheepId,
|
||||
varietyId: details.varietyId,
|
||||
sheepfold: details.sheepfoldId || form.value.sheepfold
|
||||
};
|
||||
});
|
||||
|
||||
addFixHoof(fixHoofList)
|
||||
.then(() => {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
open.value = false;
|
||||
getList();
|
||||
})
|
||||
.catch(error => {
|
||||
proxy.$modal.msgError(`处理失败:${error.message}`);
|
||||
});
|
||||
});
|
||||
addFixHoof(fixHoofList)
|
||||
.then(() => {
|
||||
proxy.$modal.msgSuccess(`成功新增 ${batchTags.value.length} 条修蹄记录`)
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
.catch(error => {
|
||||
proxy.$modal.msgError(`处理失败:${error.message}`)
|
||||
})
|
||||
}
|
||||
/* 删除单个批量耳号 */
|
||||
function removeBatchTag(idx) {
|
||||
batchTags.value.splice(idx, 1)
|
||||
batchSheep.value.splice(idx, 1)
|
||||
form.value.manageTags = batchTags.value.join(' ')
|
||||
}
|
||||
|
||||
/* 一键清空批量耳号 */
|
||||
function clearBatchTags() {
|
||||
batchTags.value = []
|
||||
batchSheep.value = []
|
||||
form.value.manageTags = ''
|
||||
form.value.sheepfold = null
|
||||
}
|
||||
//删除
|
||||
function handleDelete(row) {
|
||||
const _ids = row.id || ids.value
|
||||
@@ -431,22 +476,59 @@ function handleDelete(row) {
|
||||
|
||||
//导出
|
||||
function handleExport() {
|
||||
proxy.download('/produce/other/fixHoof/export', { ...queryParams.value }, `fixHoof_${new Date().getTime()}.xlsx`)
|
||||
queryParams.value.ids = ids.value;
|
||||
try {
|
||||
proxy.download('/produce/other/fixHoof/export', { ...queryParams.value }, `修蹄记录${Date.now()}.xlsx`);
|
||||
} finally {
|
||||
queryParams.value.ids = null;
|
||||
}
|
||||
}
|
||||
|
||||
//加载羊舍数据
|
||||
const sheepfoldOptions = ref([])
|
||||
function getSheepfoldOptions() {
|
||||
listSheepfold({ pageNum: 1, pageSize: 9999 }).then(res => {
|
||||
sheepfoldOptions.value = res.rows
|
||||
filteredSheepfoldOptions.value = res.rows
|
||||
})
|
||||
}
|
||||
function searchEarNumber(query) {
|
||||
if (!query) { earOptions.value = []; return }
|
||||
// 获取技术员列表(岗位编码:techs)
|
||||
const fetchTechnicalList = () => {
|
||||
getUserByPost({ postCode: "techs" })
|
||||
.then(res => {
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
technicalOptions.value = res.data.map(item => ({
|
||||
value: item.nickName,
|
||||
label: item.nickName
|
||||
}))
|
||||
} else {
|
||||
technicalOptions.value = []
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
technicalOptions.value = []
|
||||
})
|
||||
}
|
||||
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 = []
|
||||
@@ -490,6 +572,7 @@ function handleEarChange(val) {
|
||||
onMounted(() => {
|
||||
getSheepfoldOptions()
|
||||
getVarietyOptions()
|
||||
fetchTechnicalList()
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -9,6 +9,19 @@
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="所在地区">
|
||||
<el-cascader
|
||||
v-model="queryArea"
|
||||
:options="areaOptions"
|
||||
:props="{ checkStrictly: true, ...areaProps }"
|
||||
placeholder="请选择地区"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@change="handleQueryAreaChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
@@ -57,24 +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">
|
||||
<template #default="scope">
|
||||
{{ scope.row.province }}{{ scope.row.city }}{{ scope.row.district }}{{ scope.row.address }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<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 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>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
@@ -92,7 +120,7 @@
|
||||
<el-form-item label="客户电话" prop="phone">
|
||||
<el-input v-model="form.phone" placeholder="请输入客户电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所在地区" required>
|
||||
<el-form-item label="所在地区">
|
||||
<el-cascader
|
||||
v-model="selectedArea"
|
||||
:options="areaOptions"
|
||||
@@ -143,20 +171,26 @@ const areaProps = {
|
||||
value: 'label',
|
||||
children: 'children'
|
||||
}
|
||||
// 表单用的地区绑定
|
||||
const selectedArea = ref([])
|
||||
// 查询用的地区绑定
|
||||
const queryArea = ref([])
|
||||
|
||||
const data = reactive({
|
||||
form: {},
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20, // 默认为20
|
||||
pageSize: 20,
|
||||
name: null,
|
||||
orderByColumn: null, // 增加排序字段
|
||||
isAsc: null // 增加排序方式
|
||||
province: null, // 新增
|
||||
city: null, // 新增
|
||||
district: null, // 新增
|
||||
orderByColumn: null,
|
||||
isAsc: null
|
||||
},
|
||||
rules: {
|
||||
name: [{ required: true, message: "客户名称不能为空", trigger: "blur" }],
|
||||
address: [{ required: true, message: "详细地址不能为空", trigger: "blur" }]
|
||||
// address 校验已移除,改为可选
|
||||
}
|
||||
})
|
||||
|
||||
@@ -175,6 +209,19 @@ function getList() {
|
||||
})
|
||||
}
|
||||
|
||||
// 处理查询栏地区变化
|
||||
function handleQueryAreaChange(val) {
|
||||
if (val && val.length > 0) {
|
||||
queryParams.value.province = val[0] || null
|
||||
queryParams.value.city = val[1] || null
|
||||
queryParams.value.district = val[2] || null
|
||||
} else {
|
||||
queryParams.value.province = null
|
||||
queryParams.value.city = null
|
||||
queryParams.value.district = null
|
||||
}
|
||||
}
|
||||
|
||||
// 处理排序变化
|
||||
function handleSortChange({ column, prop, order }) {
|
||||
queryParams.value.orderByColumn = prop
|
||||
@@ -209,10 +256,14 @@ function handleQuery() {
|
||||
|
||||
function resetQuery() {
|
||||
proxy.resetForm("queryRef")
|
||||
// 重置时也要清空排序
|
||||
// 重置地区选择
|
||||
queryArea.value = []
|
||||
queryParams.value.province = null
|
||||
queryParams.value.city = null
|
||||
queryParams.value.district = null
|
||||
|
||||
queryParams.value.orderByColumn = null
|
||||
queryParams.value.isAsc = null
|
||||
// 如果el-table需要清除UI上的排序图标,可调用clearSort,此处简化处理
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
@@ -246,8 +297,9 @@ function handleUpdate(row) {
|
||||
})
|
||||
}
|
||||
|
||||
// 处理表单提交时的地区数据
|
||||
function handleAddress() {
|
||||
if (selectedArea.value.length > 0) {
|
||||
if (selectedArea.value && selectedArea.value.length > 0) {
|
||||
form.value.province = selectedArea.value[0] || ''
|
||||
form.value.city = selectedArea.value[1] || ''
|
||||
form.value.district = selectedArea.value[2] || ''
|
||||
@@ -295,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>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +1,102 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px">
|
||||
|
||||
<el-form-item label="管理耳号" prop="manageTagsList">
|
||||
<el-select
|
||||
v-model="queryParams.manageTagsList"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="请输入耳号"
|
||||
:remote-method="remoteSearchEarNo"
|
||||
:loading="loadingSearch"
|
||||
allow-create
|
||||
default-first-option
|
||||
clearable
|
||||
style="width: 240px"
|
||||
|
||||
<el-form-item label="耳号" prop="allEarNumbers">
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
|
||||
<!-- 主选择器:不显示已选标签 -->
|
||||
<el-select
|
||||
v-model="queryParams.allEarNumbers"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="输入耳号搜索"
|
||||
:remote-method="searchEarNumber"
|
||||
:loading="earNumberLoading"
|
||||
allow-create
|
||||
default-first-option
|
||||
collapse-tags
|
||||
:max-collapse-tags="0"
|
||||
style="width: 300px"
|
||||
@change="handleEarNumberChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in earNumberOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<!-- 辅助粘贴输入框 -->
|
||||
<el-input
|
||||
v-model="pasteInput"
|
||||
placeholder="或粘贴多个耳号(空格/换行/逗号分隔)"
|
||||
style="width: 300px"
|
||||
@paste="handlePaste"
|
||||
@keyup.enter="handlePasteSubmit"
|
||||
clearable
|
||||
>
|
||||
<template #append>
|
||||
<el-button @click="handlePasteSubmit" :icon="Plus">添加</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<!-- 耳号计数显示 -->
|
||||
<el-tag
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="large"
|
||||
>
|
||||
已选: {{ queryParams.allEarNumbers.length }} 个
|
||||
</el-tag>
|
||||
|
||||
<!-- 清空按钮 -->
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="clearAllEarNumbers"
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
:icon="Delete"
|
||||
>
|
||||
清空全部
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 已选耳号展示区域(默认显示2个,可展开) -->
|
||||
<div
|
||||
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
|
||||
class="selected-ear-numbers-display"
|
||||
style="margin-top: 10px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in earNoOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<!-- 显示前2个或全部耳号 -->
|
||||
<el-tag
|
||||
v-for="(tag, index) in displayedEarNumbers"
|
||||
:key="tag"
|
||||
closable
|
||||
@close="handleRemoveEarNumber(tag)"
|
||||
style="margin: 4px;"
|
||||
type="success"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
|
||||
<!-- 展开/收起按钮 -->
|
||||
<el-button
|
||||
v-if="queryParams.allEarNumbers.length > defaultShowCount"
|
||||
type="primary"
|
||||
link
|
||||
@click="toggleExpand"
|
||||
style="margin-left: 8px;"
|
||||
>
|
||||
{{ isExpanded ? '收起' : `展开剩余 ${queryParams.allEarNumbers.length - defaultShowCount} 个` }}
|
||||
<el-icon class="el-icon--right">
|
||||
<component :is="isExpanded ? ArrowUp : ArrowDown" />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="死亡日期" prop="deathDateRange">
|
||||
@@ -379,11 +452,15 @@ import {
|
||||
getSheepInfo,
|
||||
getDiseaseTree,
|
||||
searchEarNo,
|
||||
searchEarNumbers,
|
||||
// searchTechnician, // 移除旧的远程搜索接口
|
||||
// searchHandler // 移除旧的远程搜索接口
|
||||
} from "@/api/sheep_death/death"
|
||||
import { getUserByPost } from '@/api/common/user' // 新增引入
|
||||
|
||||
import { ref, computed, nextTick } from 'vue'
|
||||
import { ArrowUp, ArrowDown, Plus, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
// 响应式数据
|
||||
const pasteInput = ref('') // 批量粘贴输入框
|
||||
const earNumberOptions = ref([]) // 耳号下拉选项
|
||||
@@ -391,9 +468,6 @@ const earNumberLoading = ref(false) // 耳号加载状态
|
||||
const isExpanded = ref(false) // 控制耳号展开/折叠状态
|
||||
const defaultShowCount = 2 // 默认显示的耳号数量
|
||||
|
||||
// 新增:技术员选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
// 计算属性:控制显示的耳号列表
|
||||
const displayedEarNumbers = computed(() => {
|
||||
if (!queryParams.value.allEarNumbers || queryParams.value.allEarNumbers.length === 0) {
|
||||
@@ -407,6 +481,10 @@ const displayedEarNumbers = computed(() => {
|
||||
return queryParams.value.allEarNumbers.slice(0, defaultShowCount)
|
||||
}
|
||||
})
|
||||
|
||||
// 新增:技术员选项
|
||||
const technicalOptions = ref([])
|
||||
|
||||
const {proxy} = getCurrentInstance()
|
||||
// 获取字典数据
|
||||
const { sys_sheep_type } = proxy.useDict("sys_sheep_type");
|
||||
@@ -483,56 +561,6 @@ function handlePaste(event) {
|
||||
})
|
||||
}
|
||||
|
||||
/** 处理粘贴内容提交 */
|
||||
function handlePasteSubmit() {
|
||||
if (!pasteInput.value || pasteInput.value.trim() === '') {
|
||||
return
|
||||
}
|
||||
|
||||
// 支持多种分隔符: 空格、换行、逗号、制表符
|
||||
const separators = /[\s,,\n\r\t]+/
|
||||
const earNumbers = pasteInput.value
|
||||
.trim()
|
||||
.split(separators)
|
||||
.filter(item => item.trim() !== '')
|
||||
.map(item => item.trim())
|
||||
|
||||
if (earNumbers.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// 去重并添加到已选列表
|
||||
const existingSet = new Set(queryParams.value.allEarNumbers || [])
|
||||
const newEarNumbers = []
|
||||
const duplicates = []
|
||||
|
||||
earNumbers.forEach(earNumber => {
|
||||
if (!existingSet.has(earNumber)) {
|
||||
newEarNumbers.push(earNumber)
|
||||
existingSet.add(earNumber)
|
||||
} else {
|
||||
duplicates.push(earNumber)
|
||||
}
|
||||
})
|
||||
|
||||
// 添加新耳号
|
||||
if (newEarNumbers.length > 0) {
|
||||
queryParams.value.allEarNumbers = [
|
||||
...(queryParams.value.allEarNumbers || []),
|
||||
...newEarNumbers
|
||||
]
|
||||
|
||||
const message = `成功添加 ${newEarNumbers.length} 个耳号,当前共 ${queryParams.value.allEarNumbers.length} 个` +
|
||||
(duplicates.length > 0 ? `,已忽略 ${duplicates.length} 个重复耳号` : '')
|
||||
|
||||
proxy.$modal.msgSuccess(message)
|
||||
} else if (duplicates.length > 0) {
|
||||
proxy.$modal.msgWarning(`所有耳号均已存在,当前共 ${queryParams.value.allEarNumbers.length} 个`)
|
||||
}
|
||||
|
||||
// 清空输入框
|
||||
pasteInput.value = ''
|
||||
}
|
||||
|
||||
/** 远程搜索耳号 */
|
||||
function searchEarNumber(query) {
|
||||
@@ -560,41 +588,13 @@ function searchEarNumber(query) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 耳号选择变化处理 */
|
||||
function handleEarNumberChange(value) {
|
||||
queryParams.value.allEarNumbers = [...new Set(value)]
|
||||
console.log(`已选择 ${queryParams.value.allEarNumbers.length} 个耳号:`, queryParams.value.allEarNumbers)
|
||||
}
|
||||
|
||||
/** 切换展开/收起状态 */
|
||||
function toggleExpand() {
|
||||
isExpanded.value = !isExpanded.value
|
||||
}
|
||||
|
||||
/** 移除单个耳号 */
|
||||
function handleRemoveEarNumber(tag) {
|
||||
const index = queryParams.value.allEarNumbers.indexOf(tag)
|
||||
if (index > -1) {
|
||||
queryParams.value.allEarNumbers.splice(index, 1)
|
||||
proxy.$modal.msgSuccess('已移除该耳号')
|
||||
}
|
||||
|
||||
// 如果删除后剩余<=2个,自动收起
|
||||
if (queryParams.value.allEarNumbers.length <= defaultShowCount) {
|
||||
isExpanded.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 清空所有耳号 */
|
||||
function clearAllEarNumbers() {
|
||||
proxy.$modal.confirm('确定要清空所有已选择的耳号吗?').then(() => {
|
||||
queryParams.value.allEarNumbers = []
|
||||
pasteInput.value = ''
|
||||
earNumberOptions.value = []
|
||||
isExpanded.value = false // 重置展开状态
|
||||
proxy.$modal.msgSuccess('已清空所有耳号')
|
||||
}).catch(() => {})
|
||||
}
|
||||
/** 查询羊只死淘记录列表 */
|
||||
function getList() {
|
||||
loading.value = true
|
||||
@@ -711,6 +711,9 @@ function resetQuery() {
|
||||
queryParams.value.handlerList = []
|
||||
queryParams.value.workGroupList = []
|
||||
queryParams.value.deathDateRange = []
|
||||
queryParams.value.allEarNumbers = [] // ✅ 添加这一行
|
||||
earNumberOptions.value = [] // ✅ 添加这一行
|
||||
isExpanded.value = false // ✅ 添加这一行
|
||||
|
||||
proxy.resetForm("queryRef")
|
||||
handleQuery()
|
||||
@@ -792,6 +795,93 @@ function handleExport() {
|
||||
proxy.download('sheep_death/death/export', params, `death_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 处理粘贴内容提交 */
|
||||
function handlePasteSubmit() {
|
||||
if (!pasteInput.value || pasteInput.value.trim() === '') {
|
||||
return
|
||||
}
|
||||
|
||||
// 支持多种分隔符: 空格、换行、逗号、制表符
|
||||
const separators = /[\s,,\n\r\t]+/
|
||||
const earNumbers = pasteInput.value
|
||||
.trim()
|
||||
.split(separators)
|
||||
.filter(item => item.trim() !== '')
|
||||
.map(item => item.trim())
|
||||
|
||||
if (earNumbers.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// 去重并添加到已选列表
|
||||
const existingSet = new Set(queryParams.value.allEarNumbers || [])
|
||||
const newEarNumbers = []
|
||||
const duplicates = []
|
||||
|
||||
earNumbers.forEach(earNumber => {
|
||||
if (!existingSet.has(earNumber)) {
|
||||
newEarNumbers.push(earNumber)
|
||||
existingSet.add(earNumber)
|
||||
} else {
|
||||
duplicates.push(earNumber)
|
||||
}
|
||||
})
|
||||
|
||||
// 添加新耳号
|
||||
if (newEarNumbers.length > 0) {
|
||||
queryParams.value.allEarNumbers = [
|
||||
...(queryParams.value.allEarNumbers || []),
|
||||
...newEarNumbers
|
||||
]
|
||||
|
||||
const message = `成功添加 ${newEarNumbers.length} 个耳号,当前共 ${queryParams.value.allEarNumbers.length} 个` +
|
||||
(duplicates.length > 0 ? `,已忽略 ${duplicates.length} 个重复耳号` : '')
|
||||
|
||||
proxy.$modal.msgSuccess(message)
|
||||
} else if (duplicates.length > 0) {
|
||||
proxy.$modal.msgWarning(`所有耳号均已存在,当前共 ${queryParams.value.allEarNumbers.length} 个`)
|
||||
}
|
||||
|
||||
// 清空输入框
|
||||
pasteInput.value = ''
|
||||
}
|
||||
|
||||
|
||||
/** 耳号选择变化处理 */
|
||||
function handleEarNumberChange(value) {
|
||||
queryParams.value.allEarNumbers = [...new Set(value)]
|
||||
console.log(`已选择 ${queryParams.value.allEarNumbers.length} 个耳号:`, queryParams.value.allEarNumbers)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 移除单个耳号 */
|
||||
function handleRemoveEarNumber(tag) {
|
||||
const index = queryParams.value.allEarNumbers.indexOf(tag)
|
||||
if (index > -1) {
|
||||
queryParams.value.allEarNumbers.splice(index, 1)
|
||||
proxy.$modal.msgSuccess('已移除该耳号')
|
||||
}
|
||||
|
||||
// 如果删除后剩余<=2个,自动收起
|
||||
if (queryParams.value.allEarNumbers.length <= defaultShowCount) {
|
||||
isExpanded.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 清空所有耳号 */
|
||||
function clearAllEarNumbers() {
|
||||
proxy.$modal.confirm('确定要清空所有已选择的耳号吗?').then(() => {
|
||||
queryParams.value.allEarNumbers = []
|
||||
pasteInput.value = ''
|
||||
earNumberOptions.value = []
|
||||
isExpanded.value = false // 重置展开状态
|
||||
proxy.$modal.msgSuccess('已清空所有耳号')
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// 初始化
|
||||
getDiseaseTreeData()
|
||||
getList()
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="inList" @selection-change="handleSelectionChange">
|
||||
<el-table v-loading="loading" height="1000px" :data="inList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" prop="stockInCode" />
|
||||
<el-table-column label="单据日期" align="center" prop="docDate" />
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 物资管理记录导入对话框 -->
|
||||
<el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
|
||||
<el-dialog :title="upload.title" height="1000px" v-model="upload.open" width="400px" append-to-body>
|
||||
<el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
|
||||
:action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<el-input v-model="queryParams.title" placeholder="关键词" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="执行部门" prop="department">
|
||||
<el-input v-model="queryParams.department" placeholder="请选择" clearable style="width: 140px" />
|
||||
<el-select v-model="queryParams.department" placeholder="请选择执行部门" clearable filterable style="width: 200px">
|
||||
<el-option v-for="item in departmentOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="执行人" prop="executorIds">
|
||||
<el-input v-model="queryParams.executorIds" placeholder="用户 ID" clearable />
|
||||
@@ -176,11 +178,11 @@
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="执行部门" prop="department">
|
||||
<input v-model="form.department" placeholder="请输入执行部门" />
|
||||
<!-- <el-select v-model="form.department" placeholder="请选择" style="width: 100%">
|
||||
<el-option label="免疫组" value="免疫组" />
|
||||
<el-option label="饲喂组" value="饲喂组" />
|
||||
</el-select> -->
|
||||
<el-select v-model="form.department" placeholder="请选择执行部门" clearable filterable
|
||||
style="width: 200px">
|
||||
<el-option v-for="item in departmentOptions" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@@ -373,6 +375,13 @@ import {
|
||||
import Editor from '@/components/Editor/index.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import request from '@/utils/request'
|
||||
import { getPostTeam } from '@/api/common/user'
|
||||
|
||||
|
||||
// 部门选项
|
||||
const departmentOptions = ref([])
|
||||
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
/* -------------------------------------------------
|
||||
@@ -452,6 +461,26 @@ function genOrderNo(type) {
|
||||
return `${prefix}-${dateStr}`
|
||||
}
|
||||
|
||||
// 获取部门列表并映射为下拉选项
|
||||
const loadDepartmentOptions = async () => {
|
||||
try {
|
||||
const { data } = await getPostTeam()
|
||||
if (!Array.isArray(data)) {
|
||||
departmentOptions.value = []
|
||||
return
|
||||
}
|
||||
// Post实体类: postId -> value, postName -> label
|
||||
departmentOptions.value = data.map(item => ({
|
||||
value: item.postId,
|
||||
label: item.postName
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('获取部门列表失败', error)
|
||||
departmentOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
* 羊舍 & 耳号 功能函数
|
||||
* ------------------------------------------------- */
|
||||
@@ -652,6 +681,7 @@ function handleDetail(row) {
|
||||
|
||||
/* 初始加载 */
|
||||
getList()
|
||||
loadDepartmentOptions()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
import path from 'path'
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import createVitePlugins from './vite/plugins'
|
||||
|
||||
import { execSync } from 'node:child_process'
|
||||
const baseUrl = 'http://127.0.0.1:8080' // 后端接口
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode, command }) => {
|
||||
const env = loadEnv(mode, process.cwd())
|
||||
const { VITE_APP_ENV } = env
|
||||
|
||||
|
||||
let commitId = 'unknown'
|
||||
|
||||
try {
|
||||
commitId = execSync('git rev-parse --short HEAD')
|
||||
.toString()
|
||||
.trim()
|
||||
} catch (e) {
|
||||
console.log('git commit not found')
|
||||
}
|
||||
|
||||
const buildTime = new Date().toISOString()
|
||||
|
||||
return {
|
||||
// 部署生产环境和开发环境下的URL。
|
||||
// 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
|
||||
@@ -75,6 +89,10 @@ export default defineConfig(({ mode, command }) => {
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
define: {
|
||||
__BUILD_TIME__: JSON.stringify(buildTime),
|
||||
__COMMIT_ID__: JSON.stringify(commitId)
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user