update: 甘特图初版
This commit is contained in:
parent
cb09d8183e
commit
da17bba934
82
deploy.sh
82
deploy.sh
|
@ -1,17 +1,79 @@
|
|||
#!/bin/bash
|
||||
echo "开始部署 - $(date)"
|
||||
|
||||
# 执行 npm run build
|
||||
echo "开始部署您的项目..."
|
||||
|
||||
# 1. 克隆项目代码
|
||||
# echo "1. 克隆项目代码..."
|
||||
# git clone https://git.zhouxhere.com/wonderzhao/cola-web.git
|
||||
|
||||
# 2. 进入项目目录
|
||||
# echo "2. 进入项目目录..."
|
||||
# cd cola-web
|
||||
|
||||
# 3. 安装依赖
|
||||
# echo "3. 安装依赖..."
|
||||
# npm install
|
||||
|
||||
# 4. 构建项目
|
||||
echo "4. 构建项目..."
|
||||
npm run build
|
||||
|
||||
# 创建新目录
|
||||
mkdir deployment_package
|
||||
# 5. 构建 Docker 镜像
|
||||
echo "5. 构建 Docker 镜像..."
|
||||
docker build -t cola-web:latest .
|
||||
|
||||
# 复制 dist 文件夹和 nginx.conf 到新目录
|
||||
cp -r dist deployment_package/
|
||||
cp nginx.conf deployment_package/
|
||||
# 6. 保存镜像为 tar 文件
|
||||
echo "6. 保存 Docker 镜像..."
|
||||
docker save cola-web:latest > cola-web.tar
|
||||
|
||||
# 切换到包含新目录、Dockerfile 的上级目录
|
||||
cd..
|
||||
# 7. 传输文件到服务器
|
||||
echo "7. 传输文件到服务器..."
|
||||
ssh -p 22 owner@192.168.1.199 "mkdir -p web"
|
||||
scp -P 22 cola-web.tar owner@192.168.1.199:web/
|
||||
|
||||
# 打包
|
||||
tar -czf deployment_package.tar.gz deployment_package/ Dockerfile
|
||||
# 8. 在远程服务器上执行部署
|
||||
echo "8. 在远程服务器上执行部署..."
|
||||
ssh -p 22 owner@192.168.1.199 << EOF
|
||||
cd web
|
||||
sudo docker load < cola-web.tar
|
||||
sudo docker stop cola-web 2>/dev/null || true
|
||||
sudo docker rm cola-web 2>/dev/null || true
|
||||
sudo docker run -d \
|
||||
--name cola-web \
|
||||
-p 8090:80 \
|
||||
--restart unless-stopped \
|
||||
cola-web
|
||||
EOF
|
||||
|
||||
# 9. 清理本地临时文件
|
||||
echo "9. 清理本地临时文件..."
|
||||
rm cola-web.tar
|
||||
|
||||
# 等待容器启动
|
||||
echo "等待容器启动..."
|
||||
sleep 10
|
||||
|
||||
# 检查容器状态
|
||||
ssh -p 22 owner@192.168.1.199 << EOF
|
||||
if! sudo docker ps | grep -q cola-web; then
|
||||
echo "错误:容器未正常运行"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查应用是否响应
|
||||
if! curl -s http://localhost:8090/ > /dev/null; then
|
||||
echo "错误:应用未正常响应"
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
||||
|
||||
echo "部署完成!"
|
||||
# echo "部署完成!应用已在 http://${REMOTE_HOST}:8090 上运行"
|
||||
|
||||
# 10. 检查部署状态
|
||||
# echo "10. 检查部署状态..."
|
||||
ssh owner@192.168.1.199 "docker ps | grep cola-web"
|
||||
|
||||
# 在另一个终端窗口查看日志
|
||||
# tail -f deploy.log
|
|
@ -14,6 +14,8 @@
|
|||
"axios": "^1.7.9",
|
||||
"core-js": "^3.8.3",
|
||||
"echarts": "^5.6.0",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.47",
|
||||
"pinia": "^2.2.2",
|
||||
"vue": "^3.2.13",
|
||||
"vue-router": "^4.4.5"
|
||||
|
@ -8177,6 +8179,25 @@
|
|||
"integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moment-timezone": {
|
||||
"version": "0.5.47",
|
||||
"resolved": "https://registry.npmmirror.com/moment-timezone/-/moment-timezone-0.5.47.tgz",
|
||||
"integrity": "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==",
|
||||
"dependencies": {
|
||||
"moment": "^2.29.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mrmime": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.0.tgz",
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
"axios": "^1.7.9",
|
||||
"core-js": "^3.8.3",
|
||||
"echarts": "^5.6.0",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.47",
|
||||
"pinia": "^2.2.2",
|
||||
"vue": "^3.2.13",
|
||||
"vue-router": "^4.4.5"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import request from '@/utils/request';
|
||||
|
||||
// 获取前处理页面当前数据
|
||||
export function getCurrentReport() {
|
||||
return request({
|
||||
url: '/Report/current',
|
||||
|
@ -7,16 +8,18 @@ export function getCurrentReport() {
|
|||
});
|
||||
}
|
||||
|
||||
export function getHistoryReport() {
|
||||
// 获取前处理页面历史数据
|
||||
export function getHistoryReport(inputTime) {
|
||||
return request({
|
||||
url: '/devicedata/gethtml?name=9b889443bab24a249f43679663074e8c',
|
||||
url: `/Report/history?inputTime=${inputTime}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取前处理页面甘特图数据
|
||||
export function getGanttData(deviceId, inputTime) {
|
||||
return request({
|
||||
url: `/State?deviceId=${deviceId}&inputTime=${inputTime}`,
|
||||
method: 'get'
|
||||
url: `/State?deviceId=${deviceId}&inputTime=${inputTime}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import request from '@/utils/request';
|
||||
|
||||
// 获取点检页面当前值
|
||||
export function getInspectionCurrent(deviceId, inputTime) {
|
||||
return request({
|
||||
url: `/Check/currunt?deviceId=${deviceId}&inputTime=${inputTime}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取点检页面整点数值
|
||||
export function getInspectionData(deviceId, inputTime) {
|
||||
return request({
|
||||
url: `/Check/sharp?deviceId=${deviceId}&inputTime=${inputTime}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<svg width="41" height="42" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" overflow="hidden"><g transform="translate(-321 -194)"><path d="M11.1157 22.2083C11.1157 17.0191 15.3223 12.8125 20.5115 12.8125 25.7007 12.8125 29.9074 17.0191 29.9074 22.2083 29.9074 27.3975 25.7007 31.6042 20.5115 31.6042 15.3287 31.5889 11.1309 27.3912 11.1157 22.2083ZM21.3657 10.2927 21.3657 8.54167 23.074 8.54167C23.5458 8.54167 23.9282 8.15926 23.9282 7.6875 23.9282 7.21574 23.5458 6.83333 23.074 6.83333L17.949 6.83333C17.4773 6.83333 17.0949 7.21574 17.0949 7.6875 17.0949 8.15926 17.4773 8.54167 17.949 8.54167L19.6574 8.54167 19.6574 10.2927C13.0738 10.7603 8.11578 16.4764 8.58335 23.0599 8.78425 25.8888 9.98461 28.554 11.9699 30.5792L10.3469 33.7823C10.1334 34.2029 10.3012 34.717 10.7218 34.9306 10.725 34.9323 10.7281 34.9338 10.7313 34.9354 10.8541 34.9841 10.9839 35.0129 11.1157 35.0208 11.4375 35.013 11.7307 34.8339 11.8844 34.551L13.2938 31.7323C17.5581 34.9786 23.465 34.9786 27.7292 31.7323L29.1386 34.551C29.2924 34.8339 29.5855 35.013 29.9074 35.0208 30.0392 35.0129 30.169 34.9841 30.2917 34.9354 30.715 34.7271 30.8892 34.2151 30.6809 33.7919 30.6793 33.7887 30.6777 33.7855 30.6761 33.7823L29.0532 30.5792C33.6735 25.8659 33.5982 18.2996 28.8849 13.6792 26.8597 11.694 24.1945 10.4936 21.3657 10.2927Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/><path d="M19.6574 21.3542 13.6782 21.3542 13.6782 23.0625 20.5115 23.0625C20.9827 23.0611 21.3643 22.6795 21.3657 22.2083L21.3657 15.375 19.6574 15.375Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/><path d="M34.2636 10.3354 30.7188 6.79063C30.0622 6.1184 28.985 6.10575 28.3127 6.76235 28.3032 6.77166 28.2938 6.7811 28.2844 6.79063L26.0636 8.96875 32.0428 14.9479 34.2636 12.7271C34.9042 12.0586 34.9042 11.0039 34.2636 10.3354Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/><path d="M14.9594 8.96875 12.7386 6.74792C12.082 6.07569 11.0047 6.06305 10.3325 6.71964 10.3229 6.72895 10.3135 6.73839 10.3042 6.74792L6.75945 10.2927C6.08722 10.9493 6.07458 12.0266 6.73118 12.6988 6.74049 12.7084 6.74992 12.7178 6.75945 12.7271L8.98028 14.9479Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/><path d="M6.06458 25.7958 7.26042 24.6C5.95068 23.2413 5.95068 21.0899 7.26042 19.7313L6.06458 18.5354C4.07143 20.5452 4.07143 23.7861 6.06458 25.7958Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/><path d="M3.67292 28.1875 4.86875 26.9917C2.2034 24.3419 2.19078 20.0331 4.84056 17.3678 4.84992 17.3583 4.85931 17.3489 4.86875 17.3396L3.67292 16.1437C0.347127 19.4226 0.309022 24.7766 3.58781 28.1024 3.61597 28.131 3.64435 28.1593 3.67292 28.1875Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/><path d="M34.8073 25.7958 33.6115 24.6C34.9212 23.2413 34.9212 21.0899 33.6115 19.7313L34.8073 18.5354C36.8004 20.5452 36.8004 23.7861 34.8073 25.7958Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/><path d="M37.199 28.1875 36.0031 26.9917C38.6685 24.3419 38.6811 20.0331 36.0313 17.3678 36.022 17.3583 36.0126 17.3489 36.0031 17.3396L37.199 16.1437C40.5247 19.4226 40.5628 24.7766 37.2841 28.1024 37.2559 28.131 37.2275 28.1593 37.199 28.1875Z" fill="#FF0000" transform="matrix(1 0 0 1.02439 321 194)"/></g></svg>
|
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<div class="confirm-dialog">
|
||||
<div class="confirm-message">{{ message }}</div>
|
||||
<div class="confirm-actions">
|
||||
<button @click="onConfirm">确认</button>
|
||||
<button @click="onCancel">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
message: String,
|
||||
onConfirm: Function,
|
||||
onCancel: Function,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.confirm-dialog {
|
||||
background: #23233C; /* 修改背景颜色 */
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
color: white; /* 修改文字颜色 */
|
||||
border: 0.0625rem solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.confirm-message {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.confirm-actions button {
|
||||
margin: 0 10px;
|
||||
background: #00BEDC; /* 修改按钮背景颜色 */
|
||||
color: white; /* 修改按钮文字颜色 */
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.confirm-actions button:hover {
|
||||
background: #00A3C4; /* 修改按钮悬停背景颜色 */
|
||||
}
|
||||
</style>
|
|
@ -48,12 +48,12 @@ const initChart = () => {
|
|||
if (chart.value) {
|
||||
chart.value.dispose();
|
||||
}
|
||||
|
||||
|
||||
if (!ganttChart.value) return;
|
||||
|
||||
|
||||
// 创建新实例
|
||||
chart.value = echarts.init(ganttChart.value);
|
||||
|
||||
|
||||
// 设置基础配置
|
||||
const baseOption = {
|
||||
backgroundColor: 'transparent',
|
||||
|
@ -71,12 +71,12 @@ const initChart = () => {
|
|||
data: []
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
chart.value.setOption(baseOption);
|
||||
|
||||
|
||||
// 绑定resize事件
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
|
||||
// 更新数据
|
||||
nextTick(() => {
|
||||
updateChart();
|
||||
|
@ -132,43 +132,28 @@ const updateChart = () => {
|
|||
color: 'rgba(255, 255, 255, 0.3)'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: true,
|
||||
alignWithLabel: true,
|
||||
length: 4,
|
||||
lineStyle: {
|
||||
color: 'rgba(255, 255, 255, 0.3)'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
interval: 3, // 每4个标签显示一个(15分钟 * 4 = 1小时)
|
||||
fontSize: 12,
|
||||
margin: 15,
|
||||
rotate: 0,
|
||||
formatter: function(value) {
|
||||
formatter: function (value) {
|
||||
// 只显示整点时间
|
||||
if (value.includes('/')) {
|
||||
const [date, time] = value.split(' ')
|
||||
const [year, month, day] = date.split('/')
|
||||
|
||||
|
||||
if (time === '0') {
|
||||
return `${year}/${month}/${day} ${time}`
|
||||
return `${year}/${month}/${day} ${time}:00`
|
||||
}
|
||||
}
|
||||
const [hour, minute] = value.split(':')
|
||||
if (minute === '00') {
|
||||
return `${hour}`
|
||||
return `${hour}:00`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: 'rgba(255, 255, 255, 0.1)',
|
||||
type: 'dashed'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
|
@ -179,7 +164,7 @@ const updateChart = () => {
|
|||
},
|
||||
series: [{
|
||||
type: 'bar',
|
||||
barWidth: '100%',
|
||||
barWidth: '108%',
|
||||
barGap: 0,
|
||||
itemStyle: {
|
||||
borderRadius: 0
|
||||
|
@ -187,9 +172,7 @@ const updateChart = () => {
|
|||
data: mapDataToTimeline(timeLabels, baseDate) || [] // 确保有默认值
|
||||
}]
|
||||
}
|
||||
|
||||
chart.value.setOption(option, true)
|
||||
|
||||
// 重新绑定点击事件
|
||||
chart.value.off('click')
|
||||
chart.value.on('click', 'series', (params) => {
|
||||
|
@ -212,7 +195,7 @@ const formatTime = (timeString) => {
|
|||
}
|
||||
|
||||
const mapDataToTimeline = (timeLabels, baseDate) => {
|
||||
return timeLabels.map((label) => {
|
||||
return timeLabels.map((label) => {
|
||||
// 获取当前时间标签对应的小时和分钟
|
||||
let currentTime;
|
||||
if (label.includes('/')) {
|
||||
|
@ -230,13 +213,13 @@ const mapDataToTimeline = (timeLabels, baseDate) => {
|
|||
const matchingData = props.processData.find(item => {
|
||||
const beginTime = new Date(item.beginTime).getTime();
|
||||
const endTime = new Date(item.endTime).getTime();
|
||||
return currentTime.getTime() >= beginTime && currentTime.getTime() <= endTime;
|
||||
return currentTime.getTime() >= beginTime && currentTime.getTime() <= endTime; // 修改比较条件,确保数据正确对齐
|
||||
});
|
||||
|
||||
if (matchingData) {
|
||||
return {
|
||||
value: 1,
|
||||
status: matchingData.status,
|
||||
deviceStatus: matchingData.deviceStatus,
|
||||
mixerStep: matchingData.mixerStep,
|
||||
beginTime: formatTime(matchingData.beginTime),
|
||||
endTime: formatTime(matchingData.endTime),
|
||||
|
@ -244,7 +227,7 @@ const mapDataToTimeline = (timeLabels, baseDate) => {
|
|||
formula: matchingData.formula,
|
||||
duration: matchingData.duration,
|
||||
itemStyle: {
|
||||
color: getStatusColor(matchingData.status)
|
||||
color: getStatusColor(matchingData.deviceStatus) // 确保颜色正确
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -255,7 +238,7 @@ const mapDataToTimeline = (timeLabels, baseDate) => {
|
|||
const generateTimeLabels = () => {
|
||||
const times = [];
|
||||
const now = new Date();
|
||||
let startHour, endHour;
|
||||
let startHour, endHour;
|
||||
|
||||
switch (currentRange.value) {
|
||||
case '1h':
|
||||
|
@ -293,18 +276,17 @@ const generateTimeLabels = () => {
|
|||
timeLabel = `${dateStr} ${currentHour}`;
|
||||
}
|
||||
times.push(timeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return times;
|
||||
};
|
||||
|
||||
const updateCurrentInfo = () => {
|
||||
const currentData = props.processData[props.processData.length - 1] || {}
|
||||
currentStatus.value = currentData.status || '--'
|
||||
currentStatus.value = currentData.deviceStatus || '--'
|
||||
startTimeFormatted.value = formatTime(currentData.beginTime) || '--'
|
||||
endTimeFormatted.value = formatTime(currentData.endTime) || '--'
|
||||
|
||||
|
||||
if (currentData.beginTime && currentData.endTime) {
|
||||
const start = new Date(currentData.beginTime)
|
||||
const end = new Date(currentData.endTime)
|
||||
|
@ -313,7 +295,7 @@ const updateCurrentInfo = () => {
|
|||
} else {
|
||||
duration.value = '--'
|
||||
}
|
||||
|
||||
|
||||
productFlowRate.value = currentData.productFlowRate || '--'
|
||||
formula.value = currentData.formula || '--'
|
||||
}
|
||||
|
@ -346,7 +328,7 @@ const handleChartClick = (data) => {
|
|||
currentStatus.value = data.status
|
||||
startTimeFormatted.value = formatTime(data.beginTime)
|
||||
endTimeFormatted.value = formatTime(data.endTime)
|
||||
|
||||
|
||||
if (data.beginTime && data.endTime) {
|
||||
const start = new Date(data.beginTime)
|
||||
const end = new Date(data.endTime)
|
||||
|
@ -355,10 +337,10 @@ const handleChartClick = (data) => {
|
|||
} else {
|
||||
duration.value = '--'
|
||||
}
|
||||
|
||||
|
||||
productFlowRate.value = data.productFlowRate || '--'
|
||||
formula.value = data.formula || '--'
|
||||
|
||||
|
||||
// 触发 segment-click 事件
|
||||
emit('segment-click', data)
|
||||
}
|
||||
|
@ -418,7 +400,7 @@ watch(() => props.currentRange, (newRange) => {
|
|||
background: #23233C;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height:100%;
|
||||
height: 100%;
|
||||
min-height: 80px;
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,6 @@
|
|||
import { createApp, h } from 'vue';
|
||||
import MessageBar from '@/components/MessageBar.vue';
|
||||
import ConfirmDialog from '@/components/ConfirmDialog.vue';
|
||||
|
||||
const MessagePlugin = {
|
||||
install(app) {
|
||||
|
@ -24,10 +25,40 @@ const MessagePlugin = {
|
|||
}, 5000); // 自动卸载组件
|
||||
};
|
||||
|
||||
const showConfirm = (message, onConfirm, onCancel) => {
|
||||
const container = document.createElement('div');
|
||||
container.style.position = 'fixed';
|
||||
container.style.top = '50%';
|
||||
container.style.left = '50%';
|
||||
container.style.transform = 'translate(-50%, -50%)';
|
||||
document.body.appendChild(container);
|
||||
|
||||
const appInstance = createApp({
|
||||
render() {
|
||||
return h(ConfirmDialog, {
|
||||
message,
|
||||
onConfirm: () => {
|
||||
onConfirm();
|
||||
appInstance.unmount();
|
||||
document.body.removeChild(container);
|
||||
},
|
||||
onCancel: () => {
|
||||
onCancel();
|
||||
appInstance.unmount();
|
||||
document.body.removeChild(container);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
appInstance.mount(container);
|
||||
};
|
||||
|
||||
app.config.globalProperties.$message = {
|
||||
info: (message, action) => showMessage('info', message, action),
|
||||
danger: (message, action) => showMessage('danger', message, action),
|
||||
warning: (message, action) => showMessage('warning', message, action),
|
||||
confirm: (message, onConfirm, onCancel) => showConfirm(message, onConfirm, onCancel),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,13 +3,15 @@
|
|||
<div class="upper-section">
|
||||
<div class="upper-left">
|
||||
<div class="left-1">
|
||||
<div class="block" :data-device-id="juiceData?.deviceId" @click="handleBlockClick(juiceData?.deviceId)">
|
||||
<div class="block">
|
||||
<div class="flex-row">
|
||||
<h2 class="juice-title">果汁调配</h2>
|
||||
<span class="flow-label">累计流量:{{ totalTrafficJuice }}</span>
|
||||
</div>
|
||||
<div class="spacing"></div>
|
||||
<div v-for="item in progressList" :key="item.name" class="juice-item">
|
||||
<div v-for="item in progressList" :key="item.name" class="juice-item"
|
||||
:data-device-id="item?.deviceId" @click="handleBlockClick(item?.deviceId)"
|
||||
style="cursor: pointer;">
|
||||
<span class="juice-name">{{ item.name }}:</span>
|
||||
<div class="progress-bar">
|
||||
<div class="progress"
|
||||
|
@ -17,15 +19,18 @@
|
|||
<span class="progress-text">{{ item.value }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<img style="padding-left: 1rem;" v-if="item.rate < 10" src="@/assets/alarm.svg" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="block" :data-device-id="pulpData?.deviceId" @click="handleBlockClick(pulpData?.deviceId)">
|
||||
<div class="block">
|
||||
<div class="flex-row">
|
||||
<h2 class="juice-title">果肉调配</h2>
|
||||
<span class="flow-label">果肉流量:{{ totalTrafficPulp }}</span>
|
||||
</div>
|
||||
<div class="spacing"></div>
|
||||
<div v-for="item in innerProgressList" :key="item.name" class="juice-item">
|
||||
<div v-for="item in innerProgressList" :key="item.name" class="juice-item"
|
||||
:data-device-id="item?.deviceId" @click="handleBlockClick(item?.deviceId)"
|
||||
style="cursor: pointer;">
|
||||
<span class="juice-name">{{ item.name }}:</span>
|
||||
<div class="progress-bar">
|
||||
<div class="progress"
|
||||
|
@ -33,17 +38,19 @@
|
|||
<span class="progress-text">{{ item.value }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<img style="padding-left: 1rem;" v-if="item.rate > 90" src="@/assets/alarm.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="left-2">
|
||||
<div class="block" :data-device-id="uhtData?.deviceId" @click="handleBlockClick(uhtData?.deviceId)">
|
||||
<div class="flex-row">
|
||||
<div class="block">
|
||||
<div class="flex-row" :data-device-id="uhtData?.deviceId"
|
||||
@click="handleBlockClick(uhtData?.deviceId)" style="cursor: pointer;">
|
||||
<h2 class="juice-title">果汁 UHT</h2>
|
||||
</div>
|
||||
<div class="spacing"></div>
|
||||
<div class="UHT-item">
|
||||
<div class="info-panel" style="display: flex; justify-content: space-between;">
|
||||
<div class="info-panel" style="display: flex; justify-content: space-between;width: 45%;">
|
||||
<div class="info-row">
|
||||
<span class="info-label">当前配方:</span>
|
||||
<span class="info-value">{{ processForm_uht.formula }}</span>
|
||||
|
@ -87,13 +94,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block" :data-device-id="pulpUHTData?.deviceId" @click="handleBlockClick(pulpUHTData?.deviceId)">
|
||||
<div class="flex-row">
|
||||
<div class="block">
|
||||
<div class="flex-row" :data-device-id="pulpUHTData?.deviceId"
|
||||
@click="handleBlockClick(pulpUHTData?.deviceId)" style="cursor: pointer;">
|
||||
<h2 class="juice-title">果肉 UHT</h2>
|
||||
</div>
|
||||
<div class="spacing"></div>
|
||||
<div class="UHT-item">
|
||||
<div class="info-panel" style="display: flex; justify-content: space-between;">
|
||||
<div class="info-panel" style="display: flex; justify-content: space-between;width: 45%;">
|
||||
<div class="info-row">
|
||||
<span class="info-label">当前配方:</span>
|
||||
<span class="info-value">{{ processForm_pulp.formula }}</span>
|
||||
|
@ -140,11 +148,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="upper-right">
|
||||
<div class="block" :data-device-id="juiceTank?.deviceId" @click="handleBlockClick(juiceTank?.deviceId)">
|
||||
<div class="block">
|
||||
<div class="flex-row">
|
||||
<h2 class="juice-title">果汁无菌罐</h2>
|
||||
<div class="tag-panel-2">
|
||||
<IxChip class="right-chip" background="#00BEDC" chip-color="#000028" variant="custom">
|
||||
<IxChip class="right-chip" background="#00BEDC" chip-color="#000028" variant="custom"
|
||||
:style="{ cursor: 'default' }">
|
||||
  已碱洗
|
||||
</IxChip>
|
||||
<IxChip class="right-chip" background="#00FFB9" chip-color="#000028" variant="custom">
|
||||
|
@ -153,30 +162,31 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="spacing"></div>
|
||||
<div class="right-info-panel">
|
||||
<div class="right-info-panel" style="padding-top: 1rem;">
|
||||
<div class="info-item">
|
||||
<span class="info-label">当前步骤:</span>
|
||||
<span class="info-label">{{ juiceTank.mixerStep }}</span>
|
||||
</div>
|
||||
<div class="info-item juice-item">
|
||||
<span>当前液位:</span>
|
||||
<div class="juice-item" style="padding: 0 0 0 1rem !important;">
|
||||
<span class="info-label">当前液位:</span>
|
||||
<div class="progress-bar">
|
||||
<div class="progress"
|
||||
:style="{ width: juiceTank.rate + '%', background: juiceTank.rate > 70 ? '#00D2A0' : juiceTank.rate > 50 ? '#FF9000' : juiceTank.rate > 30 ? '#FFD732' : '#FF0000' }">
|
||||
<span class="progress-text">{{ juiceTank.liquidLevel }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<img style="padding-left: 1rem;" v-if="juiceTank.rate < 10" src="@/assets/alarm.svg" />
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" class="arrow">
|
||||
<polygon points="0,0 15,7.5 0,15" fill="#00FFB9" />
|
||||
</svg>
|
||||
<span class="info-label" :style="{ color: '#00FFB9' }">果汁流量:{{ juiceTank.productFlowRate
|
||||
}}</span>
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block" :data-device-id="dynamicMixer?.deviceId" @click="handleBlockClick(dynamicMixer?.deviceId)">
|
||||
<div class="block">
|
||||
<div class="flex-row">
|
||||
<h2 class="juice-title">动态混合器</h2>
|
||||
<div class="tag-panel-2">
|
||||
|
@ -212,13 +222,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block" :data-device-id="pulpTank?.deviceId" @click="handleBlockClick(pulpTank?.deviceId)">
|
||||
<div class="block" :data-device-id="pulpTankData?.deviceId"
|
||||
@click="handleBlockClick(pulpTankData?.deviceId)">
|
||||
<div class="info-item">
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" class="arrow">
|
||||
<polygon points="0,0 15,7.5 0,15" fill="#00FFB9" />
|
||||
</svg>
|
||||
<span class="info-label" :style="{ color: '#00FFB9' }">果汁流量:{{ pulpTank.productFlowRate
|
||||
}}</span>
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex-row">
|
||||
<h2 class="juice-title">果肉无菌罐</h2>
|
||||
|
@ -236,7 +247,7 @@
|
|||
<span class="info-label">当前配方:</span>
|
||||
<span class="info-label">果汁配方</span>
|
||||
</div>
|
||||
<div class="info-item juice-item">
|
||||
<div class="juice-item">
|
||||
<span>当前液位:</span>
|
||||
<div class="progress-bar">
|
||||
<div class="progress"
|
||||
|
@ -244,6 +255,7 @@
|
|||
<span class="progress-text">{{ pulpTank.liquidLevel }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<img style="padding-left: 1rem;" v-if="pulpTank.rate < 10" src="@/assets/alarm.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -259,6 +271,7 @@
|
|||
<IxButton Outline @click="changeTimeRange('shift')">当班</IxButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacing"></div>
|
||||
<ProcessGanttChart ref="ganttChart" :process-data="formattedProcessData" :current-range="currentRange"
|
||||
@update-info="updateCurrentInfo" @segment-click="handleSegmentClick" />
|
||||
</div>
|
||||
|
@ -271,7 +284,19 @@
|
|||
<IxButton Outline> 流量:{{ productFlowRate }} </IxButton>
|
||||
<IxButton Outline> 配方:{{ formula }} </IxButton>
|
||||
<IxButton Outline> 持续时长:{{ duration }} </IxButton>
|
||||
<IxButton Outline> 请选择停机原因:{{ }} </IxButton>
|
||||
<IxButton Outline id="triggerId"> {{ selectedReason ? '停机原因:' + selectedReason : '请选择停机原因' }} </IxButton>
|
||||
<IxDropdown trigger="triggerId" class="drop-down">
|
||||
<IxDropdownHeader label="停机原因"></IxDropdownHeader>
|
||||
<IxDropdownItem label="灌注机温度过高" @click="handleReasonChange('灌注机温度过高')"></IxDropdownItem>
|
||||
<IxDropdownItem label="设备故障" @click="handleReasonChange('设备故障')"></IxDropdownItem>
|
||||
<IxDropdownItem label="原料不足" @click="handleReasonChange('原料不足')"></IxDropdownItem>
|
||||
<IxDivider></IxDivider>
|
||||
<IxDropdownItem label="其他" @click="handleOtherReasonClick"></IxDropdownItem>
|
||||
<div v-if="showOtherReasonInput" class="other-reason-input" @click.stop>
|
||||
<input type="text" v-model="otherReason" placeholder="请输入其他原因" />
|
||||
<IxButton @click="handleReasonConfirm">确认</IxButton>
|
||||
</div>
|
||||
</IxDropdown>
|
||||
<!-- <IxButton @click="showInfoMessage">Show Info Message</IxButton>
|
||||
<IxButton @click="showDangerMessage">Show Danger Message</IxButton>
|
||||
<IxButton @click="showWarningMessage">Show Warning Message</IxButton> -->
|
||||
|
@ -280,14 +305,28 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, getCurrentInstance } from 'vue'
|
||||
import { IxChip, IxButton } from '@siemens/ix-vue'; // 引入 Chip 组件
|
||||
import moment from'moment';
|
||||
import momentTimezone from'moment-timezone';
|
||||
import { ref, onMounted, getCurrentInstance, computed } from 'vue'
|
||||
import { IxChip, IxButton, IxDropdown, IxDropdownItem, IxDropdownHeader, IxDivider } from '@siemens/ix-vue'; // 引入 Chip 组件
|
||||
import { getCurrentReport, getHistoryReport, getGanttData } from '@/api/dashboard.js';
|
||||
import GradientProgressBar from '@/components/GradientProgressBar.vue'
|
||||
import ProcessStatusBar from '@/components/ProcessStatusBar.vue'
|
||||
import ProcessGanttChart from '@/components/ProcessGanttChart.vue'
|
||||
|
||||
// 设置为您期望的时区,比如 "Asia/Shanghai"
|
||||
const timezone = 'Asia/Shanghai';
|
||||
|
||||
// 响应式数据
|
||||
// 原始数据
|
||||
const juiceData = ref({}) // 果汁调配数据
|
||||
const pulpData = ref({}) // 果肉调配数据
|
||||
const uhtData = ref({}) // 果汁杀菌数据
|
||||
const pulpUHTData = ref({}) // 果肉杀菌数据
|
||||
const juiceTankData = ref({}) // 果汁无菌罐数据
|
||||
const pulpTankData = ref({}) // 果肉无菌罐数据
|
||||
const dynamicMixerData = ref({}) // 动态混合器数据
|
||||
|
||||
const currentTime = ref('')
|
||||
const totalTrafficJuice = ref(0); // 果汁调配 累计流量
|
||||
const totalTrafficPulp = ref(0); // 果汁调配 累计流量
|
||||
|
@ -298,10 +337,6 @@ const processForm_pulp = ref({})// 果肉UHT
|
|||
const juiceTank = ref({})// 果汁无菌罐
|
||||
const pulpTank = ref({})// 果肉无菌罐
|
||||
const dynamicMixer = ref({})// 动态混合器
|
||||
const juiceData = ref({}) // 果汁调配数据
|
||||
const pulpData = ref({}) // 果肉调配数据
|
||||
const uhtData = ref({}) // 果汁杀菌数据
|
||||
const pulpUHTData = ref({}) // 果肉杀菌数据
|
||||
|
||||
const statuses = ref([
|
||||
{ id: 1, label: '已碱洗', color: '#00BEDC' },
|
||||
|
@ -313,17 +348,17 @@ const statuses = ref([
|
|||
const processData = ref([])
|
||||
|
||||
// 新增函数,转换时间格式
|
||||
const convertToGMTPlus8 = (timeString) => {
|
||||
const date = new Date(timeString);
|
||||
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
||||
const formatTime = (timeString) => {
|
||||
const momentDate = moment.utc(timeString);
|
||||
return momentDate.format('YYYY-MM-DD HH:mm');
|
||||
}
|
||||
|
||||
// 新增函数,统一日期格式
|
||||
const formatDates = (data) => {
|
||||
return data.map(item => {
|
||||
const newItem = { ...item };
|
||||
newItem.beginTime = convertToGMTPlus8(item.beginTime);
|
||||
newItem.endTime = convertToGMTPlus8(item.endTime);
|
||||
newItem.beginTime = formatTime(item.beginTime);
|
||||
newItem.endTime = formatTime(item.endTime);
|
||||
return newItem;
|
||||
});
|
||||
}
|
||||
|
@ -344,7 +379,14 @@ const ganttChart = ref(null); // 增加 ganttChart 引用
|
|||
|
||||
// 全局响应式变量
|
||||
const globalDeviceId = ref(null);
|
||||
const globalTime = ref(new Date().toISOString());
|
||||
const globalTime = computed(() => {
|
||||
return moment().tz(timezone).format('YYYY-MM-DD HH:mm');
|
||||
});
|
||||
|
||||
// 新增响应式变量
|
||||
const selectedReason = ref(''); // 新增响应式变量
|
||||
const showOtherReasonInput = ref(false);
|
||||
const otherReason = ref('');
|
||||
|
||||
// 方法
|
||||
const removeStatus = (id) => {
|
||||
|
@ -352,9 +394,9 @@ const removeStatus = (id) => {
|
|||
};
|
||||
|
||||
const updateCurrentInfo = (segment) => {
|
||||
currentStatus.value = segment.status;
|
||||
startTimeFormatted.value = convertToGMTPlus8(segment.beginTime);
|
||||
endTimeFormatted.value = convertToGMTPlus8(segment.endTime);
|
||||
currentStatus.value = segment.deviceStatus;
|
||||
startTimeFormatted.value = formatTime(segment.beginTime);
|
||||
endTimeFormatted.value = formatTime(segment.endTime);
|
||||
duration.value = segment.duration;
|
||||
productFlowRate.value = segment.productFlowRate;
|
||||
formula.value = segment.formula;
|
||||
|
@ -373,8 +415,8 @@ const changeTimeRange = (range) => {
|
|||
};
|
||||
|
||||
const updateTime = () => {
|
||||
const now = new Date()
|
||||
currentTime.value = convertToGMTPlus8(now.toISOString())
|
||||
const now = moment();
|
||||
currentTime.value = now.format('YYYY-MM-DD HH:mm');
|
||||
}
|
||||
//#TODO:主数据
|
||||
// 处理接口返回的数据
|
||||
|
@ -388,6 +430,7 @@ const processDataFromAPI = (apiData) => {
|
|||
data: {
|
||||
id: item.data.id || 0,
|
||||
weight: item.data.weight || 0,
|
||||
capacity: item.data.capacity,
|
||||
status: item.data.status || '',
|
||||
productFlowRate: item.data.productFlowRate || 0,
|
||||
name: item.data.name || '',
|
||||
|
@ -402,10 +445,22 @@ const processDataFromAPI = (apiData) => {
|
|||
return processedData;
|
||||
};
|
||||
|
||||
// 筛选数据并合并第二层 data
|
||||
const processHistoryDataFromAPI = processDataFromAPI; // 复用 processDataFromAPI 函数
|
||||
|
||||
const getDataByName = (data, name) => {
|
||||
const filteredData = data.filter(item => item.name === name);
|
||||
const mergedData = filteredData.map(item => item.data);
|
||||
if (filteredData.length === 0) {
|
||||
return {
|
||||
name,
|
||||
deviceId: null,
|
||||
totalTraffic: 0,
|
||||
data: []
|
||||
};
|
||||
}
|
||||
const mergedData = filteredData.map(item => ({
|
||||
...item.data,
|
||||
deviceId: item.deviceId // 增加 deviceId 字段
|
||||
}));
|
||||
return {
|
||||
name,
|
||||
deviceId: filteredData[0].deviceId,
|
||||
|
@ -414,79 +469,100 @@ const getDataByName = (data, name) => {
|
|||
};
|
||||
};
|
||||
|
||||
const updateData = (processedData) => {
|
||||
juiceData.value = getDataByName(processedData, "果汁调配");
|
||||
pulpData.value = getDataByName(processedData, "果肉调配");
|
||||
uhtData.value = getDataByName(processedData, "果汁杀菌");
|
||||
pulpUHTData.value = getDataByName(processedData, "果肉杀菌");
|
||||
juiceTankData.value = getDataByName(processedData, "果汁无菌罐");
|
||||
pulpTankData.value = getDataByName(processedData, "果肉无菌罐");
|
||||
dynamicMixerData.value = getDataByName(processedData, "动态混合器");
|
||||
|
||||
// 设置默认值
|
||||
if (juiceData.value.deviceId) {
|
||||
globalDeviceId.value = juiceData.value.deviceId;
|
||||
}
|
||||
// 累计流量
|
||||
totalTrafficJuice.value = juiceData.value.totalTraffic;
|
||||
totalTrafficPulp.value = pulpData.value.totalTraffic;
|
||||
|
||||
if (juiceData.value.data.length > 0) {
|
||||
progressList.value = juiceData.value.data.map(item => ({
|
||||
name: item.name,
|
||||
deviceId: item.deviceId,
|
||||
value: item.weight,
|
||||
rate: item.weight === 0 ? 0 : (item.weight / item.capacity) * 100
|
||||
}));
|
||||
console.log("🚀 ~ updateData ~ progressList.value:", progressList.value)
|
||||
|
||||
}
|
||||
if (pulpData.value.data.length > 0) {
|
||||
innerProgressList.value = pulpData.value.data.map(item => ({
|
||||
name: item.name,
|
||||
deviceId: item.deviceId,
|
||||
value: item.weight,
|
||||
rate: item.weight === 0 ? 0 : (item.weight / item.capacity) * 100
|
||||
}));
|
||||
}
|
||||
// 更新 UHT 数据
|
||||
if (uhtData.value.data.length > 0) {
|
||||
processForm_uht.value = {
|
||||
formula: uhtData.value.data[0].formula,
|
||||
totalTraffic: uhtData.value.totalTraffic,
|
||||
status: uhtData.value.data[0].status,
|
||||
productFlowRate: uhtData.value.data[0].productFlowRate,
|
||||
mixerStep: uhtData.value.data[0].mixerStep,
|
||||
temperature: uhtData.value.data[0].temperature
|
||||
};
|
||||
}
|
||||
if (pulpUHTData.value.data.length > 0) {
|
||||
processForm_pulp.value = {
|
||||
formula: pulpUHTData.value.data[0].formula,
|
||||
totalTraffic: pulpUHTData.value.totalTraffic,
|
||||
status: pulpUHTData.value.data[0].status,
|
||||
productFlowRate: pulpUHTData.value.data[0].productFlowRate,
|
||||
mixerStep: pulpUHTData.value.data[0].mixerStep,
|
||||
temperature: pulpUHTData.value.data[0].temperature
|
||||
};
|
||||
}
|
||||
// 更新果汁无菌罐数据
|
||||
if (juiceTankData.value.data.length > 0) {
|
||||
juiceTank.value = {
|
||||
mixerStep: juiceTankData.value.data[0].mixerStep,
|
||||
rate: juiceTankData.value.data[0].liquidLevel === 0 ? 0 : (juiceTankData.value.data[0].liquidLevel / juiceTankData.value.data[0].capacity) * 100,
|
||||
liquidLevel: juiceTankData.value.data[0].liquidLevel,
|
||||
productFlowRate: juiceTankData.value.data[0].productFlowRate
|
||||
};
|
||||
}
|
||||
if (pulpTankData.value.data.length > 0) {
|
||||
pulpTank.value = {
|
||||
mixerStep: pulpTankData.value.data[0].mixerStep,
|
||||
rate: pulpTankData.value.data[0].liquidLevel === 0 ? 0 : (pulpTankData.value.data[0].liquidLevel / pulpTankData.value.data[0].capacity) * 100,
|
||||
liquidLevel: pulpTankData.value.data[0].liquidLevel,
|
||||
productFlowRate: pulpTankData.value.data[0].productFlowRate
|
||||
};
|
||||
}
|
||||
if (dynamicMixerData.value.data.length > 0) {
|
||||
dynamicMixer.value = {
|
||||
formula: dynamicMixerData.value.data[0].formula,
|
||||
status: dynamicMixerData.value.data[0].status,
|
||||
liquidLevel: dynamicMixerData.value.data[0].liquidLevel,
|
||||
mixerStep: dynamicMixerData.value.data[0].mixerStep,
|
||||
temperature: dynamicMixerData.value.data[0].temperature,
|
||||
productFlowRate: dynamicMixerData.value.data[0].productFlowRate
|
||||
};
|
||||
}
|
||||
if (processedData.data !== undefined) showInfoMessage("数据刷新成功!");
|
||||
else showWarningMessage("未查询到历史数据!");
|
||||
};
|
||||
|
||||
// 读取接口数据
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await getCurrentReport();
|
||||
if (response.code === 200) {
|
||||
const processedData = processDataFromAPI(response);
|
||||
// 处理后的数据可以赋值给相应的响应式变量
|
||||
juiceData.value = getDataByName(processedData, "果汁调配");
|
||||
|
||||
// 设置默认值
|
||||
globalDeviceId.value = juiceData.value.deviceId;
|
||||
|
||||
pulpData.value = getDataByName(processedData, "果肉调配");
|
||||
uhtData.value = getDataByName(processedData, "果汁杀菌");
|
||||
pulpUHTData.value = getDataByName(processedData, "果肉杀菌");
|
||||
juiceTank.value = getDataByName(processedData, "果汁无菌罐");
|
||||
pulpTank.value = getDataByName(processedData, "果肉无菌罐");
|
||||
dynamicMixer.value = getDataByName(processedData, "动态混合器");
|
||||
console.log("🚀 ~ fetchData ~ dynamicMixer:", dynamicMixer)
|
||||
|
||||
// 累计流量
|
||||
totalTrafficJuice.value = juiceData.value.totalTraffic;
|
||||
totalTrafficPulp.value = pulpData.value.totalTraffic;
|
||||
|
||||
progressList.value = juiceData.value.data.map(item => ({
|
||||
name: item.name,
|
||||
value: item.productFlowRate,
|
||||
rate: item.productFlowRate === 0 ? 0 : (item.productFlowRate / item.weight) * 100
|
||||
}));
|
||||
innerProgressList.value = pulpData.value.data.map(item => ({
|
||||
name: item.name,
|
||||
value: item.productFlowRate,
|
||||
rate: item.productFlowRate === 0 ? 0 : (item.productFlowRate / item.weight) * 100
|
||||
}));
|
||||
// 更新 UHT 数据
|
||||
processForm_uht.value = {
|
||||
formula: uhtData.value.data[0].formula,
|
||||
totalTraffic: uhtData.value.totalTraffic,
|
||||
status: uhtData.value.data[0].status,
|
||||
productFlowRate: uhtData.value.data[0].productFlowRate,
|
||||
mixerStep: uhtData.value.data[0].mixerStep,
|
||||
temperature: uhtData.value.data[0].temperature
|
||||
};
|
||||
processForm_pulp.value = {
|
||||
formula: pulpUHTData.value.data[0].formula,
|
||||
totalTraffic: pulpUHTData.value.totalTraffic,
|
||||
status: pulpUHTData.value.data[0].status,
|
||||
productFlowRate: pulpUHTData.value.data[0].productFlowRate,
|
||||
mixerStep: pulpUHTData.value.data[0].mixerStep,
|
||||
temperature: pulpUHTData.value.data[0].temperature
|
||||
};
|
||||
// 更新果汁无菌罐数据
|
||||
juiceTank.value = {
|
||||
mixerStep: juiceTank.value.data[0].mixerStep,
|
||||
rate: juiceTank.value.data[0].liquidLevel === 0 ? 0 : (juiceTank.value.data[0].liquidLevel / juiceTank.value.data[0].weight) * 100,
|
||||
liquidLevel: juiceTank.value.data[0].liquidLevel,
|
||||
productFlowRate: juiceTank.value.data[0].productFlowRate
|
||||
};
|
||||
pulpTank.value = {
|
||||
mixerStep: pulpTank.value.data[0].mixerStep,
|
||||
rate: pulpTank.value.data[0].liquidLevel === 0 ? 0 : (pulpTank.value.data[0].liquidLevel / pulpTank.value.data[0].weight) * 100,
|
||||
liquidLevel: pulpTank.value.data[0].liquidLevel,
|
||||
productFlowRate: pulpTank.value.data[0].productFlowRate
|
||||
};
|
||||
dynamicMixer.value = {
|
||||
formula: dynamicMixer.value.data[0].formula,
|
||||
status: dynamicMixer.value.data[0].status,
|
||||
liquidLevel: dynamicMixer.value.data[0].liquidLevel,
|
||||
mixerStep: dynamicMixer.value.data[0].mixerStep,
|
||||
temperature: dynamicMixer.value.data[0].temperature,
|
||||
productFlowRate: dynamicMixer.value.data[0].productFlowRate
|
||||
};
|
||||
console.log("🚀 ~ fetchData ~ dynamicMixer:", dynamicMixer)
|
||||
updateData(processedData);
|
||||
} else {
|
||||
console.error('Error fetching data:', response.message);
|
||||
}
|
||||
|
@ -495,26 +571,85 @@ const fetchData = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const fetchHistoryData = async (datetime) => {
|
||||
try {
|
||||
const response = await getHistoryReport(datetime);
|
||||
if (response.code === 200) {
|
||||
const processedData = processHistoryDataFromAPI(response);
|
||||
updateData(processedData);
|
||||
} else {
|
||||
console.error('Error fetching history data:', response.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching history data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const processGanttDataResponse = (response) => {
|
||||
if (response.data) {
|
||||
const ganttData = response.data.map(item => ({
|
||||
deviceId: item.deviceId,
|
||||
duration: item.duration,
|
||||
beginTime: formatTime(item.beginTime),
|
||||
endTime: formatTime(item.endTime),
|
||||
deviceStatus: item.deviceStatus,
|
||||
mixerStep: item.mixerStep,
|
||||
productFlowRate: item.productFlowRate,
|
||||
formula: item.formula,
|
||||
lineId: item.lineId
|
||||
}));
|
||||
processData.value = ganttData;
|
||||
console.log("🚀 ~ processGanttDataResponse ~ processData.value:", processData.value)
|
||||
|
||||
formattedProcessData.value = formatDates(ganttData);
|
||||
if (ganttChart.value && ganttChart.value.updateChart) {
|
||||
ganttChart.value.updateChart();
|
||||
}
|
||||
showInfoMessage('' + ganttData.length + ' 条数据已刷新!');
|
||||
} else {
|
||||
showWarningMessage('未查询到数据!');
|
||||
processData.value = [];
|
||||
formattedProcessData.value = [];
|
||||
if (ganttChart.value && ganttChart.value.updateChart) {
|
||||
ganttChart.value.updateChart();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const fetchGanttData = async () => {
|
||||
try {
|
||||
const response = await getGanttData(globalDeviceId.value, globalTime.value);
|
||||
if (response.code === 200) {
|
||||
const ganttData = response.data.map(item => ({
|
||||
deviceId: item.deviceId,
|
||||
duration: item.duration,
|
||||
beginTime: convertToGMTPlus8(item.beginTime),
|
||||
endTime: convertToGMTPlus8(item.endTime),
|
||||
status: item.status,
|
||||
mixerStep: item.mixerStep,
|
||||
productFlowRate: item.productFlowRate,
|
||||
formula: item.formula,
|
||||
lineId: item.lineId
|
||||
}));
|
||||
processData.value = ganttData;
|
||||
formattedProcessData.value = formatDates(ganttData); // 确保数据格式化后赋值给 formattedProcessData
|
||||
} else {
|
||||
// 数据不存在
|
||||
if (!globalDeviceId.value) {
|
||||
console.error('Device ID is null');
|
||||
return;
|
||||
}
|
||||
// 生成假数据
|
||||
// const fakeData = [
|
||||
// {
|
||||
// deviceId: globalDeviceId.value,
|
||||
// duration: '2h',
|
||||
// beginTime: '2025-02-26 08:00',
|
||||
// endTime: '2025-02-26 10:00',
|
||||
// deviceStatus: 'running',
|
||||
// mixerStep: '混合',
|
||||
// productFlowRate: 500,
|
||||
// formula: '配方A',
|
||||
// lineId: 1
|
||||
// },
|
||||
// {
|
||||
// deviceId: globalDeviceId.value,
|
||||
// duration: '1h',
|
||||
// beginTime: '2025-02-26 10:00',
|
||||
// endTime: '2025-02-26 11:00',
|
||||
// deviceStatus: 'cleaning',
|
||||
// mixerStep: '等待',
|
||||
// productFlowRate: 0,
|
||||
// formula: '配方B',
|
||||
// lineId: 1
|
||||
// }
|
||||
// ];
|
||||
// processGanttDataResponse({ data: fakeData });
|
||||
const response = await getGanttData(globalDeviceId.value, globalTime.value);
|
||||
processGanttDataResponse(response);
|
||||
} catch (error) {
|
||||
console.error('Error fetching Gantt data:', error);
|
||||
}
|
||||
|
@ -522,31 +657,18 @@ const fetchGanttData = async () => {
|
|||
|
||||
const handleBlockClick = async (deviceId) => {
|
||||
try {
|
||||
globalDeviceId.value = deviceId;
|
||||
const currentTime = new Date().toISOString();
|
||||
globalTime.value = currentTime;
|
||||
const response = await getGanttData(deviceId, currentTime);
|
||||
if (response.code === 200) {
|
||||
const ganttData = response.data.map(item => ({
|
||||
deviceId: item.deviceId,
|
||||
duration: item.duration,
|
||||
beginTime: convertToGMTPlus8(item.beginTime),
|
||||
endTime: convertToGMTPlus8(item.endTime),
|
||||
status: item.status,
|
||||
mixerStep: item.mixerStep,
|
||||
productFlowRate: item.productFlowRate,
|
||||
formula: item.formula,
|
||||
lineId: item.lineId
|
||||
}));
|
||||
processData.value = ganttData;
|
||||
formattedProcessData.value = formatDates(ganttData);
|
||||
if (ganttChart.value && ganttChart.value.updateChart) {
|
||||
ganttChart.value.updateChart();
|
||||
}
|
||||
showInfoMessage();
|
||||
} else {
|
||||
console.error('Error fetching Gantt data:', response.message);
|
||||
if (!deviceId) {
|
||||
showWarningMessage('Device ID is null');
|
||||
return;
|
||||
}
|
||||
globalDeviceId.value = deviceId;
|
||||
const currentTime = moment();
|
||||
const formattedTime = currentTime.format('YYYY-MM-DD HH:mm');
|
||||
console.log("🚀 ~ handleBlockClick ~ formattedTime:", formattedTime)
|
||||
|
||||
globalTime.value = formattedTime;
|
||||
const response = await getGanttData(deviceId, formattedTime);
|
||||
processGanttDataResponse(response);
|
||||
} catch (error) {
|
||||
console.error('Error fetching Gantt data:', error);
|
||||
}
|
||||
|
@ -568,21 +690,60 @@ const getHistory = async (datetime) => {
|
|||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const showInfoMessage = () => {
|
||||
proxy.$message.info('数据写入成功!');
|
||||
const showInfoMessage = (message) => {
|
||||
proxy.$message.info(message);
|
||||
};
|
||||
|
||||
const showDangerMessage = () => {
|
||||
proxy.$message.danger('数据未成功写入!');
|
||||
const showInfoMessageWithAction = (message, action) => {
|
||||
proxy.$message.$confirm(message, action);
|
||||
};
|
||||
|
||||
const showWarningMessage = () => {
|
||||
proxy.$message.warning('数据写入异常!');
|
||||
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 handleReasonChange = (reason) => {
|
||||
if (!startTimeFormatted.value) {
|
||||
showWarningMessage('请先点击甘特图中的数据块,再设置停机原因!');
|
||||
return;
|
||||
}
|
||||
showConfirmMessage(
|
||||
'确定要设置停机原因为 "' + reason + '" 吗?',
|
||||
() => {
|
||||
selectedReason.value = reason;
|
||||
showInfoMessage('停机原因已设置为:' + reason);
|
||||
},
|
||||
() => {
|
||||
showWarningMessage('操作已取消')
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const handleOtherReasonClick = (event) => {
|
||||
event.stopPropagation();
|
||||
showOtherReasonInput.value = true;
|
||||
};
|
||||
|
||||
const handleReasonConfirm = () => {
|
||||
if (!otherReason.value) {
|
||||
showWarningMessage('请输入其他原因');
|
||||
return;
|
||||
}
|
||||
handleReasonChange(otherReason.value);
|
||||
showOtherReasonInput.value = false;
|
||||
};
|
||||
|
||||
// 生命周期钩子
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
onMounted(async () => {
|
||||
await fetchData();
|
||||
fetchGanttData();
|
||||
updateTime();
|
||||
setInterval(updateTime, 1000);
|
||||
|
@ -593,18 +754,23 @@ onMounted(() => {
|
|||
|
||||
// 监听 update-history 事件
|
||||
window.addEventListener('update-history', (event) => {
|
||||
alert('接收到 update-history 事件');
|
||||
getHistory(event.detail);
|
||||
fetchHistoryData(event.detail);
|
||||
});
|
||||
|
||||
// 监听 reset 事件
|
||||
window.addEventListener('reset', (event) => {
|
||||
fetchData();
|
||||
fetchGanttData();
|
||||
});
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 全局样式 */
|
||||
.dashboard-container {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
@ -614,15 +780,15 @@ onMounted(() => {
|
|||
overflow: hidden;
|
||||
color: white;
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
font-size: 1.2rem;
|
||||
/* 调大全局字体大小 */
|
||||
font-size: 1rem; /* 统一字体大小 */
|
||||
}
|
||||
|
||||
/* 上部区域样式 */
|
||||
.upper-section {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
height: 60%;
|
||||
/* 调整高度 */
|
||||
}
|
||||
|
||||
/* 上左区域样式 */
|
||||
|
@ -653,52 +819,54 @@ onMounted(() => {
|
|||
.spacing {
|
||||
height: 0.125rem;
|
||||
background-color: #000028;
|
||||
margin: 1rem 0;
|
||||
margin: 0.5rem 0;
|
||||
/* 调整间隔 */
|
||||
}
|
||||
|
||||
/* 进度条样式 */
|
||||
.juice-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* justify-content: space-around; */
|
||||
margin: 2rem 1rem 3rem 1rem;
|
||||
padding: 1rem 1rem 1rem 1rem;
|
||||
height: 22%;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 3rem;
|
||||
height: 2.5rem;
|
||||
/* 调整高度 */
|
||||
}
|
||||
|
||||
/* 标题和流量标签样式 */
|
||||
.juice-title {
|
||||
font-size: 1.2rem;
|
||||
/* 调大标题字体大小 */
|
||||
margin: 1rem 0 0 1rem;
|
||||
font-size: 1rem; /* 统一字体大小 */
|
||||
margin: 0.5rem 0 0 1rem;
|
||||
/* 调整间距 */
|
||||
}
|
||||
|
||||
.flow-label {
|
||||
font-size: 1rem;
|
||||
/* 调大流量标签字体大小 */
|
||||
margin: 1rem 1rem 0 0;
|
||||
font-size: 1rem; /* 统一字体大小 */
|
||||
margin: 0.5rem 1rem 0 0;
|
||||
/* 调整间距 */
|
||||
}
|
||||
|
||||
.juice-name {
|
||||
font-size: 1rem;
|
||||
/* 调大果汁名称字体大小 */
|
||||
font-size: 1rem; /* 统一字体大小 */
|
||||
}
|
||||
|
||||
.juice-value {
|
||||
font-size: 1.2rem;
|
||||
/* 调大果汁值字体大小 */
|
||||
font-size: 1rem; /* 统一字体大小 */
|
||||
}
|
||||
|
||||
/* 进度条样式 */
|
||||
.progress-bar {
|
||||
height: 1.25rem;
|
||||
height: 1rem;
|
||||
/* 调整高度 */
|
||||
background: #000028;
|
||||
border-radius: 0.625rem;
|
||||
border-radius: 0.5rem;
|
||||
/* 调整圆角 */
|
||||
width: 70%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
@ -707,18 +875,17 @@ onMounted(() => {
|
|||
/* 进度样式 */
|
||||
.progress {
|
||||
height: 100%;
|
||||
border-radius: 0.625rem;
|
||||
border-radius: 0.5rem;
|
||||
/* 调整圆角 */
|
||||
transition: width 0.3s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
position: absolute;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #000028;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
text-shadow: 0.0625rem 0.0625rem 0.125rem rgba(0, 0, 0, 0.5);
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@ -733,7 +900,8 @@ onMounted(() => {
|
|||
background: #23233C;
|
||||
border: 0.0625rem solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 0.5rem;
|
||||
min-height: 6.25rem;
|
||||
min-height: 5rem;
|
||||
/* 调整最小高度 */
|
||||
box-shadow: 0 0.25rem 0.375rem rgba(0, 0, 0, 0.2);
|
||||
text-align: center;
|
||||
margin: 0.5rem;
|
||||
|
@ -747,16 +915,17 @@ onMounted(() => {
|
|||
|
||||
/* 恢复 info-panel 样式 */
|
||||
.info-panel {
|
||||
width: 30%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 1rem 1rem 0 0;
|
||||
}
|
||||
|
||||
/* 信息行样式 */
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin: 0 0 3rem 1rem;
|
||||
margin: 0 0 2rem 1rem;
|
||||
/* 调整间距 */
|
||||
}
|
||||
|
||||
/* 信息项样式 */
|
||||
|
@ -767,8 +936,7 @@ onMounted(() => {
|
|||
|
||||
/* 信息标签样式 */
|
||||
.info-label {
|
||||
font-size: 1rem;
|
||||
/* 调大信息标签字体大小 */
|
||||
font-size: 1rem; /* 统一字体大小 */
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
@ -776,12 +944,11 @@ onMounted(() => {
|
|||
.tag-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 5rem;
|
||||
}
|
||||
|
||||
:deep(ix-chip) .container.custom {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
:deep(.ix-chip) {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
:deep(ix-chip) .container.custom {
|
||||
|
@ -793,25 +960,29 @@ onMounted(() => {
|
|||
.upper-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 40%;
|
||||
width: 30%;
|
||||
/* 调整宽度 */
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 右侧信息行样式 */
|
||||
.info-item {
|
||||
margin: 0 0 0.875rem 1rem;
|
||||
margin: 0 0 0.5rem 1rem;
|
||||
/* 调整间距 */
|
||||
}
|
||||
|
||||
/* 左侧 IxChip 样式 */
|
||||
.left-chip {
|
||||
margin: 0.5rem;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 右侧 IxChip 样式 */
|
||||
.right-chip {
|
||||
margin: 1rem 0.5rem 0 0;
|
||||
margin: 0.5rem 0.5rem 0 0;
|
||||
width: 95%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tag-panel-2 {
|
||||
|
@ -827,14 +998,23 @@ onMounted(() => {
|
|||
/* 下部区域样式 */
|
||||
.lower-section {
|
||||
width: 100%;
|
||||
height: 20.5%;
|
||||
height: 20%;
|
||||
/* 调整高度 */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 甘特图块样式 */
|
||||
.gantt-block {
|
||||
height: 12.5rem;
|
||||
height: 10rem;
|
||||
/* 调整高度 */
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 箭头样式 */
|
||||
.arrow {
|
||||
width: 0;
|
||||
/* 调整高度 */
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -854,7 +1034,8 @@ onMounted(() => {
|
|||
width: 100%;
|
||||
gap: 0.625rem;
|
||||
justify-content: space-between;
|
||||
/* 添加此行 */
|
||||
height: 10%;
|
||||
margin: 1rem 0 0 0;
|
||||
}
|
||||
|
||||
.lower-footer :deep(ix-button) {
|
||||
|
@ -862,6 +1043,10 @@ onMounted(() => {
|
|||
max-width: calc(25% - 1.25rem);
|
||||
margin: 0.3125rem;
|
||||
text-align: center;
|
||||
/* 添加此行 */
|
||||
}
|
||||
|
||||
.drop-down {
|
||||
width: calc(25% - 1.25rem);
|
||||
background-color: #23233C;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<div class="inspection-container">
|
||||
<div class="header">
|
||||
<div class="header_left">
|
||||
<ix-select v-model="state.selectedShift" :options="shiftOptions"></ix-select>
|
||||
<ix-select v-model="state.selectedOption1" :options="state.options1"></ix-select>
|
||||
<ix-select v-model="state.selectedOption2" :options="state.options2"></ix-select>
|
||||
<IxButton> 查询 </IxButton>
|
||||
<ix-select v-model="state.selectedShift" :options="shiftOptions" label="label" value="value"></ix-select>
|
||||
<ix-select v-model="state.selectedOption1" :options="state.options1" label="label" value="value"></ix-select>
|
||||
<ix-select v-model="state.selectedOption2" :options="state.options2" label="label" value="value"></ix-select>
|
||||
<IxButton @click="fetchInspectionData"> 查询 </IxButton>
|
||||
<IxButton> 导出全部 </IxButton>
|
||||
</div>
|
||||
<div class="header_right">
|
||||
|
@ -20,7 +20,7 @@
|
|||
<IxEventList>
|
||||
<IxEventListItem class="testbg1">
|
||||
<div class="table-row">
|
||||
<span class="fixed-width"></span>
|
||||
<span class="fixed-width title-width"></span>
|
||||
<span class="fixed-width"></span>
|
||||
<span class="fixed-width"></span>
|
||||
<span class="fixed-width"></span>
|
||||
|
@ -32,21 +32,21 @@
|
|||
</IxEventListItem>
|
||||
<IxEventListItem class="testbg1">
|
||||
<div class="table-row-1">
|
||||
<span class="header-row">点检项目</span>
|
||||
<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">
|
||||
<span class="header-row" v-for="hour in hours" :key="hour" :style="{ backgroundColor: '#00FFB9', color: '#000028' }">
|
||||
{{ hour }}
|
||||
</span>
|
||||
</div>
|
||||
</IxEventListItem>
|
||||
<IxEventListItem v-for="(item, index) in inspectionItems" :key="index" color="color-success" class="testbg">
|
||||
<div class="table-row">
|
||||
<span class="fixed-width">{{ item.name }}</span>
|
||||
<span class="fixed-width title-width">{{ item.label }}</span>
|
||||
<span class="fixed-width">--</span>
|
||||
<span class="fixed-width">{{ item.reference }}</span>
|
||||
<span class="fixed-width">{{ item.current }}</span>
|
||||
<span class="fixed-width">{{ item.current }}</span> <!-- 确保这里绑定的是 item.current -->
|
||||
<span class="fixed-width" v-for="hour in hours" :key="hour">
|
||||
{{ item.data[hour] || '--' }}
|
||||
</span>
|
||||
|
@ -60,9 +60,11 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, getCurrentInstance } from 'vue';
|
||||
import { ref, computed, getCurrentInstance, onMounted } from 'vue';
|
||||
import { IxDatetimePicker, IxButton, IxDivider, IxDropdown, IxDropdownHeader, IxDropdownItem, IxEventList, IxEventListItem, IxSelect } from '@siemens/ix-vue';
|
||||
import InspectionForm from './InspectionForm.vue';
|
||||
import { getInspectionCurrent, getInspectionData } from '@/api/inspection';
|
||||
import { color } from 'echarts';
|
||||
|
||||
// 定义班次选项
|
||||
const shiftOptions = [
|
||||
|
@ -117,240 +119,28 @@ const hours = computed(() => {
|
|||
|
||||
// JSON 数据
|
||||
const data = {
|
||||
juiceFlow: {
|
||||
'07:00': 123456,
|
||||
'08:00': 234567,
|
||||
'09:00': 345678,
|
||||
'10:00': 456789,
|
||||
'11:00': 567890,
|
||||
'12:00': 678901,
|
||||
'13:00': 789012,
|
||||
'14:00': 890123,
|
||||
'15:00': 901234,
|
||||
'16:00': 123456,
|
||||
'17:00': 234567,
|
||||
'18:00': 345678,
|
||||
'19:00': 456789,
|
||||
},
|
||||
pulpFlow: {
|
||||
'07:00': 654321,
|
||||
'08:00': 543210,
|
||||
'09:00': 432109,
|
||||
'10:00': 321098,
|
||||
'11:00': 210987,
|
||||
'12:00': 109876,
|
||||
'13:00': 987654,
|
||||
'14:00': 876543,
|
||||
'15:00': 765432,
|
||||
'16:00': 654321,
|
||||
'17:00': 543210,
|
||||
'18:00': 432109,
|
||||
},
|
||||
sterile: {
|
||||
'07:00': 111222,
|
||||
'08:00': 222111,
|
||||
'09:00': 333222,
|
||||
'10:00': 444333,
|
||||
'11:00': 555444,
|
||||
'12:00': 666555,
|
||||
'13:00': 777666,
|
||||
'14:00': 888777,
|
||||
'15:00': 999888,
|
||||
'16:00': 111222,
|
||||
'17:00': 222111,
|
||||
'18:00': 333222,
|
||||
},
|
||||
clean: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test1: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test2: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test3: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test4: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test5: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test6: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test7: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test8: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test9: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test10: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
test11: {
|
||||
'07:00': 333444,
|
||||
'08:00': 444555,
|
||||
'09:00': 555666,
|
||||
'10:00': 666777,
|
||||
'11:00': 777888,
|
||||
'12:00': 888999,
|
||||
'13:00': 999000,
|
||||
'14:00': 111111,
|
||||
'15:00': 222222,
|
||||
'16:00': 333333,
|
||||
'17:00': 444444,
|
||||
'18:00': 555555,
|
||||
},
|
||||
juiceFlow: {},
|
||||
pulpFlow: {},
|
||||
sterile: {},
|
||||
clean: {},
|
||||
test1: {},
|
||||
test2: {},
|
||||
test3: {},
|
||||
test4: {},
|
||||
test5: {},
|
||||
test6: {},
|
||||
test7: {},
|
||||
test8: {},
|
||||
test9: {},
|
||||
test10: {},
|
||||
test11: {},
|
||||
};
|
||||
|
||||
const inspectionItems = [
|
||||
{ name: '果汁调配状态', reference: 727, current: 727, data: data.juiceFlow },
|
||||
{ name: '果肉调配状态', reference: 800, current: 800, data: data.pulpFlow },
|
||||
{ name: '无菌状态', reference: 128, current: 128, data: data.sterile },
|
||||
{ name: '清洁状态', reference: 727, current: 727, data: data.clean },
|
||||
{ name: '测试1', reference: 123, current: 123, data: data.test1 },
|
||||
{ name: '测试2', reference: 456, current: 456, data: data.test2 },
|
||||
{ name: '测试3', reference: 789, current: 789, data: data.test3 },
|
||||
{ name: '测试4', reference: 101, current: 101, data: data.test4 },
|
||||
{ name: '测试5', reference: 202, current: 202, data: data.test5 },
|
||||
{ name: '测试6', reference: 303, current: 303, data: data.test6 },
|
||||
{ name: '测试7', reference: 404, current: 404, data: data.test7 },
|
||||
{ name: '测试8', reference: 505, current: 505, data: data.test8 },
|
||||
{ name: '测试9', reference: 606, current: 606, data: data.test9 },
|
||||
{ name: '测试10', reference: 707, current: 707, data: data.test10 },
|
||||
{ name: '测试11', reference: 808, current: 808, data: data.test11 },
|
||||
];
|
||||
const inspectionItems = ref([]);
|
||||
|
||||
// 点检按钮点击事件
|
||||
const handleInspection = (index) => {
|
||||
selectedItemName.value = inspectionItems[index].name;
|
||||
selectedItemName.value = inspectionItems.value[index].name;
|
||||
showForm.value = true;
|
||||
};
|
||||
|
||||
|
@ -367,6 +157,62 @@ const showDangerMessage = (index) => {
|
|||
const showWarningMessage = (index) => {
|
||||
proxy.$message.warning(index + '数据写入异常!');
|
||||
};
|
||||
|
||||
const fetchCurrentValues = async () => {
|
||||
try {
|
||||
const deviceId = 7; // 根据实际情况设置设备ID
|
||||
const inputTime = new Date().toISOString(); // 获取当前时间
|
||||
const response = await getInspectionCurrent(deviceId, inputTime);
|
||||
if (response.code === 200) {
|
||||
const currentValues = response.data.data;
|
||||
console.log("🚀 ~ fetchCurrentValues ~ currentValues:", currentValues)
|
||||
inspectionItems.value.forEach(item => {
|
||||
item.current = currentValues[item.name] || '--';
|
||||
});
|
||||
console.log("🚀 ~ fetchCurrentValues ~ inspectionItems:", inspectionItems.value)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching current values:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchInspectionData = async () => {
|
||||
try {
|
||||
const deviceId = 7; // 根据实际情况设置设备ID
|
||||
const inputTime = new Date().toISOString(); // 获取当前时间
|
||||
const response = await getInspectionData(deviceId, inputTime);
|
||||
if (response.code === 200) {
|
||||
const inspectionData = response.data;
|
||||
console.log("🚀 ~ fetchInspectionData ~ inspectionData:", inspectionData)
|
||||
const itemsMap = {};
|
||||
inspectionData.forEach(record => {
|
||||
const recordTime = record.recordTime;
|
||||
const data = record.data;
|
||||
for (const [name, value] of Object.entries(data)) {
|
||||
if (!itemsMap[name]) {
|
||||
itemsMap[name] = {
|
||||
name,
|
||||
label: name, // 可以根据需要调整label的值
|
||||
reference: 0,
|
||||
current: 0,
|
||||
data: {}
|
||||
};
|
||||
}
|
||||
itemsMap[name].data[recordTime] = value;
|
||||
}
|
||||
});
|
||||
inspectionItems.value = Object.values(itemsMap);
|
||||
console.log("🚀 ~ fetchInspectionData ~ inspectionItems:", inspectionItems.value)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching inspection data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchCurrentValues();
|
||||
fetchInspectionData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -444,6 +290,10 @@ const showWarningMessage = (index) => {
|
|||
font-size: 1rem; /* 调大表头行字体大小 */
|
||||
}
|
||||
|
||||
.title-width {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
ix-button {
|
||||
margin: 0.25rem;
|
||||
}
|
||||
|
|
|
@ -1,25 +1,17 @@
|
|||
<template>
|
||||
<IxApplication
|
||||
:appSwitchConfig="appSwitchConfig"
|
||||
theme="classic-dark"
|
||||
>
|
||||
<IxApplicationHeader
|
||||
name="SIEMENS MIS 1.0 前处理界面"
|
||||
:applicationSwitchButton="true"
|
||||
>
|
||||
<div className="placeholder-logo"></div>
|
||||
|
||||
<IxApplication :appSwitchConfig="appSwitchConfig" theme="classic-dark">
|
||||
<IxApplicationHeader name="SIEMENS MIS 1.0 前处理界面" :applicationSwitchButton="true">
|
||||
<!-- 添加实时显示时间 -->
|
||||
<div class="time-display">{{ currentTime }}</div>
|
||||
|
||||
<!-- 确保图标按钮正确显示 -->
|
||||
<IxIconButton icon="print" variant="secondary" ghost @click="toggleDatetimePicker"></IxIconButton>
|
||||
<IxIconButton icon="star" variant="secondary" ghost></IxIconButton>
|
||||
<IxIconButton icon="tools" variant="secondary" ghost></IxIconButton>
|
||||
<IxIconButton icon="alarm-bell-filled" variant="secondary" ghost></IxIconButton>
|
||||
<IxIconButton icon="calendar-filled" variant="secondary" ghost @click="toggleDatetimePicker"></IxIconButton>
|
||||
<IxIconButton icon="alarm-clock-filled" variant="secondary" ghost @click="handleReset"></IxIconButton>
|
||||
</IxApplicationHeader>
|
||||
|
||||
<IxContent class="mainContent">
|
||||
<router-view @update-history="updateHistory"></router-view>
|
||||
<router-view @update-history="updateHistory" @reset="reset"></router-view>
|
||||
</IxContent>
|
||||
|
||||
<!-- 添加 IxDatetimePicker 组件 -->
|
||||
|
@ -33,7 +25,6 @@
|
|||
import {
|
||||
IxApplication,
|
||||
IxApplicationHeader,
|
||||
IxAvatar,
|
||||
IxContent,
|
||||
IxContentHeader,
|
||||
IxDropdownButton,
|
||||
|
@ -58,9 +49,9 @@ const appSwitchConfig = {
|
|||
},
|
||||
{
|
||||
id: 'other-app',
|
||||
name: '其他系统',
|
||||
name: '点检系统',
|
||||
iconSrc: 'https://www.svgrepo.com/show/530661/genetic-data.svg',
|
||||
url: 'https://ix.siemens.io/',
|
||||
url: '/#/inspection',
|
||||
description: '其他系统描述',
|
||||
target: '_blank',
|
||||
},
|
||||
|
@ -85,6 +76,12 @@ const toggleDatetimePicker = () => {
|
|||
showDatetimePicker.value = !showDatetimePicker.value;
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
// 触发主页中的 getHistory 方法
|
||||
const event = new CustomEvent('reset');
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
|
||||
const handleDatetimePickerDone = (event) => {
|
||||
selectedDatetime.value = event.detail;
|
||||
showDatetimePicker.value = false;
|
||||
|
@ -94,8 +91,22 @@ const handleDatetimePickerDone = (event) => {
|
|||
};
|
||||
|
||||
const updateHistory = (datetime) => {
|
||||
// 将 datetime 转换为标准的 YYYY-MM-DD HH:mm:ss 格式
|
||||
const parsedDate = new Date(datetime.replace(/-/g, '/'));
|
||||
if (isNaN(parsedDate.getTime())) {
|
||||
console.error('Invalid datetime format:', datetime);
|
||||
return;
|
||||
}
|
||||
const year = parsedDate.getFullYear();
|
||||
const month = String(parsedDate.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(parsedDate.getDate()).padStart(2, '0');
|
||||
const hours = String(parsedDate.getHours()).padStart(2, '0');
|
||||
const minutes = String(parsedDate.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(parsedDate.getSeconds()).padStart(2, '0');
|
||||
const formattedDatetime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
// 触发主页中的 getHistory 方法
|
||||
const event = new CustomEvent('update-history', { detail: datetime });
|
||||
console.log("🚀 ~ updateHistory ~ formattedDatetime:", formattedDatetime)
|
||||
const event = new CustomEvent('update-history', { detail: formattedDatetime });
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
|
||||
|
@ -109,19 +120,28 @@ onMounted(() => {
|
|||
<style scoped>
|
||||
ix-application {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: 100vh;
|
||||
/* 设置应用高度为视口高度 */
|
||||
background-color: #000028;
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
font-size: 1.5rem; /* 调大全局字体大小 */
|
||||
font-size: 1.5rem;
|
||||
/* 调大全局字体大小 */
|
||||
display: flex;
|
||||
/* 使用 flex 布局 */
|
||||
flex-direction: column;
|
||||
/* 垂直排列子元素 */
|
||||
}
|
||||
|
||||
:deep(ix-application-header) {
|
||||
background-color: #23233C !important;
|
||||
height: 4rem !important; /* 64px 转换为 rem */
|
||||
height: 4rem !important;
|
||||
/* 64px 转换为 rem */
|
||||
padding: 0 !important;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
/* 防止头部收缩 */
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
|
@ -133,24 +153,30 @@ ix-application {
|
|||
|
||||
.logo-text {
|
||||
color: #fff;
|
||||
font-size: 1.2rem; /* 调大 logo 文本字体大小 */
|
||||
font-size: 1.2rem;
|
||||
/* 调大 logo 文本字体大小 */
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.03125rem; /* 0.5px 转换为 rem */
|
||||
letter-spacing: 0.03125rem;
|
||||
/* 0.5px 转换为 rem */
|
||||
padding: 0.1rem;
|
||||
}
|
||||
|
||||
.time-display {
|
||||
color: #fff;
|
||||
font-size: 1rem; /* 调大时间显示字体大小 */
|
||||
margin: 0.5rem 1rem 0 1rem; /* 16px 转换为 rem */
|
||||
font-size: 1rem;
|
||||
/* 调大时间显示字体大小 */
|
||||
margin: 0.5rem 1rem 0 1rem;
|
||||
/* 16px 转换为 rem */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:deep(.ix-icon-button) {
|
||||
--background-color: transparent;
|
||||
--color: #fff;
|
||||
height: 4rem; /* 64px 转换为 rem */
|
||||
width: 4rem; /* 64px 转换为 rem */
|
||||
height: 4rem;
|
||||
/* 64px 转换为 rem */
|
||||
width: 4rem;
|
||||
/* 64px 转换为 rem */
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -159,7 +185,8 @@ ix-application {
|
|||
|
||||
:deep(.application-name) {
|
||||
color: #fff !important;
|
||||
font-size: 1.2rem !important; /* 调大应用名称字体大小 */
|
||||
font-size: 1.2rem !important;
|
||||
/* 调大应用名称字体大小 */
|
||||
font-weight: normal !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -168,36 +195,44 @@ ix-application {
|
|||
:deep(IxContent) {
|
||||
width: 100%;
|
||||
height: calc(100vh - 4rem);
|
||||
padding: 0 !important; /* 确保没有内边距 */
|
||||
padding: 0 !important;
|
||||
/* 确保没有内边距 */
|
||||
margin: 0 !important;
|
||||
position: relative; /* 确保 IxDatetimePicker 组件正确显示 */
|
||||
position: relative;
|
||||
/* 确保 IxDatetimePicker 组件正确显示 */
|
||||
flex-grow: 1;
|
||||
/* 让内容区域填充剩余空间 */
|
||||
}
|
||||
|
||||
.datetime-picker-container {
|
||||
position: absolute;
|
||||
top: 4rem; /* 确保在头部下方 */
|
||||
right: 1rem; /* 靠右对齐 */
|
||||
z-index: 1000; /* 确保在最上层 */
|
||||
}
|
||||
|
||||
.dashboard-container {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: #000028;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
top: 4rem;
|
||||
/* 确保在头部下方 */
|
||||
right: 1rem;
|
||||
/* 靠右对齐 */
|
||||
z-index: 1000;
|
||||
/* 确保在最上层 */
|
||||
}
|
||||
|
||||
:deep(IxApplication) {
|
||||
margin: 0; /* 确保没有外边距 */
|
||||
padding: 0; /* 确保没有内边距 */
|
||||
margin: 0;
|
||||
/* 确保没有外边距 */
|
||||
padding: 0;
|
||||
/* 确保没有内边距 */
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
padding: 0 !important; /* 确保没有内边距 */
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #000028;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
:global(.visible) {
|
||||
--theme-modal--background:#23233C !important;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue