Compare commits

...

2 Commits

7 changed files with 279 additions and 80 deletions

View File

@ -25,7 +25,7 @@
"echarts": "5.5.1",
"element-china-area-data": "^6.1.0",
"element-plus": "^2.7.6",
"file-saver": "2.0.5",
"file-saver": "^2.0.5",
"fuse.js": "6.6.2",
"js-beautify": "1.14.11",
"js-cookie": "3.0.5",
@ -37,7 +37,8 @@
"vue-cropper": "1.1.1",
"vue-router": "4.4.0",
"vuedraggable": "4.1.0",
"vuex": "^4.0.2"
"vuex": "^4.0.2",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "5.0.5",

View File

@ -1,4 +1,3 @@
// src/api/dairyProducts/sheepMilkAnalysis/sheepMilkAnalysis.js
import request from '@/utils/request'
// 查询羊奶产量分析列表(分页 + 条件)
@ -16,14 +15,4 @@ export function getSheepMilkAnalysis(sheepId) {
url: '/dairyProducts/sheepMilkAnalysis/' + sheepId,
method: 'get'
})
}
// 导出羊奶产量分析 Excel
export function exportSheepMilkAnalysis(query) {
return request({
url: '/dairyProducts/sheepMilkAnalysis/export',
method: 'get',
params: query,
responseType: 'blob' // 返回二进制流
})
}
}

View File

@ -291,6 +291,9 @@
import { ref, reactive, onMounted } from 'vue';
import { listFreshMilkTest, getFreshMilkTest, delFreshMilkTest, addFreshMilkTest, updateFreshMilkTest } from "@/api/dairyProducts/freshMilkTest/freshMilkTest.js";
import { ElMessage, ElMessageBox } from 'element-plus';
// xlsxfile-saver
import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
const freshMilkTestList = ref([]);
const open = ref(false);
@ -304,6 +307,27 @@ const title = ref("");
const columnShowDialogVisible = ref(false);
const freshMilkTestRef = ref(null);
//
const columnConfig = [
{ prop: 'source', label: '来源' },
{ prop: 'datetime', label: '检测日期' },
{ prop: 'fat', label: '脂肪g/100g' },
{ prop: 'protein', label: '蛋白质g/100g' },
{ prop: 'nonFat', label: '非脂g/100g' },
{ prop: 'acidity', label: '酸度oT' },
{ prop: 'bacterialColony1', label: '菌落总数1' },
{ prop: 'bacterialColony2', label: '菌落总数2' },
{ prop: 'bacterialColony3', label: '菌落总数3' },
{ prop: 'bacterialColony4', label: '菌落总数4' },
{ prop: 'bacterialColony5', label: '菌落总数5' },
{ prop: 'coli', label: '大肠菌群(CFU/ml)' },
{ prop: 'lactoferrin', label: '乳铁蛋白(mg/L)' },
{ prop: 'ig', label: '免疫球蛋白(mg/L)' },
{ prop: 'commnet', label: '备注' },
{ prop: 'createBy', label: '创建人' },
{ prop: 'createTime', label: '创建时间' }
];
//
const selectedColumns = ref([
'source', 'datetime', 'fat', 'protein', 'nonFat', 'acidity',
@ -545,17 +569,42 @@ function handleDelete(row) {
});
}
/** 导出按钮操作 */
/** 导出按钮操作 - 前端实现 */
function handleExport() {
const params = new URLSearchParams();
for (const key in queryParams) {
if (queryParams[key] !== null && queryParams[key] !== undefined) {
params.append(key, queryParams[key]);
}
}
//
const visibleColumnsConfig = columnConfig.filter(
col => selectedColumns.value.includes(col.prop)
);
const url = `/freshMilkTest/freshMilkTest/export?${params.toString()}`;
window.location.href = url;
//
const exportData = freshMilkTestList.value.map(item => {
const rowData = {};
visibleColumnsConfig.forEach(col => {
//
if (col.prop === 'datetime') {
rowData[col.label] = formatDate(item[col.prop]);
} else if (col.prop === 'createTime') {
rowData[col.label] = formatDateTime(item[col.prop]);
} else {
rowData[col.label] = item[col.prop];
}
});
return rowData;
});
// 簿
const worksheet = XLSX.utils.json_to_sheet(exportData);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, '鲜奶检验记录');
// Excel
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
const blob = new Blob([excelBuffer], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
// 使file-saver
saveAs(blob, `鲜奶检验记录_${new Date().getTime()}.xlsx`);
}
//

