油漆实验室

This commit is contained in:
卢江海
2025-03-28 17:29:58 +08:00
parent 5ef7baa655
commit c90ed71ae5
4 changed files with 349 additions and 194 deletions

View File

@@ -1,7 +1,18 @@
<template>
<div class="app-container">
<!-- 搜索部分 -->
<el-form :model="searchForm" inline size="mini" label-width="80px">
<el-form-item label="日期类型">
<el-select
v-model="searchForm.dateType"
:style="{ width: inputWidth }"
placeholder="选择日期类型"
>
<el-option label="创建日期" value="1" />
<el-option label="填写日期" value="2" />
</el-select>
</el-form-item>
<el-form-item label="开始日期">
<el-date-picker
:style="{ width: inputWidth }"
@@ -38,6 +49,14 @@
:style="{ width: inputWidth }"
></el-input>
</el-form-item>
<!-- 新增工单号搜索 -->
<el-form-item label="工单号">
<el-input
v-model.trim="searchForm.workOrder"
placeholder="输入工单号"
:style="{ width: inputWidth }"
></el-input>
</el-form-item>
<br />
<el-form-item label=" ">
<el-button
@@ -121,19 +140,18 @@
:edit-render="{ autofocus: '.vxe-input--inner' }"
>
<template #default="{ row }">
<span v-if="row.dt && isValidDate(row.dt)">
<span v-if="isValidDate(row.dt)">
{{ formatDate(row.dt) }}
<!-- {{ row.dt }} -->
</span>
<span v-else>-</span>
<span v-else class="invalid-date">无效日期</span>
</template>
<template #edit="{ row }">
<vxe-textarea
:autosize="{ minRows: 4 }"
v-model="row.dt"
type="text"
></vxe-textarea>
<vxe-input v-model="row.dt" placeholder="请输入日期YYYY-MM-DD">
</vxe-input>
</template>
</vxe-column>
<vxe-column
field="workorder"
title="工单号"
@@ -448,6 +466,7 @@ export default {
],
},
searchForm: {
dateType: "1", // 默认选择创建日期
starttime: new Date(
new Date(new Date().toLocaleDateString()).getTime()
),
@@ -458,6 +477,7 @@ export default {
),
workorderid: null,
description: "",
workOrder: "", // 新增工单号字段
},
reportTypeOptions: [
{ label: "批量生产记录", value: 0 },
@@ -517,13 +537,44 @@ export default {
this.fetchData();
},
methods: {
isValidDate(date) {
return this.$dayjs(date).isValid();
},
// 修改后的校验方法
isValidDate(dateTimeStr) {
if (!dateTimeStr) {
return false; // 如果为空,直接返回 false
}
// 允许日期时间格式,提取日期部分
const datePart = dateTimeStr.split(" ")[0]; // 分离日期部分
const timePart = dateTimeStr.split(" ")[1] || ""; // 可选时间校验
formatDate(date) {
return this.$dayjs(date).format("YYYY-MM-DD HH:mm:ss");
},
// 校验日期部分格式
const dateFormatRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
if (!dateFormatRegex.test(datePart)) return false;
// 处理日期部分
const parts = datePart.split("-").map((part) => part.padStart(2, "0"));
const year = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10);
const day = parseInt(parts[2], 10);
// 创建日期对象使用UTC避免时区问题
const dateObj = new Date(Date.UTC(year, month - 1, day));
const isValidDate =
dateObj.getUTCFullYear() === year &&
dateObj.getUTCMonth() === month - 1 &&
dateObj.getUTCDate() === day;
// 验证时间范围(>=2024-01-01
const minDate = new Date(Date.UTC(2024, 0, 1));
return isValidDate && dateObj >= minDate;
},
// 修改formatDate方法
formatDate(date) {
if (!date) return "-";
return this.$dayjs(date).isValid()
? this.$dayjs(date).format("YYYY-MM-DD HH:mm:ss")
: "-";
},
handleEditActived({ row }) {
if (!this.modifiedRows[row.id]) {
// 深拷贝原始数据
@@ -531,27 +582,25 @@ export default {
}
},
handleEditClosed({ row }) {
handleEditClosed({ row, column }) {
if (column.property === "dt" && !this.isValidDate(row.dt)) {
this.$message.error("日期格式无效,请按日期格式(年-月-日)填写");
row.dt = "";
}
const original = this.modifiedRows[row.id];
if (original) {
// 深度比较对象差异
const changed = Object.keys(original).some((key) => {
// 特殊处理日期类型
if (key === "dt") {
return (
this.$dayjs(original[key]).format() !==
this.$dayjs(row[key]).format()
);
return original[key] !== row[key];
}
return original[key] !== row[key];
});
if (!changed) {
this.$delete(this.modifiedRows, row.id);
}
}
},
async saveAllChanges() {
if (Object.keys(this.modifiedRows).length === 0) {
this.$message.warning("没有需要保存的修改");
@@ -595,6 +644,10 @@ export default {
// 生成6条更新记录即使部分未修改
Array.from({ length: 6 }).forEach((_, i) => {
const row = groupRows[i] || {};
if (group.baseRow == undefined) {
throw new Error("需要保存的数据不在当前页");
}
updateList.push({
id: row.id,
plIdGroup: row.idGroup,
@@ -628,7 +681,6 @@ export default {
});
});
});
const { code, data } = await UpdateBatchlist(updateList);
if (code === 200) {
this.$message.success(`成功保存${data}条记录`);
@@ -682,6 +734,7 @@ export default {
endtime: this.$dayjs(this.searchForm.endtime).format(
"YYYY-MM-DD HH:mm:ss"
),
workOrder: this.searchForm.workOrder,
};
const { code, data } = await GetBatchlist(query);
@@ -964,4 +1017,5 @@ export default {
};
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
</style>

View File

@@ -398,89 +398,92 @@ export default {
}
}
},
async saveAllChanges() {
if (Object.keys(this.modifiedRows).length === 0) {
this.$message.warning("没有需要保存的修改");
return;
}
try {
// 创建分组映射
const groupMap = new Map();
// 遍历所有修改的行
Object.values(this.modifiedRows).forEach((row) => {
// 找到当前行在表格中的索引
const rowIndex = this.qualityStatistics.findIndex(
(r) => r.id === row.id
);
// 计算所属分组的起始索引每6行一组
const groupIndex = Math.floor(rowIndex / 6) * 6;
// 如果该组还未创建,初始化分组
if (!groupMap.has(groupIndex)) {
groupMap.set(groupIndex, {
baseRow: this.qualityStatistics[groupIndex],
modifiedRows: new Set(),
});
async saveAllChanges() {
if (Object.keys(this.modifiedRows).length === 0) {
this.$message.warning("没有需要保存的修改");
return;
}
// 将修改行添加到对应分组
const group = groupMap.get(groupIndex);
group.modifiedRows.add(rowIndex % 6); // 记录组内修改的位置
});
try {
// 创建分组映射
const groupMap = new Map();
// 构建最终更新数据
const updateList = [];
groupMap.forEach((group, groupIndex) => {
const groupRows = this.qualityStatistics.slice(
groupIndex,
groupIndex + 6
);
// 遍历所有修改的行
Object.values(this.modifiedRows).forEach((row) => {
// 找到当前行在表格中的索引
const rowIndex = this.qualityStatistics.findIndex(
(r) => r.id === row.id
);
// 计算所属分组的起始索引每6行一组
const groupIndex = Math.floor(rowIndex / 6) * 6;
// 生成6条更新记录即使部分未修改
Array.from({ length: 6 }).forEach((_, i) => {
const row = groupRows[i] || {};
updateList.push({
id: row.id,
plIdGroup: row.idGroup,
description: group.baseRow.description,
plCode: group.baseRow.code,
plPci: group.baseRow.pci,
plValue01: row.value01,
plValue02: row.value02,
plValue03: row.value03,
plValue04: row.value04,
plValue05: row.value05,
plValue06: group.baseRow.value06,
plValue07: group.baseRow.value07,
plValue08: group.baseRow.value08,
plValue09: row.value09,
plValue10: row.value10,
plValue11: row.value11,
plCreatedBy: row.createdBy,
plCreatedTime: row.createdTime,
plUpdatedBy: row.updatedBy,
plUpdatedTime: row.updatedTime,
// 如果该组还未创建,初始化分组
if (!groupMap.has(groupIndex)) {
groupMap.set(groupIndex, {
baseRow: this.qualityStatistics[groupIndex],
modifiedRows: new Set(),
});
}
// 将修改行添加到对应分组
const group = groupMap.get(groupIndex);
group.modifiedRows.add(rowIndex % 6); // 记录组内修改的位置
});
});
});
const { code, data } = await UpdateRawMateriallist(updateList);
if (code === 200) {
this.$message.success(`成功保存${data}条记录`);
this.modifiedRows = {};
await this.fetchData();
// 保持合并单元格状态
this.mergeTableRows(6);
}
} catch (error) {
console.error("保存失败:", error);
this.$message.error(
"保存失败: " + (error.response?.data?.message || error.message)
);
}
},
// 构建最终更新数据
const updateList = [];
groupMap.forEach((group, groupIndex) => {
const groupRows = this.qualityStatistics.slice(
groupIndex,
groupIndex + 6
);
// 生成6条更新记录即使部分未修改
Array.from({ length: 6 }).forEach((_, i) => {
const row = groupRows[i] || {};
if (group.baseRow == undefined) {
throw new Error("需要保存的数据不在当前页");
}
updateList.push({
id: row.id,
plIdGroup: row.idGroup,
description: group.baseRow.description,
plCode: group.baseRow.code,
plPci: group.baseRow.pci,
plValue01: row.value01,
plValue02: row.value02,
plValue03: row.value03,
plValue04: row.value04,
plValue05: row.value05,
plValue06: group.baseRow.value06,
plValue07: group.baseRow.value07,
plValue08: group.baseRow.value08,
plValue09: row.value09,
plValue10: row.value10,
plValue11: row.value11,
plCreatedBy: row.createdBy,
plCreatedTime: row.createdTime,
plUpdatedBy: row.updatedBy,
plUpdatedTime: row.updatedTime,
});
});
});
const { code, data } = await UpdateRawMateriallist(updateList);
if (code === 200) {
this.$message.success(`成功保存${data}条记录`);
this.modifiedRows = {};
await this.fetchData();
// 保持合并单元格状态
this.mergeTableRows(6);
}
} catch (error) {
console.error("保存失败:", error);
this.$message.error(
"保存失败: " + (error.response?.data?.message || error.message)
);
}
},
updateUser(value) {
console.log(value);
},
@@ -491,42 +494,46 @@ export default {
if (res.code === 200) this.fetchData();
});
},
async fetchData() {
try {
this.isLoading = true;
const query = {
startDate: this.$dayjs(this.searchForm.startDate).format('YYYY-MM-DDTHH:mm:ss'),
endDate: this.$dayjs(this.searchForm.endDate).format('YYYY-MM-DDTHH:mm:ss'),
batchNumber: this.searchForm.batchNumber || undefined,
colorCode: this.searchForm.colorCode || undefined,
productDescription: this.searchForm.productDescription || undefined,
pageNum: this.pagination.currentPage,
pageSize: this.pagination.pageSize
};
async fetchData() {
try {
this.isLoading = true;
const { code, data } = await GetRawMateriallist(query);
if (code === 200) {
this.qualityStatistics = data.item1.map(item => ({
...item,
dt: this.$dayjs(item.dt).isValid()
? this.$dayjs(item.dt).format('YYYY-MM-DD HH:mm:ss')
: null
}));
const query = {
startDate: this.$dayjs(this.searchForm.startDate).format(
"YYYY-MM-DDTHH:mm:ss"
),
endDate: this.$dayjs(this.searchForm.endDate).format(
"YYYY-MM-DDTHH:mm:ss"
),
batchNumber: this.searchForm.batchNumber || undefined,
colorCode: this.searchForm.colorCode || undefined,
productDescription: this.searchForm.productDescription || undefined,
pageNum: this.pagination.currentPage,
pageSize: this.pagination.pageSize,
};
this.pagination.total = data.item2;
this.realTotal = Math.ceil(data.item2 / 5); // 根据实际分组调整
this.$nextTick(() => this.mergeTableRows(5)); // 根据实际分组调整
}
} catch (error) {
console.error("数据加载失败:", error);
this.$message.error(
"数据加载失败: " + (error.response?.data?.message || error.message)
);
} finally {
this.isLoading = false;
}
},
const { code, data } = await GetRawMateriallist(query);
if (code === 200) {
this.qualityStatistics = data.item1.map((item) => ({
...item,
dt: this.$dayjs(item.dt).isValid()
? this.$dayjs(item.dt).format("YYYY-MM-DD HH:mm:ss")
: null,
}));
this.pagination.total = data.item2;
this.realTotal = Math.ceil(data.item2 / 5); // 根据实际分组调整
this.$nextTick(() => this.mergeTableRows(5)); // 根据实际分组调整
}
} catch (error) {
console.error("数据加载失败:", error);
this.$message.error(
"数据加载失败: " + (error.response?.data?.message || error.message)
);
} finally {
this.isLoading = false;
}
},
// fetchData() {
// this.isLoading = true;
// setTimeout(() => (this.isLoading = false), 30000);

View File

@@ -3,6 +3,16 @@
<!-- 搜索部分 -->
<div>
<el-form :model="search" inline size="mini" label-width="80px">
<el-form-item label="日期类型">
<el-select
v-model="search.dateType"
:style="{ width: inputWidth }"
placeholder="选择日期类型"
>
<el-option label="创建日期" value="1" />
<el-option label="填写日期" value="2" />
</el-select>
</el-form-item>
<el-form-item label="开始日期">
<el-date-picker
:style="{ width: inputWidth }"
@@ -111,7 +121,7 @@
@edit-actived="handleEditActived"
@edit-closed="handleEditClosed"
>
<vxe-column
<!-- <vxe-column
field="dt"
title="日期"
width="140px"
@@ -124,7 +134,27 @@
type="text"
></vxe-textarea>
</template>
</vxe-column> -->
<vxe-column
field="dt"
title="日期"
width="140px"
:edit-render="{ autofocus: '.vxe-input--inner' }"
>
<template #default="{ row }">
<span v-if="isValidDate(row.dt)">
{{ formatDate(row.dt) }}
<!-- {{ row.dt }} -->
</span>
<span v-else class="invalid-date">无效日期</span>
</template>
<template #edit="{ row }">
<vxe-input v-model="row.dt" placeholder="请输入日期YYYY-MM-DD">
</vxe-input>
</template>
</vxe-column>
<vxe-column
field="code"
title="颜色/代号"
@@ -347,7 +377,7 @@ export default {
name: "DataCapture",
data() {
return {
modifiedRows: {}, // 改为响应式对象
modifiedRows: {}, // 改为响应式对象
inputWidth: "180px",
pickerOptions: {
shortcuts: [
@@ -376,6 +406,7 @@ export default {
],
},
search: {
dateType: "1", // 默认选择创建日期
starttime: new Date(
new Date(new Date().toLocaleDateString()).getTime()
),
@@ -436,7 +467,44 @@ export default {
this.fetchData();
},
methods: {
handleEditActived({ row }) {
isValidDate(dateTimeStr) {
if (!dateTimeStr) {
return false; // 如果为空,直接返回 false
}
// 允许日期时间格式,提取日期部分
const datePart = dateTimeStr.split(" ")[0]; // 分离日期部分
const timePart = dateTimeStr.split(" ")[1] || ""; // 可选时间校验
// 校验日期部分格式
const dateFormatRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
if (!dateFormatRegex.test(datePart)) return false;
// 处理日期部分
const parts = datePart.split("-").map((part) => part.padStart(2, "0"));
const year = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10);
const day = parseInt(parts[2], 10);
// 创建日期对象使用UTC避免时区问题
const dateObj = new Date(Date.UTC(year, month - 1, day));
const isValidDate =
dateObj.getUTCFullYear() === year &&
dateObj.getUTCMonth() === month - 1 &&
dateObj.getUTCDate() === day;
// 验证时间范围(>=2024-01-01
const minDate = new Date(Date.UTC(2024, 0, 1));
return isValidDate && dateObj >= minDate;
},
// 修改formatDate方法
formatDate(date) {
if (!date) return "-";
return this.$dayjs(date).isValid()
? this.$dayjs(date).format("YYYY-MM-DD HH:mm:ss")
: "-";
},
handleEditActived({ row }) {
if (!this.modifiedRows[row.id]) {
// 深拷贝原始数据
this.$set(this.modifiedRows, row.id, JSON.parse(JSON.stringify(row)));
@@ -506,6 +574,9 @@ export default {
// 生成6条更新记录即使部分未修改
Array.from({ length: 6 }).forEach((_, i) => {
const row = groupRows[i] || {};
if (group.baseRow == undefined) {
throw new Error("需要保存的数据不在当前页");
}
updateList.push({
id: row.id,
plIdGroup: row.idGroup,
@@ -576,40 +647,47 @@ export default {
// }
// },
async fetchData() {
try {
this.isLoading = true;
// Properly format dates for the API
const query = {
starttime: this.$dayjs(this.search.starttime).format('YYYY-MM-DDTHH:mm:ss'),
endtime: this.$dayjs(this.search.endtime).format('YYYY-MM-DDTHH:mm:ss'),
workorderid: this.search.workorderid || undefined, // Send undefined instead of null
description: this.search.description || undefined,
pageNum: this.pagination.pageNum,
pageSize: this.pagination.pageSize
};
async fetchData() {
try {
this.isLoading = true;
const { code, data } = await GetTestlist(query);
if (code === 200) {
this.qualityStatisticsTable = data.item1.map(item => ({
...item,
dt: this.$dayjs(item.dt).isValid()
? this.$dayjs(item.dt).format('YYYY-MM-DD HH:mm:ss')
: null
}));
this.pagination.total = data.item2;
this.realTotal = Math.ceil(data.item2 / 6);
this.$nextTick(() => this.mergeTableRows(6));
}
} catch (error) {
console.error('数据加载失败:', error);
this.$message.error('数据加载失败: ' + (error.response?.data?.message || error.message));
} finally {
this.isLoading = false;
}
},
// Properly format dates for the API
const query = {
starttime: this.$dayjs(this.search.starttime).format(
"YYYY-MM-DDTHH:mm:ss"
),
endtime: this.$dayjs(this.search.endtime).format(
"YYYY-MM-DDTHH:mm:ss"
),
workorderid: this.search.workorderid || undefined, // Send undefined instead of null
description: this.search.description || undefined,
pageNum: this.pagination.pageNum,
pageSize: this.pagination.pageSize,
dateType:this.search.dateType
};
const { code, data } = await GetTestlist(query);
if (code === 200) {
this.qualityStatisticsTable = data.item1.map((item) => ({
...item,
dt: this.$dayjs(item.dt).isValid()
? this.$dayjs(item.dt).format("YYYY-MM-DD HH:mm:ss")
: null,
}));
this.pagination.total = data.item2;
this.realTotal = Math.ceil(data.item2 / 6);
this.$nextTick(() => this.mergeTableRows(6));
}
} catch (error) {
console.error("数据加载失败:", error);
this.$message.error(
"数据加载失败: " + (error.response?.data?.message || error.message)
);
} finally {
this.isLoading = false;
}
},
// fetchData() {
// this.isLoading = true;
// setTimeout(() => {
@@ -631,32 +709,44 @@ export default {
// }
// });
// },
// 优化后的合并单元格方法
mergeTableRows(rowsPerGroup) {
this.mergeCells = [];
const table = this.$refs.xTable;
if (!table) {
console.warn('表格引用未找到');
return;
}
// 优化后的合并单元格方法
mergeTableRows(rowsPerGroup) {
this.mergeCells = [];
const table = this.$refs.xTable;
if (!table) {
console.warn("表格引用未找到");
return;
}
const columns = table.getColumns().filter(col => col.visible);
// 定义需要合并的列字段
const mergeFields = ['dt', 'code', 'description', 'value06', 'value07', 'value08', 'value16'];
for (let i = 0; i < this.qualityStatisticsTable.length; i += rowsPerGroup) {
columns.forEach((col, colIndex) => {
if (mergeFields.includes(col.property)) {
this.mergeCells.push({
row: i,
col: colIndex,
rowspan: rowsPerGroup,
colspan: 1
const columns = table.getColumns().filter((col) => col.visible);
// 定义需要合并的列字段
const mergeFields = [
"dt",
"code",
"description",
"value06",
"value07",
"value08",
"value16",
];
for (
let i = 0;
i < this.qualityStatisticsTable.length;
i += rowsPerGroup
) {
columns.forEach((col, colIndex) => {
if (mergeFields.includes(col.property)) {
this.mergeCells.push({
row: i,
col: colIndex,
rowspan: rowsPerGroup,
colspan: 1,
});
}
});
}
});
}
},
},
showAddDialog() {
this.isAddDialogVisible = true;
},

View File

@@ -21,6 +21,9 @@
>
<el-form-item label="毛坯号" prop="blankNum">
<el-input v-model.trim="queryParams.blankNum" placeholder="请输入毛坯号" clearable />
</el-form-item>
<el-form-item label="产品描述" prop="description">
<el-input v-model.trim="queryParams.description" placeholder="请输入产品描述" clearable />
</el-form-item>
<el-form-item label="类别" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择类别" @change="handleQuery">
@@ -279,6 +282,7 @@ export default {
status: 1,
sort: undefined,
sortType: undefined,
description:null
},
// 弹出层标题
title: '',