561 lines
18 KiB
Vue
561 lines
18 KiB
Vue
<template>
|
||
<div class="inspection-container">
|
||
<div class="header">
|
||
<div class="header_left">
|
||
<!-- 日期输入框 -->
|
||
<IxDateInput label="日期" name="date" :value="currentDate" class="input-spacing" @dateChange="handleDateChange">
|
||
</IxDateInput>
|
||
|
||
<!-- 班次选择框 -->
|
||
<IxSelect Outline id="triggerId" v-model="shift" label="班次" hideListHeader="true" class="input-spacing" @valueChange="handleShiftChange">
|
||
<IxSelectItem icon="sun" label="白班" value="0"></IxSelectItem>
|
||
<IxSelectItem icon="moon" label="晚班" value="1"></IxSelectItem>
|
||
</IxSelect>
|
||
|
||
<!-- 状态选择框 -->
|
||
<IxSelect Outline id="statusSelect" v-model="status" label="状态" hideListHeader="true" class="input-spacing">
|
||
<IxSelectItem icon="sun" label="全部" value="0"></IxSelectItem>
|
||
<IxSelectItem icon="sun" label="正常" value="1"></IxSelectItem>
|
||
<IxSelectItem label="报警" value="2"></IxSelectItem>
|
||
</IxSelect>
|
||
<!-- 查询按钮 -->
|
||
<IxButton @click="handleSearch" class="input-spacing btn-style"> 查询 </IxButton>
|
||
<!-- 导出按钮 -->
|
||
<IxButton class="input-spacing btn-style" @click="handleExport"> 导出全部 </IxButton>
|
||
</div>
|
||
<div class="header_right">
|
||
<!-- 设备列表按钮 -->
|
||
<span v-for="(item, index) in deviceList" :key="item.id">
|
||
<IxButton :outline="selectedDeviceId !== item.id" class="btn-style" @click="handleDeviceListChange(item.id)">
|
||
{{ item.name }}
|
||
</IxButton>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div class="inspection-table">
|
||
<div class="table-container">
|
||
<!-- 表头部分 -->
|
||
<div class="table-row fixed-row">
|
||
<span class="fixed-width title-width"></span>
|
||
<span class="fixed-width"></span>
|
||
<span class="fixed-width"></span>
|
||
<span class="fixed-width"></span>
|
||
<span class="fixed-width" v-for="(hour, index) in hours" :key="hour">
|
||
<IxButton :disabled="confirmedHours.includes(hour)" class="custom-button" @click="handleInspection(hour, index)">
|
||
{{ confirmedHours.includes(hour) ? confirmedTimes[hour] : '确认' }}
|
||
</IxButton>
|
||
</span>
|
||
</div>
|
||
<div class="table-row-1 fixed-row">
|
||
<span class="header-row title-width">点检项目</span>
|
||
<span class="header-row">单位</span>
|
||
<span class="header-row">参考值</span>
|
||
<span class="header-row">当前值</span>
|
||
<span class="header-row" v-for="hour in hours" :key="hour"
|
||
:style="{ backgroundColor: getDeviceNameById(selectedDeviceId) === '灌注机' ? '#00FFB9' : '#00E4FF', color: '#000028' }">
|
||
{{ hour }}
|
||
</span>
|
||
</div>
|
||
<!-- 点检项目列表 -->
|
||
<IxEventList>
|
||
<IxEventListItem v-for="(item, index) in inspectionItems" :key="index" color="color-success" class="testbg">
|
||
<div class="table-row">
|
||
<span class="fixed-width title-width">{{ item.label }}</span>
|
||
<span class="fixed-width">{{ item.unit || '--' }}</span>
|
||
<span class="fixed-width">{{ item.reference || '--' }}</span>
|
||
<span class="fixed-width">{{ item.current }}</span> <!-- 确保这里绑定的是 item.current -->
|
||
<span class="fixed-width" v-for="hour in hours" :key="hour"
|
||
:class="{ 'highlight-cell': item.data[hour] < 0.5 }"
|
||
@click="item.data[hour] < 0.5 ? handleInspection(hour, index) : null">
|
||
{{ item.data[hour] || '--' }}
|
||
</span>
|
||
</div>
|
||
</IxEventListItem>
|
||
</IxEventList>
|
||
</div>
|
||
</div>
|
||
<!-- 点检表单 -->
|
||
<InspectionForm v-if="showForm" :itemName="selectedItemName" :itemTime="selectedItemTime" :timezone="timezone" @close="showForm = false" @submit="handleFormSubmit" />
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
// 引入必要的库和组件
|
||
import moment from 'moment';
|
||
import momentTimezone from 'moment-timezone';
|
||
import { ref, computed, getCurrentInstance, onMounted, defineEmits, onUnmounted } from 'vue';
|
||
import { IxDatePicker, IxButton, IxDropdownItem, IxEventList, IxEventListItem, IxSelect, IxSelectItem, IxDateInput } from '@siemens/ix-vue';
|
||
import InspectionForm from './InspectionForm.vue';
|
||
import { getInspectionCurrent, getInspectionData, getCheckParas, getDeviceList, exportExcel } from '@/api/inspection';
|
||
|
||
const emit = defineEmits(['send-data']);
|
||
|
||
// 设置为您期望的时区,比如 "Asia/Shanghai"
|
||
const timezone = 'Asia/Shanghai';
|
||
|
||
// 全局响应式变量
|
||
const globalTime = ref(moment().tz(timezone).format('YYYY-MM-DD HH:mm'));
|
||
const isAutoUpdate = ref(true); // 是否自动更新
|
||
|
||
const sendDataToParent = () => {
|
||
emit('send-data', 'SIEMENS MIS 1.0 无菌产线点检界面', 'other-app');
|
||
};
|
||
|
||
// 获取当前时间的小时数
|
||
const currentHour = new Date().getHours();
|
||
|
||
// 根据当前时间确定默认班次
|
||
const defaultShift = currentHour >= 7 && currentHour < 19 ? '0' : '1'; // 早班为0,晚班为1
|
||
|
||
// 定义响应式变量
|
||
const shift = ref(defaultShift); // 设置默认班次
|
||
const status = ref('0'); // 确保 status 变量已定义
|
||
|
||
// 设备列表
|
||
const deviceList = ref([]);
|
||
const selectedDeviceId = ref(null);
|
||
|
||
const showForm = ref(false);
|
||
const selectedItemName = ref('');
|
||
const selectedItemTime = ref('');
|
||
const selectedItemIndex = ref(null); // 添加索引变量
|
||
|
||
const selectedDate = ref(null);
|
||
|
||
const formatDate = (date) => {
|
||
const d = new Date(date);
|
||
const year = d.getFullYear();
|
||
const month = (d.getMonth() + 1).toString().padStart(2, '0');
|
||
const day = d.getDate().toString().padStart(2, '0');
|
||
return `${year}/${month}/${day}`;
|
||
};
|
||
|
||
const currentDate = formatDate(new Date());
|
||
|
||
// 计算当前班次的时间段
|
||
const hours = computed(() => {
|
||
const shiftValue = shift.value;
|
||
const hours = [];
|
||
if (shiftValue === '0') {
|
||
for (let i = 7; i <= 18; i++) {
|
||
hours.push(`${i < 10 ? '0' : ''}${i}:00`); // 白班 07:00-18:00
|
||
}
|
||
} else {
|
||
for (let i = 19; i <= 23; i++) {
|
||
hours.push(`${i}:00`); // 晚班 19:00-23:00
|
||
}
|
||
for (let i = 0; i <= 6; i++) {
|
||
hours.push(`${i < 10 ? '0' : ''}${i}:00`); // 晚班 00:00-06:00
|
||
}
|
||
}
|
||
return hours;
|
||
});
|
||
|
||
// JSON 数据
|
||
const data = ref({});
|
||
|
||
const inspectionItems = ref([]);
|
||
const confirmedHours = ref([]);
|
||
const confirmedTimes = ref({});
|
||
|
||
// 点检按钮点击事件
|
||
const handleInspection = (hour, index) => {
|
||
selectedItemName.value = inspectionItems.value[index].label;
|
||
selectedItemTime.value = hour;
|
||
showForm.value = true;
|
||
};
|
||
|
||
// 点检表单提交事件
|
||
const handleFormSubmit = (currentTime) => {
|
||
confirmedHours.value.push(selectedItemTime.value);
|
||
console.log("🚀 ~ handleFormSubmit ~ confirmedHours.value:", confirmedHours.value)
|
||
confirmedTimes.value[selectedItemTime.value] = currentTime;
|
||
showForm.value = false;
|
||
};
|
||
|
||
const { proxy } = getCurrentInstance();
|
||
|
||
const showInfoMessage = (message) => {
|
||
proxy.$message.info(message);
|
||
};
|
||
|
||
const showInfoMessageWithAction = (message, action) => {
|
||
proxy.$message.$confirm(message, action);
|
||
};
|
||
|
||
const showDangerMessage = (message) => {
|
||
proxy.$message.danger(message);
|
||
};
|
||
|
||
const showWarningMessage = (message) => {
|
||
proxy.$message.warning(message);
|
||
};
|
||
|
||
const showConfirmMessage = (message, onConfirm, onCancel) => {
|
||
proxy.$message.confirm(message, onConfirm, onCancel);
|
||
};
|
||
|
||
const toLowerCaseFirstLetter = (str) => {
|
||
if (!str) return str;
|
||
return str.charAt(0).toLowerCase() + str.slice(1);
|
||
}
|
||
|
||
// 日期变化处理函数
|
||
const handleDateChange = (event) => {
|
||
selectedDate.value = event.target.value;
|
||
};
|
||
|
||
// 班次变化处理函数
|
||
const handleShiftChange = (event) => {
|
||
shift.value = event.detail;
|
||
fetchInspectionData();
|
||
fetchCurrentValues();
|
||
};
|
||
|
||
// 切换设备
|
||
const handleDeviceListChange = (id) => {
|
||
selectedDeviceId.value = id;
|
||
fetchInspectionData();
|
||
fetchCurrentValues();
|
||
};
|
||
|
||
// 获取设备列表
|
||
const fetchDeviceList = async () => {
|
||
try {
|
||
const response = await getDeviceList();
|
||
if (response.code === 200) {
|
||
deviceList.value = response.data;
|
||
selectedDeviceId.value = deviceList.value[2].id; // 默认选中第一个设备
|
||
} else {
|
||
showWarningMessage('获取设备列表失败!');
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching device list:', error);
|
||
}
|
||
};
|
||
|
||
// 获取当前值、参考值、单位等信息
|
||
const fetchCurrentValues = async () => {
|
||
try {
|
||
const deviceId = selectedDeviceId.value; // 根据实际情况设置设备ID
|
||
const dateValue = selectedDate.value || currentDate;
|
||
const response = await getInspectionCurrent(deviceId, dateValue);
|
||
const params = await getCheckParas(deviceId, dateValue);
|
||
|
||
if (response.data) {
|
||
const currentValues = response.data.data;
|
||
inspectionItems.value.forEach(item => {
|
||
item.current = currentValues[item.name] || '--';
|
||
});
|
||
} else {
|
||
showWarningMessage('获取当前设备当前值失败!');
|
||
}
|
||
|
||
if (params.data) {
|
||
const paramData = params.data;
|
||
|
||
inspectionItems.value.forEach(item => {
|
||
const param = paramData.find(param => {
|
||
return toLowerCaseFirstLetter(param.keyname) === item.name;
|
||
});
|
||
|
||
if (param) {
|
||
item.label = param.projectDescription;
|
||
item.reference = param.referenceValue;
|
||
item.unit = param.unit;
|
||
}
|
||
});
|
||
} else {
|
||
showWarningMessage('获取设备具体信息失败!');
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('Error fetching current values:', error);
|
||
}
|
||
};
|
||
|
||
// 获取点检数据
|
||
const fetchInspectionData = async () => {
|
||
try {
|
||
const deviceId = selectedDeviceId.value; // 根据实际情况设置设备ID
|
||
// const inputTime = new Date().toISOString(); // globalTime; // 获取当前时间
|
||
const shiftValue = shift.value;
|
||
const statusValue = status.value;
|
||
const dateValue = selectedDate.value || currentDate;
|
||
const response = await getInspectionData(deviceId, dateValue, shiftValue);
|
||
if (response.data) {
|
||
const inspectionData = response.data;
|
||
const itemsMap = {};
|
||
inspectionData.forEach(record => {
|
||
const recordTime = record.recordTime;
|
||
const data = record.data;
|
||
for (const [name, value] of Object.entries(data)) {
|
||
if (value === -1) continue; // 过滤掉值为 -1 的属性
|
||
if (!itemsMap[name]) {
|
||
itemsMap[name] = {
|
||
name,
|
||
label: name, // 可以根据需要调整label的值
|
||
reference: 0,
|
||
current: 0,
|
||
unit: '', // 添加单位字段
|
||
data: {}
|
||
};
|
||
}
|
||
itemsMap[name].data[recordTime] = value;
|
||
}
|
||
});
|
||
inspectionItems.value = Object.values(itemsMap);
|
||
} else {
|
||
showWarningMessage('获取点检数据失败!');
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching inspection data:', error);
|
||
}
|
||
};
|
||
|
||
// 查询接口数据
|
||
const handleSearch = () => {
|
||
fetchInspectionData();
|
||
fetchCurrentValues();
|
||
};
|
||
|
||
const handleExport = () => {
|
||
showInfoMessage('导出全部');
|
||
exportExcel(selectedDeviceId.value, selectedDate.value || currentDate, shift.value)
|
||
.then((response) => {
|
||
if (response) {
|
||
// 有数据的处理
|
||
const url = window.URL.createObjectURL(new Blob([response]));
|
||
const link = document.createElement('a');
|
||
link.href = url;
|
||
link.setAttribute('download', 'inspection_data.xlsx');
|
||
document.body.appendChild(link);
|
||
link.click();
|
||
document.body.removeChild(link);
|
||
showInfoMessage('导出成功');
|
||
} else {
|
||
// 没有数据的处理
|
||
showWarningMessage('没有可导出的数据');
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.error('导出 Excel 失败:', error);
|
||
showDangerMessage('导出 Excel 失败,请稍后重试');
|
||
});
|
||
};
|
||
|
||
// 通过设备ID获取设备名称
|
||
const getDeviceNameById = (id) => {
|
||
const device = deviceList.value.find(device => device.id === id);
|
||
return device ? device.name : '';
|
||
};
|
||
|
||
let autoUpdateInterval = null;
|
||
|
||
onMounted(async () => {
|
||
await fetchDeviceList();
|
||
fetchCurrentValues();
|
||
fetchInspectionData();
|
||
sendDataToParent();
|
||
|
||
const setupAutoUpdate = () => {
|
||
if (isAutoUpdate.value) {
|
||
autoUpdateInterval = setInterval(() => {
|
||
fetchCurrentValues();
|
||
fetchInspectionData();
|
||
}, 60000); // 每分钟刷新一次接口
|
||
} else if (autoUpdateInterval) {
|
||
clearInterval(autoUpdateInterval);
|
||
autoUpdateInterval = null;
|
||
}
|
||
};
|
||
|
||
setupAutoUpdate();
|
||
|
||
// 监听 update-history 事件
|
||
// window.addEventListener('update-history', (event) => {
|
||
// isAutoUpdate.value = false;
|
||
// selectedDate.value = event.detail;
|
||
// fetchCurrentValues();
|
||
// fetchInspectionData();
|
||
// setupAutoUpdate();
|
||
// });
|
||
|
||
// 监听 reset 事件
|
||
// window.addEventListener('reset', (event) => {
|
||
// isAutoUpdate.value = true;
|
||
// selectedDate.value = moment().tz(timezone).format('YYYY-MM-DD HH:mm');
|
||
// fetchCurrentValues();
|
||
// fetchInspectionData();
|
||
// setupAutoUpdate();
|
||
// });
|
||
});
|
||
// 在 onUnmounted 中添加
|
||
// onUnmounted(() => {
|
||
// window.removeEventListener('update-history', handleHistoryUpdate);
|
||
// window.removeEventListener('reset', handleReset);
|
||
// });
|
||
onUnmounted(() => {
|
||
if (autoUpdateInterval) {
|
||
clearInterval(autoUpdateInterval);
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 样式定义 */
|
||
.inspection-container {
|
||
width: calc(100% + 1.5rem);
|
||
margin: 0 -1.5rem 0 0 !important;
|
||
height: 100vh;
|
||
/* 修改为100vh,使其高度铺满整个视口 */
|
||
background-color: #000028;
|
||
color: white;
|
||
font-size: 1.2rem;
|
||
/* 调大全局字体大小 */
|
||
}
|
||
|
||
.header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
height: 10%;
|
||
}
|
||
|
||
.header_left {
|
||
display: flex;
|
||
align-items: center;
|
||
width: 70%;
|
||
/* 设置宽度,确保三个搜索框都能正常显示 */
|
||
font-size: 1rem;
|
||
/* 调大左侧头部字体大小 */
|
||
}
|
||
|
||
.header_right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
/* 添加间距 */
|
||
font-size: 1rem;
|
||
/* 调大右侧头部字体大小 */
|
||
}
|
||
|
||
.inspection-table {
|
||
width: 100%;
|
||
height: 90%;
|
||
/* 修改为90%,使其高度铺满剩余部分 */
|
||
overflow-x: auto;
|
||
/* 添加水平滚动条 */
|
||
}
|
||
|
||
.table-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-width: 100%;
|
||
/* 确保表格宽度至少为容器宽度 */
|
||
overflow-x: auto;
|
||
/* 添加水平滚动条 */
|
||
}
|
||
|
||
.table-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
/* padding: 10px;
|
||
border-bottom: 1px solid #ccc; */
|
||
flex: 1;
|
||
/* 使每一行铺满 */
|
||
}
|
||
|
||
.table-row-1 {
|
||
height: 100%;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
flex: 1;
|
||
padding: 0 0 0 0.5rem;
|
||
}
|
||
|
||
.fixed-width {
|
||
width: 6.5rem;
|
||
/* 设置固定宽度 */
|
||
height: 2.5rem;
|
||
text-align: center;
|
||
/* 居中对齐 */
|
||
font-size: 1rem;
|
||
/* 调大固定宽度元素字体大小 */
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.header-row {
|
||
display: flex;
|
||
width: 6.5rem;
|
||
height: 2.5rem;
|
||
background-color: #23233C;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 1rem;
|
||
margin: 0 0 0.5rem 0;
|
||
}
|
||
|
||
.title-width {
|
||
width: 15rem;
|
||
}
|
||
|
||
.btn-style {
|
||
margin: 1.8rem 0.5rem 0 0;
|
||
}
|
||
|
||
.testbg {
|
||
/* 这里是因为它tm组件里的,还用的好像是webcomponent,但是tmd不对外提供修改的东西,好在有个css颜色变量可以修改 */
|
||
--theme-event-item--background: #23233C;
|
||
/* --theme-event-item--background--hover: blue; */
|
||
}
|
||
|
||
.testbg1 {
|
||
--theme-event-item--background: #000028;
|
||
}
|
||
|
||
/**如果要改按钮的颜色,那么上面就不要用 :style 改成用 :class 来设置,这个总没问题吧,然后再f12看按钮有哪些颜色变量 */
|
||
/* 定义按钮颜色的 CSS 类 */
|
||
.custom-button {
|
||
--theme-btn-primary--background: #FFA849;
|
||
--theme-btn-primary--background--hover: #FFA849;
|
||
}
|
||
|
||
.drop-down {
|
||
width: calc(25% - 1.25rem);
|
||
background-color: #23233C;
|
||
}
|
||
|
||
:deep(ix-date-input) {
|
||
--theme-menu--background: #23233C;
|
||
padding-left: 1rem;
|
||
}
|
||
|
||
.search-label {
|
||
margin-right: 10px;
|
||
margin-left: 20px;
|
||
color: white;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
.input-spacing {
|
||
margin-right: 1rem;
|
||
--theme-color-2: #23233C;
|
||
}
|
||
|
||
.fixed-row {
|
||
position: sticky;
|
||
top: 0;
|
||
background-color: inherit;
|
||
z-index: 1;
|
||
}
|
||
|
||
.highlight-cell {
|
||
background-color: orange;
|
||
cursor: pointer;
|
||
}
|
||
</style>
|