Files
zhyc-sheep-ui/src/views/dairyProducts/sheepMilkAnalysis/index.vue

320 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="app-container">
<el-form :inline="true" :model="queryParams" ref="queryRef" class="filter-form">
<el-form-item label="耳号" prop="allEarNumbers">
<el-select
v-model="queryParams.allEarNumbers"
multiple
filterable
remote
reserve-keyword
placeholder="输入耳号搜索"
:remote-method="searchEarNumber"
:loading="earNumberLoading"
allow-create
default-first-option
style="width: 300px"
@change="handleEarNumberChange"
>
<el-option
v-for="item in earNumberOptions"
:key="item"
:label="item"
:value="item"
/>
</el-select>
<el-button
type="text"
@click="clearEarNumbers"
v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0"
style="margin-left: 10px"
>
清空
</el-button>
</el-form-item>
<el-form-item label="筛选天数">
<el-input-number v-model="queryParams.screenDays" :min="1" placeholder="请输入天数" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<div v-if="queryParams.allEarNumbers && queryParams.allEarNumbers.length > 0" class="selected-ear-numbers">
<span style="margin-right: 10px; color: #606266;">已选择耳号</span>
<el-tag
v-for="earNumber in queryParams.allEarNumbers"
:key="earNumber"
closable
@close="removeEarNumber(earNumber)"
style="margin-right: 8px;"
>
{{ earNumber }}
</el-tag>
</div>
<div class="button-group">
<el-popover placement="bottom" width="400" trigger="click">
<el-checkbox-group v-model="selectedFields" class="checkbox-columns">
<el-checkbox v-for="col in allColumns" :key="col.prop" :value="col.prop">{{ col.label }}</el-checkbox>
</el-checkbox-group>
<template #reference>
<el-button type="info" icon="Menu">展示列</el-button>
</template>
</el-popover>
<el-button type="success" icon="Download" @click="handleExport">导出</el-button>
</div>
<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"
:total="total"
:current-page="queryParams.pageNum"
:page-size="queryParams.pageSize"
@current-change="handlePageChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[20, 50, 100, 200, 500, 1000, 2000]"
/>
</div>
</template>
<script>
// 修改处:导入 searchEarNumbers
import { listSheepMilkAnalysis, searchEarNumbers } from "@/api/dairyProducts/sheepMilkAnalysis/sheepMilkAnalysis.js";
import { format } from 'date-fns';
import * as XLSX from 'xlsx'; // 导入xlsx库
export default {
name: "SheepMilkAnalysis",
data() {
return {
loading: false,
total: 0,
list: [],
// 修改处:新增耳号搜索相关状态
earNumberOptions: [],
earNumberLoading: false,
queryParams: {
pageNum: 1,
pageSize: 20,
allEarNumbers: [], // 修改:改为数组
screenDays: 100
},
selectedFields: [],
allColumns: [
{ label: "耳号", prop: "manageEarTag" },
{ label: "品种", prop: "variety" },
{ label: "挤奶开始时间", prop: "milkingStartTime", formatter: row => row.milkingStartTime ? format(new Date(row.milkingStartTime),'yyyy-MM-dd') : '' },
{ label: "干奶时间", prop: "dryEndTime", formatter: row => row.dryEndTime ? format(new Date(row.dryEndTime),'yyyy-MM-dd') : '' },
{ label: "筛选天数", prop: "screenDays", sortable: true },
{ label: "挤奶天数", prop: "milkingDays", sortable: true },
{ label: "校正后最大胎次", prop: "maxParity", sortable: true },
{ label: "系统奶量之合计", prop: "sumSystemMilk", sortable: true },
{ label: "校正奶量之合计", prop: "sumCorrectedMilk", sortable: true },
{ label: "校正日平均奶量", prop: "avgCorrectedDaily", sortable: true },
{ label: "胎次1的总奶量", prop: "sumParity1Milk", sortable: true },
{ label: "胎次2的总奶量", prop: "sumParity2Milk", sortable: true },
{ label: "胎次3的总奶量", prop: "sumParity3Milk", sortable: true },
{ label: "胎次4的总奶量", prop: "sumParity4Milk", sortable: true },
{ label: "胎次1日平均", prop: "avgParity1Daily", sortable: true },
{ label: "胎次2日平均", prop: "avgParity2Daily", sortable: true },
{ label: "胎次3日平均", prop: "avgParity3Daily", sortable: true },
{ label: "胎次4日平均", prop: "avgParity4Daily", sortable: true },
{ label: "泌乳天数", prop: "lactationDays", sortable: true },
{ label: "过去7日均奶量", prop: "avgLast7Milk", sortable: true },
{ label: "校正过去7日均", prop: "avgLast7Corrected", sortable: true },
{ label: "过去14日均奶量", prop: "avgLast14Milk", sortable: true },
{ label: "过去30日均奶量", prop: "avgLast30Milk", sortable: true },
{ label: "羊只类别", prop: "sheepCategory" },
{ label: "生日", prop: "birthday", formatter: row => row.birthday ? format(new Date(row.birthday),'yyyy-MM-dd') : '' },
{ label: "当前胎次", prop: "parity", sortable: true },
{ label: "月龄", prop: "monthAge", sortable: true },
{ label: "当前体重", prop: "currentWeight", sortable: true },
{ label: "繁育状态", prop: "breedStatus" },
{ label: "父号", prop: "fatherManageTags" },
{ label: "母号", prop: "motherManageTags" },
{ label: "牧场", prop: "ranchName" },
{ label: "家系", prop: "family" },
{ label: "母亲挤奶天数", prop: "motherMilkingDays", sortable: true },
{ label: "母亲校正奶量之合计", prop: "motherSumCorrected", sortable: true },
{ label: "母亲校正后最大胎次", prop: "motherMaxParity", sortable: true },
{ label: "母亲校正日平均奶量", prop: "motherAvgCorrectedDaily", sortable: true }
]
};
},
created() {
this.selectedFields = this.allColumns.map(c => c.prop);
this.getList();
},
computed: {
visibleColumns() {
// 保持原有顺序
return this.allColumns.filter(col => this.selectedFields.includes(col.prop));
}
},
methods: {
// 修改处:新增耳号搜索与处理方法
/** 远程搜索耳号 */
searchEarNumber(query) {
if (query !== '') {
this.earNumberLoading = true
searchEarNumbers(query).then(response => {
this.earNumberOptions = response.data || []
this.earNumberLoading = false
}).catch(() => {
this.earNumberOptions = []
this.earNumberLoading = false
})
} else {
this.earNumberOptions = []
}
},
/** 耳号变更处理 */
handleEarNumberChange(value) {
// 可选:添加日志或额外逻辑
},
/** 清空所有耳号 */
clearEarNumbers() {
this.queryParams.allEarNumbers = []
},
/** 移除单个耳号 */
removeEarNumber(earNumber) {
const index = this.queryParams.allEarNumbers.indexOf(earNumber)
if (index > -1) {
this.queryParams.allEarNumbers.splice(index, 1)
}
},
getList() {
this.loading = true;
listSheepMilkAnalysis(this.queryParams).then(response => {
const res = response && response.data ? response.data : response;
this.list = res.rows || res;
this.total = res.total || (Array.isArray(this.list) ? this.list.length : 0);
this.loading = false;
}).catch(()=>{ this.loading = false; });
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 20,
allEarNumbers: [], // 修改:重置为空数组
screenDays: 100
};
this.earNumberOptions = []; // 修改:清空选项
this.selectedFields = this.allColumns.map(c => c.prop);
this.getList();
},
handlePageChange(pageNum) {
this.queryParams.pageNum = pageNum;
this.getList();
},
handleSizeChange(pageSize) {
this.queryParams.pageSize = pageSize;
this.getList();
},
// 前端导出方法
handleExport() {
// 准备导出数据
const exportData = this.list.map(item => {
const row = {};
this.visibleColumns.forEach(col => {
let value = item[col.prop];
// 处理日期格式化
if (col.formatter && typeof col.formatter === 'function') {
value = col.formatter(item);
} else if (value instanceof Date) {
value = format(new Date(value), 'yyyy-MM-dd');
}
row[col.label] = value;
});
return row;
});
// 创建工作簿和工作表
const worksheet = XLSX.utils.json_to_sheet(exportData);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "羊奶产量分析");
// 生成Excel文件并下载
XLSX.writeFile(workbook, "羊奶产量分析数据.xlsx");
this.$message.success('导出成功');
}
}
};
</script>
<style scoped>
.filter-form .el-form-item {
margin-right: 15px;
}
.button-group {
margin-bottom: 10px;
}
.checkbox-columns {
display: flex;
flex-wrap: wrap;
gap: 10px;
max-height: 300px;
overflow-y: auto;
}
/* 修改处:新增样式 */
.selected-ear-numbers {
margin-bottom: 16px;
padding: 10px;
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>