View File

@ -1,16 +1,24 @@
<!-- index.vue (前端视图修改 resetQuery 以匹配正确字段) -->
<!-- index.vue (前端视图仅保留单日查询功能) -->
<template>
<div class="app-container">
<el-form ref="queryRef" :model="queryParams" inline label-width="80px">
<el-form-item label="日期范围">
<el-date-picker v-model="dateRange" type="daterange" range-separator=""
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" />
<!-- 单日查询 -->
<el-form-item label="查询日期">
<el-date-picker
v-model="queryDate"
type="date"
placeholder="选择查询日期"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
clearable />
</el-form-item>
<!-- 管理耳号变成输入框 -->
<!-- 管理耳号输入框 -->
<el-form-item label="管理耳号">
<el-input v-model="queryParams.manageEarNo" placeholder="请输入管理耳号" clearable />
</el-form-item>
<!-- 厂区下拉框数据源来自字典 da_ranch -->
<!-- 厂区下拉框 -->
<el-form-item label="厂区">
<el-select v-model="queryParams.factory" clearable placeholder="请选择">
<el-option
@ -20,13 +28,15 @@
:value="d.value" />
</el-select>
</el-form-item>
<!-- 班次只有 12 -->
<!-- 班次下拉框 -->
<el-form-item label="班次">
<el-select v-model="queryParams.classes" clearable placeholder="请选择">
<el-option :value="1" label="1" />
<el-option :value="2" label="2" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
@ -56,7 +66,7 @@
</el-table-column>
<el-table-column prop="correctedMilk" label="班次校正奶量" >
<template #default="{ row }">
{{ row.milk ? Number(row.milk).toFixed(2) : '-' }}
{{ row.correctedMilk ? Number(row.correctedMilk).toFixed(2) : '-' }}
</template>
</el-table-column>
</el-table>
@ -82,6 +92,7 @@ import { ref, reactive, onMounted } from 'vue'
import { listMilkProdclasses, importMilkProdclasses, exportMilkProdclasses } from '@/api/dairyProducts/milkProdclasses/milkProdclasses'
import { getToken } from '@/utils/auth'
import { getRanchList } from '@/api/dairyProducts/ranch/ranch.js'
import { ElMessage } from 'element-plus'
import { Upload, Download, UploadFilled } from '@element-plus/icons-vue';
const ranchOptions = ref([])
@ -100,25 +111,36 @@ onMounted(() => {
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
manageEarNo: '', //
factory: null,
classes: null
datetimeStart: null, //
datetimeEnd: null, //
manageEarNo: '', //
factory: null, //
classes: null //
})
const dateRange = ref([])
const tableData = ref([])
const total = ref(0)
const loading = ref(false)
const openImport = ref(false)
const queryDate = ref(null) //
const tableData = ref([]) //
const total = ref(0) //
const loading = ref(false) //
const openImport = ref(false) //
const uploadUrl = import.meta.env.VITE_APP_BASE_API + '/milkProdclasses/milkProdclasses/import';
const headers = { Authorization: 'Bearer ' + getToken() };
function getList() {
loading.value = true
const [start, end] = dateRange.value || []
//
if (queryDate.value) {
queryParams.datetimeStart = queryDate.value;
queryParams.datetimeEnd = queryDate.value;
} else {
queryParams.datetimeStart = null;
queryParams.datetimeEnd = null;
}
listMilkProdclasses({
datetimeStart: start,
datetimeEnd: end,
datetimeStart: queryParams.datetimeStart,
datetimeEnd: queryParams.datetimeEnd,
manageEarNo: queryParams.manageEarNo,
factory: queryParams.factory,
classes: queryParams.classes,
@ -135,8 +157,15 @@ function getList() {
}
function resetQuery() {
Object.assign(queryParams, { pageNum: 1, manageEarNo: '', factory: null, classes: null });
dateRange.value = [];
Object.assign(queryParams, {
pageNum: 1,
datetimeStart: null,
datetimeEnd: null,
manageEarNo: '',
factory: null,
classes: null
});
queryDate.value = null;
getList();
}
@ -148,22 +177,59 @@ function uploadSuccess(response) {
console.log('上传成功:', response);
openImport.value = false;
getList();
ElMessage.success('导入成功');
}
function uploadError(err) {
console.error('上传失败:', err);
ElMessage.error('导入失败');
}
function handleExport() {
const [start, end] = dateRange.value || [];
//
if (queryDate.value) {
queryParams.datetimeStart = queryDate.value;
queryParams.datetimeEnd = queryDate.value;
} else {
queryParams.datetimeStart = null;
queryParams.datetimeEnd = null;
}
exportMilkProdclasses({
datetimeStart: start,
datetimeEnd: end,
manageEarNo: queryParams.manageEarNo, //
datetimeStart: queryParams.datetimeStart,
datetimeEnd: queryParams.datetimeEnd,
manageEarNo: queryParams.manageEarNo,
factory: queryParams.factory,
classes: queryParams.classes
}).then(response => {
// Blob
const blob = new Blob([response], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
//
const downloadElement = document.createElement('a');
const href = window.URL.createObjectURL(blob);
downloadElement.href = href;
//
const now = new Date();
const dateStr = `${now.getFullYear()}${(now.getMonth()+1).toString().padStart(2, '0')}${now.getDate().toString().padStart(2, '0')}`;
downloadElement.download = `班次产奶数据_${dateStr}.xlsx`;
document.body.appendChild(downloadElement);
//
downloadElement.click();
// URL
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(href);
ElMessage.success('导出成功');
}).catch(error => {
console.error('导出失败:', error);
ElMessage.error('导出失败: ' + (error.message || '未知错误'));
});
}
getList();
</script>
</script>

View File

@ -236,6 +236,10 @@
</template>
<script setup name="RawMilkTest">
// xlsx
import * as XLSX from 'xlsx';
// file-saver
import { saveAs } from 'file-saver';
import { listRawMilkTest, getRawMilkTest, delRawMilkTest, addRawMilkTest, updateRawMilkTest } from "@/api/dairyProducts/rawMilkTest/rawMilkTest.js"
import { getCurrentInstance, ref, reactive, toRefs, onMounted } from 'vue'
import { parseTime } from '@/utils/ruoyi'
@ -496,9 +500,38 @@ function handleDelete(row) {
/** 导出按钮操作 */
function handleExport() {
proxy.download('rawMilkTest/rawMilkTest/export', {
...queryParams.value
}, `rawMilkTest_${new Date().getTime()}.xlsx`)
//
const visibleColumnsConfig = allColumns.value.filter(
col => visibleColumns.value[col.prop]
);
//
const exportData = rawMilkTestList.value.map(item => {
const rowData = {};
visibleColumnsConfig.forEach(col => {
//
if (col.prop === 'datetime' || col.prop === 'createTime') {
rowData[col.label] = parseTime(item[col.prop]);
} else {
rowData[col.label] = item[col.prop];
}
});
return rowData;
});
// 簿
const worksheet = XLSX.utils.json_to_sheet(exportData);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, '生乳检验记录');
// Excel
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
const blob = new Blob([excelBuffer], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
// 使file-saver
saveAs(blob, `生乳检验记录_${new Date().getTime()}.xlsx`);
}
onMounted(() => {

View File

@ -16,16 +16,16 @@
<!-- 操作按钮行 -->
<div class="button-group">
<el-button type="success" @click="handleExport">导出</el-button>
<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" :label="col.prop">{{ col.label }}</el-checkbox>
<!-- 使用 :value 替代 :label -->
<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">展示列</el-button>
</template>
</el-popover>
<el-button type="success" @click="handleExport">导出</el-button>
</div>
<!-- 数据表格 -->
@ -55,8 +55,9 @@
</template>
<script>
import { listSheepMilkAnalysis, exportSheepMilkAnalysis } from "@/api/dairyProducts/sheepMilkAnalysis/sheepMilkAnalysis.js";
import { listSheepMilkAnalysis } from "@/api/dairyProducts/sheepMilkAnalysis/sheepMilkAnalysis.js";
import { format } from 'date-fns';
import * as XLSX from 'xlsx'; // xlsx
export default {
name: "SheepMilkAnalysis",
@ -126,7 +127,6 @@ export default {
getList() {
this.loading = true;
listSheepMilkAnalysis(this.queryParams).then(response => {
// axios wrapper { data: { rows, total } }, { rows, total }
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);
@ -155,21 +155,33 @@ export default {
this.queryParams.pageSize = pageSize;
this.getList();
},
//
handleExport() {
exportSheepMilkAnalysis(this.queryParams).then(response => {
const data = response && response.data ? response.data : response;
const blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', '羊奶分析数据.xlsx');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}).catch(err => {
this.$message.error('导出失败,请检查后端是否正确返回文件流');
//
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('导出成功');
}
}
};
@ -189,4 +201,4 @@ export default {
max-height: 300px;
overflow-y: auto;
}
</style>
</style>

View File

@ -287,6 +287,9 @@
import { ref, reactive, onMounted } from 'vue';
import { listYogurtTest, getYogurtTest, delYogurtTest, addYogurtTest, updateYogurtTest } from "@/api/dairyProducts/yogurtTest/yogurtTest.js";
import { ElMessage, ElMessageBox } from 'element-plus';
// xlsxfile-saver
import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
//
const yogurtTestList = ref([]);
@ -301,6 +304,27 @@ const title = ref("");
const columnShowDialogVisible = ref(false);
const yogurtTestRef = ref(null);
//
const columnConfig = [
{ prop: 'source', label: '来源' },
{ prop: 'datetime', label: '检测日期' },
{ prop: 'fat', label: '脂肪g/100g' },
{ prop: 'protein', label: '蛋白质g/100g' },
{ prop: 'nonFat', label: '非脂g/100g' },
{ prop: 'acidity', label: '酸度oT' },
{ prop: 'bacterialColony1', label: '菌落总数1' },
{ prop: 'bacterialClony2', label: '菌落总数2' },
{ prop: 'bacterialClony3', label: '菌落总数3' },
{ prop: 'bacterialClony4', label: '菌落总数4' },
{ prop: 'bacterialClony5', label: '菌落总数5' },
{ prop: 'yeast', label: '酵母菌(CFU/g)' },
{ prop: 'mould', label: '霉菌(CFU/g)' },
{ prop: 'lacto', label: '乳酸菌(CFU/g)' },
{ prop: 'comment', label: '备注' },
{ prop: 'createBy', label: '创建人' },
{ prop: 'createTime', label: '创建时间' }
];
//
const selectedColumns = ref([
'source', 'datetime', 'fat', 'protein', 'nonFat', 'acidity',
@ -543,17 +567,42 @@ function handleDelete(row) {
});
}
/** 导出按钮操作 */
/** 导出按钮操作 - 前端实现 */
function handleExport() {
const params = new URLSearchParams();
for (const key in queryParams) {
if (queryParams[key] !== null && queryParams[key] !== undefined) {
params.append(key, queryParams[key]);
}
}
//
const visibleColumnsConfig = columnConfig.filter(
col => selectedColumns.value.includes(col.prop)
);
const url = `/yogurtTest/yogurtTest/export?${params.toString()}`;
window.location.href = url;
//
const exportData = yogurtTestList.value.map(item => {
const rowData = {};
visibleColumnsConfig.forEach(col => {
//
if (col.prop === 'datetime') {
rowData[col.label] = formatDate(item[col.prop]);
} else if (col.prop === 'createTime') {
rowData[col.label] = formatDateTime(item[col.prop]);
} else {
rowData[col.label] = item[col.prop];
}
});
return rowData;
});
// 簿
const worksheet = XLSX.utils.json_to_sheet(exportData);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, '酸奶检疫记录');
// Excel
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
const blob = new Blob([excelBuffer], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
// 使file-saver
saveAs(blob, `酸奶检疫记录_${new Date().getTime()}.xlsx`);
}
//