feat: 新增导出整车列表

dev
donghao 1 week ago
parent d364741783
commit 445ae91686

@ -144,7 +144,7 @@
### 1.2 请求参数
| 参数名 | 类型 | 是否必填 | 说明 | 示例值 |
|-----------------------|---------|----------|--------------------------|--------------|
| train_number | string | 否 | 车(精确/模糊查询) | "JZ20250301" |
| train_number | string | 否 | 车辆ID(精确/模糊查询) | "JZ20250301" |
| train_model | string | 否 | 车型 | "货车" |
| train_carriage_number | string | 否 | 车厢号(精确查询) | "C001" |
| alarm_type | string | 否 | 告警类型(如:倾斜、断裂) | "倾斜" |
@ -164,7 +164,7 @@
| ├─ total | int | 总记录数 |
| ├─ list | array | 撑杆监测列表 |
| └─ ├─ id | string | 唯一标识 |
| └─ ├─ carNo | string | 车 |
| └─ ├─ carNo | string | 车辆ID |
| └─ ├─ carType | string | 车型 |
| └─ ├─ carriageNo | string | 车厢号 |
| └─ ├─ warnType | string | 告警类型 |
@ -239,7 +239,7 @@
| message | string | 响应信息 |
| data | object | 数据体 |
| ├─ id | string | 监测数据 ID |
| ├─ carNo | string | 车 |
| ├─ carNo | string | 车辆ID |
| ├─ carType | string | 车型 |
| ├─ carriageNo | string | 车厢号 |
| ├─ warnType | string | 告警类型 |
@ -312,7 +312,7 @@
### 1.2 请求参数
| 参数名 | 类型 | 是否必填 | 说明 | 示例值 |
|-----------------------|---------|----------|--------------------------|--------------|
| train_number | string | 否 | 车(精确/模糊查询) | "JZ20250301" |
| train_number | string | 否 | 车辆ID(精确/模糊查询) | "JZ20250301" |
| train_model | string | 否 | 车型 | "货车" |
| train_carriage_number | string | 否 | 车厢号(精确查询) | "C001" |
| alarm_type | string | 否 | 告警类型(如:倾斜、断裂) | "倾斜" |
@ -333,7 +333,7 @@
| ├─ total | int | 总记录数 |
| ├─ list | array | 外观监测列表 |
| └─ ├─ id | string | 唯一标识 |
| └─ ├─ carNo | string | 车 |
| └─ ├─ carNo | string | 车辆ID |
| └─ ├─ carType | string | 车型 |
| └─ ├─ carriageNo | string | 车厢号 |
| └─ ├─ warnType | string | 告警类型 |
@ -410,7 +410,7 @@
| message | string | 响应信息 |
| data | object | 数据体 |
| ├─ id | string | 监测数据 ID |
| ├─ carNo | string | 车 |
| ├─ carNo | string | 车辆ID |
| ├─ carType | string | 车型 |
| ├─ carriageNo | string | 车厢号 |
| ├─ warnType | string | 告警类型 |

@ -21,7 +21,7 @@ const mockListData = Mock.mock({
// 生成 10 条数据,可以根据需要调整数量
"data|140": [
{
// 车,生成随机的 4 位字母和数字组合
// 车辆ID,生成随机的 4 位字母和数字组合
train_number: /[A-Z0-9]{10}/,
// 车型,从预定义的数组中随机选择一个
train_model: () => Mock.Random.pick(["轿车", "SUV", "客车", "货车"]),

@ -24,7 +24,7 @@ const mockListData = Mock.mock({
// 生成 10 条数据,可以根据需要调整数量
"data|140": [
{
// 车,生成随机的 4 位字母和数字组合
// 车辆ID,生成随机的 4 位字母和数字组合
train_number: /[A-Z0-9]{10}/,
// 车型,从预定义的数组中随机选择一个
train_model: () => Mock.Random.pick(["轿车", "SUV", "客车", "货车"]),

@ -0,0 +1,140 @@
<template>
<span>
报表下载
</span>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import ExcelJS from 'exceljs';
import { saveAs } from 'file-saver-es';
// ()
const listData = [
{
trainCode: 'T-20250508',
trainType: 'C54K',
occurrenceTime: 5785.67354,
alarmType: '车辆损坏',
faultType: '搭扣未扣',
},
];
// URL (URL)
const imageUrl = ref(''); // Replace with the actual image URL
const placeholderImageUrl = 'https://via.placeholder.com/150'; // Fallback
const convertImageToBase64 = async (url: string) => {
try {
const response = await fetch(url);
const blob = await response.blob();
return new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result as string);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
} catch (error) {
console.error('Error loading image:', error);
return null;
}
};
const saveToExcel = async () => {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet1');
// 1. ()
worksheet.getColumn('A').width = 15;
worksheet.getColumn('B').width = 15;
worksheet.getColumn('C').width = 15;
worksheet.getColumn('D').width = 10; // Smaller width for ''
worksheet.getColumn('E').width = 15;
worksheet.getColumn('F').width = 15;
worksheet.getColumn('G').width = 15;
worksheet.getColumn('H').width = 10;
worksheet.getColumn('I').width = 10;
// 2.
worksheet.getCell('A1').value = '进场时间';
worksheet.getCell('B1').value = '出场时间';
worksheet.getCell('A3').value = '车厢编号';
worksheet.getCell('C3').value = '1234567890'; // Example Value
// 3.
worksheet.getCell('C5').value = '列车编号';
worksheet.getCell('D5').value = '车型';
worksheet.getCell('E5').value = '发生时间';
worksheet.getCell('F5').value = '告警类型';
worksheet.getCell('G5').value = '故障类型';
// 4.
listData.forEach((item, index) => {
const row = index + 6; // 6
worksheet.getCell(`C${row}`).value = item.trainCode;
worksheet.getCell(`D${row}`).value = item.trainType;
worksheet.getCell(`E${row}`).value = item.occurrenceTime;
worksheet.getCell(`F${row}`).value = item.alarmType;
worksheet.getCell(`G${row}`).value = item.faultType;
});
// 5.
// Load the image (using a data URL or URL)
try {
if (imageUrl.value) {
const base64Image = await convertImageToBase64(imageUrl.value);
if (base64Image) {
const imageId = workbook.addImage({
base64: base64Image,
extension: 'png', // Adjust extension if needed (jpeg, etc.)
});
// Add the image to the worksheet
worksheet.addImage(imageId, {
tl: { col: 2, row: 8 }, // Top left corner of the image (C9 in Excel)
br: { col: 7, row: 25 }, // Bottom right corner of the image (H26 in Excel)
});
}
}
} catch (error) {
console.error('Error adding image:', error);
}
// 6. ""
worksheet.getCell('A17').value = '车身缺陷';
// 7. H
for (let i = 8; i <= 28; i++) {
const cell = worksheet.getCell(`H${i}`);
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'ADD8E6' }, // Light blue color
};
}
// 8. (Optional) Style the header rows
const headerRange = 'A1:G5'; // Adjust as needed
worksheet.getCell(headerRange).font = { bold: true };
worksheet.getCell(headerRange).alignment = { vertical: 'middle', horizontal: 'center' }; // Center align headers
// 9. Excel
const buffer = await workbook.xlsx.writeBuffer();
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), '车辆信息.xlsx');
};
onMounted(async () => {
// Pre-load the image (or use a placeholder if loading fails)
imageUrl.value = 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/No-Image-Placeholder.svg/1665px-No-Image-Placeholder.svg.png'
});
</script>

@ -0,0 +1,166 @@
import ExcelJS from "exceljs";
// import { saveAs } from 'file-saver-es';
// 模拟列表数据 (替换成你的真实数据)
export const useTrainSaveToExcel = (props) => {
const { arrive_at, data, leave_at } = props;
console.log("useTrainSaveToExcel_data", data);
const listData = [
{
trainCode: "T-20250508",
trainType: "C54K",
occurrenceTime: 5785.67354,
alarmType: "车辆损坏",
faultType: "搭扣未扣",
},
{
trainCode: "T-20250508",
trainType: "C54K",
occurrenceTime: 5785.67354,
alarmType: "车辆损坏",
faultType: "搭扣未扣",
},
{
trainCode: "T-20250508",
trainType: "C54K",
occurrenceTime: 5785.67354,
alarmType: "车辆损坏",
faultType: "搭扣未扣",
},
];
// 模拟图片 URL (替换成你的真实图片URL)
const imageUrl =
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg"; // Fallback
const convertImageToBase64 = async (url: string) => {
try {
const response = await fetch(url);
const blob = await response.blob();
return new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result as string);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
} catch (error) {
console.error("Error loading image:", error);
return null;
}
};
const saveToExcel = async () => {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet("Sheet1");
// 1. 设置列宽 (根据你的内容调整)
worksheet.getColumn("A").width = 15;
worksheet.getColumn("B").width = 15;
worksheet.getColumn("C").width = 15;
worksheet.getColumn("D").width = 10; // Smaller width for '车型'
worksheet.getColumn("E").width = 15;
worksheet.getColumn("F").width = 15;
worksheet.getColumn("G").width = 15;
worksheet.getColumn("H").width = 10;
worksheet.getColumn("I").width = 10;
// 2. 添加头部数据
worksheet.getCell("A1").value = "进场时间";
worksheet.getCell("B1").value = "出场时间";
worksheet.getCell("A3").value = "车厢编号";
worksheet.getCell("C3").value = "1234567890"; // Example Value
// 3. 添加表格头部
worksheet.getCell("C5").value = "列车编号";
worksheet.getCell("D5").value = "车型";
worksheet.getCell("E5").value = "发生时间";
worksheet.getCell("F5").value = "告警类型";
worksheet.getCell("G5").value = "故障类型";
const loadRemark = async (record) => {
try {
if (imageUrl) {
const base64Image = await convertImageToBase64(imageUrl);
if (base64Image) {
const imageId = workbook.addImage({
base64: base64Image,
extension: "png", // Adjust extension if needed (jpeg, etc.)
});
// Add the image to the worksheet
worksheet.addImage(imageId, {
tl: { col: 2, row: 8 }, // Top left corner of the image (C9 in Excel)
br: { col: 7, row: 25 }, // Bottom right corner of the image (H26 in Excel)
});
}
}
} catch (error) {
console.error("Error adding image:", error);
}
}
// 4. 填充表格数据
listData.forEach((item, index) => {
const row = index + 6; // 从第6行开始
worksheet.getCell(`C${row}`).value = item.trainCode;
worksheet.getCell(`D${row}`).value = item.trainType;
worksheet.getCell(`E${row}`).value = item.occurrenceTime;
worksheet.getCell(`F${row}`).value = item.alarmType;
worksheet.getCell(`G${row}`).value = item.faultType;
loadRemark(item);
});
// 5. 添加图片
// Load the image (using a data URL or URL)
// 6. 添加 "车身缺陷" 文本
worksheet.getCell("A17").value = "车身缺陷";
// 7. 设置 H 列的背景色
for (let i = 8; i <= 28; i++) {
const cell = worksheet.getCell(`H${i}`);
cell.fill = {
type: "pattern",
pattern: "solid",
fgColor: { argb: "ADD8E6" }, // Light blue color
};
}
// 8. (Optional) Style the header rows
const headerRanges = ["A1:G5", "B1:G5"]; // Adjust as needed
// const headerRange = "A1:G5, B8:G5"; // Adjust as needed
for (const headerRange of headerRanges) {
worksheet.getCell(headerRange).font = { bold: true };
worksheet.getCell(headerRange).alignment = {
vertical: "middle",
horizontal: "center",
}; // Center align headers
}
// 9. 下载 Excel 文件
const buffer = await workbook.xlsx.writeBuffer();
try {
const blob = new Blob([buffer], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "车辆信息.xlsx";
link.click();
URL.revokeObjectURL(url);
} catch (error) {
console.error("导出 Excel 文件时出错:", error);
}
// saveAs(
// new Blob([buffer], { type: "application/octet-stream" }),
// "车辆信息.xlsx"
// );
};
return {
saveToExcel,
};
};

@ -0,0 +1,392 @@
import ExcelJS from "exceljs";
interface TrainReportData {
train_id: string;
arrive_at: string;
leave_at: string | null;
train_data: { carriage_number: string }[];
appearance_data: {
carriage_number: string;
carriage_type: string;
occurrence_time: string;
warning_type: string;
fault_type: string;
defect_image: string;
}[];
}
const formatDateTime = (dateTimeStr: string) => {
const date = new Date(dateTimeStr);
return date.toLocaleString("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
});
};
// 使用您指定的图片URL
const DEFAULT_IMAGE_URL =
"https://img1.baidu.com/it/u=967792105,51180745&fm=253&fmt=auto?w=1200&h=800";
const convertImageToBase64 = async (url: string) => {
try {
const response = await fetch(url);
const blob = await response.blob();
return new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result as string);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
} catch (error) {
console.error("Error loading image:", error);
return null;
}
};
const getImageDimensions = (
url: string
): Promise<{ width: number; height: number }> => {
return new Promise((resolve) => {
const img = new Image();
const timer = setTimeout(() => {
resolve({ width: 80, height: 60 }); // 默认尺寸
}, 3000);
img.crossOrigin = "Anonymous";
img.onload = () => {
clearTimeout(timer);
resolve({ width: img.width, height: img.height });
};
img.onerror = () => {
clearTimeout(timer);
resolve({ width: 80, height: 60 });
};
img.src = url;
});
};
// 下载图片并转换为ArrayBuffer
const downloadImage = async (url: string): Promise<ExcelJS.Image | null> => {
try {
const finalUrl = url || DEFAULT_IMAGE_URL;
let response: Response;
try {
response = await fetch(finalUrl);
if (!response.ok) throw new Error("直接下载失败");
} catch (directError) {
// 尝试使用CORS代理
try {
const proxyUrl = `https://corsproxy.io/?${encodeURIComponent(
finalUrl
)}`;
response = await fetch(proxyUrl);
if (!response.ok) throw new Error("代理下载失败");
} catch (proxyError) {
console.error("图片下载失败:", proxyError);
return null;
}
}
const arrayBuffer = await response.arrayBuffer();
const extension = finalUrl.split(".").pop()?.toLowerCase() || "jpeg";
const { width, height } = await getImageDimensions(finalUrl);
// 计算缩放比例(保持宽高比)
const maxWidth = 80;
const maxHeight = 60;
const scale = Math.min(maxWidth / width, maxHeight / height, 1);
return {
buffer: arrayBuffer, // 直接使用ArrayBuffer
extension: extension === "png" ? "png" : "jpeg",
width: width * scale,
height: height * scale,
};
} catch (error) {
console.error("图片处理失败:", error);
return null;
}
};
// 像素转换为Excel的EMU单位 (Excel使用EMU作为度量单位)
const pixelsToEMU = (pixels: number) => Math.round(pixels * 9525);
export const exportTrainReport = async (data: TrainReportData) => {
const workbook = new ExcelJS.Workbook();
workbook.creator = "Railway Inspection System";
workbook.created = new Date();
// 1. 创建"整车信息"工作表 (无表头行)
const trainSheet = workbook.addWorksheet("整车信息");
trainSheet.getColumn(1).width = 20;
trainSheet.getColumn(2).width = 30;
// 直接添加数据行
const trainInfoData = [
{ key: "车头编号", value: data.train_id },
{ key: "进场时间", value: formatDateTime(data.arrive_at) },
{
key: "出场时间",
value: data.leave_at ? formatDateTime(data.leave_at) : "未出场",
},
{ key: "车厢列表", value: "" },
];
trainInfoData.forEach((info, index) => {
const row = index + 1;
trainSheet.getCell(`A${row}`).value = info.key;
trainSheet.getCell(`B${row}`).value = info.value;
// 设置第一列加粗
trainSheet.getCell(`A${row}`).font = { bold: true };
// 设置第二列加粗(除车厢列表行)
if (row < 4) {
trainSheet.getCell(`B${row}`).font = { bold: true };
}
});
// 添加车厢列表
const startRow = trainInfoData.length + 1;
data.train_data.forEach((carriage, index) => {
const row = startRow + index;
trainSheet.getCell(`A${row}`).value = `车厢 ${index + 1}`;
trainSheet.getCell(`B${row}`).value = carriage.carriage_number;
});
// 2. 创建"车身缺陷记录"工作表
const defectSheet = workbook.addWorksheet("车身缺陷记录");
// 修改列定义
defectSheet.columns = [
{ header: "车厢号", key: "carriage_number", width: 15 },
// { header: "车型", key: "carriage_type", width: 20 },
{ header: "发生时间", key: "occurrence_time", width: 20 },
{ header: "告警类型", key: "warning_type", width: 15 },
{ header: "缺陷类型", key: "fault_type", width: 15 },
{ header: "缺陷图片", key: "thumbnail", width: 15 }, // 缩略图列
// { header: "查看原图", key: "defect_image", width: 15 }, // 原图链接列
];
// 设置表头样式
defectSheet.getRow(1).eachCell((cell) => {
cell.font = { bold: true };
cell.fill = {
type: "pattern",
pattern: "solid",
fgColor: { argb: "FFDDEBF7" }, // 浅蓝色背景
};
cell.border = {
top: { style: "thin" },
left: { style: "thin" },
bottom: { style: "thin" },
right: { style: "thin" },
};
});
// 设置所有行高60像素≈45磅
defectSheet.properties.defaultRowHeight = 45;
// 添加所有缺陷记录
for (let i = 0; i < data.appearance_data.length; i++) {
const item = data.appearance_data[i];
const rowIndex = i + 2; // 从第二行开始(第一行是表头)
// 添加文本数据
defectSheet.addRow({
carriage_number: item.carriage_number,
carriage_type: item.carriage_type,
occurrence_time: formatDateTime(item.occurrence_time),
warning_type: item.warning_type,
fault_type: item.fault_type,
});
// 使用指定图片URL
const imageUrl = item.defect_image || DEFAULT_IMAGE_URL;
try {
// 下载图片
// const image = await downloadImage(imageUrl);
// console.log("图片下载成功", image);
const base64Image = await convertImageToBase64(imageUrl);
if (base64Image) {
const imageId = workbook.addImage({
base64: base64Image,
extension: "png", // Adjust extension if needed (jpeg, etc.)
});
// TODO : 调整图片大小和位置 (根据需要调整)
// // 计算缩放比例和显示尺寸
// const maxSize = 30; // 最大边长30像素
// const scale = Math.min(maxSize / image.width, maxSize / image.height);
// const displayWidth = image.width * scale;
// const displayHeight = image.height * scale;
// // 列宽(像素)和行高(像素)
// const colWidthPixels = 105; // 15字符 * 7
// const rowHeightPixels = 60; // 45磅 * (96/72) = 60像素
// // 计算偏移量(居中)
// const offsetXPixels = (colWidthPixels - displayWidth) / 2;
// const offsetYPixels = (rowHeightPixels - displayHeight) / 2;
// // 转换为EMU
// const offsetXEMU = pixelsToEMU(offsetXPixels);
// const offsetYEMU = pixelsToEMU(offsetYPixels);
// const widthEMU = pixelsToEMU(displayWidth);
// const heightEMU = pixelsToEMU(displayHeight);
defectSheet.addImage(imageId, {
tl: { col: defectSheet.columns.length - 1, row: rowIndex - 1 }, // F列是第5列0-based
// br: { col: 6, row: rowIndex },
ext: {
width: 80,
height: 45,
},
editAs: "oneCell",
});
}
} catch (error) {
console.error(`图片添加失败 (行 ${rowIndex}):`, error);
const errorCell = defectSheet.getCell(`E${rowIndex}`);
errorCell.value = "图片加载失败";
errorCell.font = {
color: { argb: "FFFF0000" }, // 红色
italic: true,
};
}
}
// 3. 生成Excel文件
const buffer = await workbook.xlsx.writeBuffer();
try {
const blob = new Blob([buffer], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "车辆信息.xlsx";
link.click();
URL.revokeObjectURL(url);
} catch (error) {
console.error("导出 Excel 文件时出错:", error);
}
};
// ... formatDateTime 函数保持不变 ...
export const useTrainSaveToExcel = (data) => {
// 模拟数据 (实际应用中应通过API获取)
const reportData = {
train_id: "DF4-1234",
arrive_at: "2023-06-15 08:30:00",
leave_at: "2023-06-15 16:45:22",
train_data: [
{ carriage_number: "CK-1001" },
{ carriage_number: "CK-1002" },
{ carriage_number: "CK-1003" },
],
appearance_data: [
{
carriage_number: "CK-1001",
carriage_type: "C80型运煤敞车",
occurrence_time: "2023-06-15 09:15:34",
warning_type: "AI智能识别告警",
fault_type: "车体变形",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1002",
carriage_type: "P70型棚车",
occurrence_time: "2023-06-15 10:22:18",
warning_type: "人工巡检报告",
fault_type: "油漆剥落",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1001",
carriage_type: "C80型运煤敞车",
occurrence_time: "2023-06-15 09:15:34",
warning_type: "AI智能识别告警",
fault_type: "车体变形",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1002",
carriage_type: "P70型棚车",
occurrence_time: "2023-06-15 10:22:18",
warning_type: "人工巡检报告",
fault_type: "油漆剥落",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1001",
carriage_type: "C80型运煤敞车",
occurrence_time: "2023-06-15 09:15:34",
warning_type: "AI智能识别告警",
fault_type: "车体变形",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1002",
carriage_type: "P70型棚车",
occurrence_time: "2023-06-15 10:22:18",
warning_type: "人工巡检报告",
fault_type: "油漆剥落",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1001",
carriage_type: "C80型运煤敞车",
occurrence_time: "2023-06-15 09:15:34",
warning_type: "AI智能识别告警",
fault_type: "车体变形",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1002",
carriage_type: "P70型棚车",
occurrence_time: "2023-06-15 10:22:18",
warning_type: "人工巡检报告",
fault_type: "油漆剥落",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1001",
carriage_type: "C80型运煤敞车",
occurrence_time: "2023-06-15 09:15:34",
warning_type: "AI智能识别告警",
fault_type: "车体变形",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
{
carriage_number: "CK-1002",
carriage_type: "P70型棚车",
occurrence_time: "2023-06-15 10:22:18",
warning_type: "人工巡检报告",
fault_type: "油漆剥落",
defect_image:
"http://192.168.10.14:8123/sftp/2025-07-01/20250701_131010.jpg",
},
],
};
return {
saveToExcel: () => exportTrainReport(reportData),
};
};

@ -208,6 +208,7 @@
//
.fg-footer-charts {
display: flex;
justify-content: space-between;
margin-top: 16px;
gap: 16px;
width: 100%;
@ -217,12 +218,13 @@
background: url("@/assets/common/long_chart_bg.png") no-repeat center center;
background-size: 100% 100%;
// background-color: red;
&:nth-child(1) {
width: calc(50% - 50px - 16px);
width: calc(50% - 50px - 8px);
// overflow: hidden;
}
&:nth-child(2) {
width: calc(50% + 50px - 16px);
width: calc(50% + 50px - 8px);
// overflow: hidden;
}
.fg-footer-charts-title {
@ -236,6 +238,8 @@
// overflow: hidden;
max-width: 100%;
height: 195px;
// display: flex;
// justify-content: center;
// background-color: red;
}
}

@ -46,7 +46,7 @@ const columns = [
width: 75,
},
{
label: "车",
label: "车辆ID",
property: "train_number",
width: 155,
},
@ -296,7 +296,7 @@ onMounted(() => {
</el-select>
<el-input
v-model="searchForm.train_number"
placeholder="请输入列车"
placeholder="请输入列车辆ID"
class="custom-input"
clearable
/>

@ -53,7 +53,7 @@ const columns = [
width: 90,
},
{
label: "车",
label: "车辆ID",
property: "train_number",
width: 185,
},
@ -278,7 +278,7 @@ onMounted(() => {
</el-select> -->
<el-input
v-model="searchForm.train_number"
placeholder="请输入列车"
placeholder="请输入列车辆ID"
class="custom-input"
clearable
/>

@ -29,7 +29,7 @@ const columns = [
width: 80,
},
{
label: "车",
label: "车辆ID",
property: "train_number",
width: 155,
},

@ -3,10 +3,10 @@ import { BaseTable } from "@/components/CustomTable";
import { getVehiclManagementApi } from "@/api/dashboard";
import { isSuccessApi } from "@/utils/forApi";
import AlarmModal from "./components/AlarmModal.vue";
import VehiclModal from "./components/VehiclModal.vue";
import { useTrainSaveToExcel } from "@/hooks/useTrainSaveToExcel";
import { useWebSocketStore } from "@/stores/websocketStore";
import { onBeforeRouteLeave } from "vue-router";
import VehiclModal from "./components/VehiclModal.vue";
defineOptions({
name: "VehiclManagementWrap",
});
@ -106,7 +106,9 @@ onMounted(() => {
<template>
<div class="bg-basic-content">
<div class="vehicl-management-wrap">
<div class="vehicl-management-header mt-[24px] py-[16px] flex items-center">
<div
class="vehicl-management-header mt-[24px] py-[16px] flex items-center"
>
<div class="fg-icon mr-[8px]"></div>
<div class="fg-title">车辆管理</div>
</div>
@ -124,13 +126,14 @@ onMounted(() => {
>
<template v-slot:actionBar="{ row }">
<ul class="flex table_action_box">
<li class="flex items-center mr-[8px]" @click="useTrainSaveToExcel(row)?.saveToExcel()">
<div class="fg-button-primary1">报表下载</div>
</li>
<li
class="flex items-center mr-[16px]"
@click="openCurrent(row)"
>
<div class="fg-button-primary">
查看详情
</div>
<div class="fg-button-primary">查看详情</div>
</li>
</ul>
</template>

@ -487,8 +487,8 @@ onUnmounted(() => {
@click="returnToCenter"
></span>
<!-- 新增进度条 -->
<div v-if="loading" class="progress-bar">
<div class="progress" :style="{ width: progress + '%' }"></div>
<div v-if="loading" class="pointModal-progress-bar">
<div class="pointModal-progress" :style="{ width: progress + '%' }"></div>
</div>
</div>
</el-dialog>
@ -547,7 +547,7 @@ onUnmounted(() => {
background-image: url("@/assets/common/reset_btn.png");
}
.progress-bar {
.pointModal-progress-bar {
position: absolute;
bottom: 20px;
left: 50%;
@ -559,7 +559,7 @@ onUnmounted(() => {
overflow: hidden;
}
.progress {
.pointModal-progress {
height: 100%;
background-color: #007bff;
transition: width 0.3s ease;

Loading…
Cancel
Save