diff --git a/cola-web.tar b/cola-web.tar deleted file mode 100644 index e69de29..0000000 diff --git a/deploy.sh b/deploy.sh index 70d16cf..73d11ef 100644 --- a/deploy.sh +++ b/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 \ No newline at end of file +# 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 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a76a8e2..5fb87b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 43053db..91b3194 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/src/api/dashboard.js b/src/api/dashboard.js index 02397c6..755261c 100644 --- a/src/api/dashboard.js +++ b/src/api/dashboard.js @@ -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' }); -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/api/inspection.js b/src/api/inspection.js index e69de29..dde312f 100644 --- a/src/api/inspection.js +++ b/src/api/inspection.js @@ -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' + }); +} \ No newline at end of file diff --git a/src/assets/alarm.svg b/src/assets/alarm.svg new file mode 100644 index 0000000..1f37f10 --- /dev/null +++ b/src/assets/alarm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/ConfirmDialog.vue b/src/components/ConfirmDialog.vue new file mode 100644 index 0000000..60642b4 --- /dev/null +++ b/src/components/ConfirmDialog.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/components/ProcessGanttChart.vue b/src/components/ProcessGanttChart.vue index 249cf4f..993afa6 100644 --- a/src/components/ProcessGanttChart.vue +++ b/src/components/ProcessGanttChart.vue @@ -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; } \ No newline at end of file diff --git a/src/plugins/message.js b/src/plugins/message.js index ffa6340..81b61f6 100644 --- a/src/plugins/message.js +++ b/src/plugins/message.js @@ -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), }; }, }; diff --git a/src/views/Dashboard/index.vue b/src/views/Dashboard/index.vue index 47997d0..c6719d5 100644 --- a/src/views/Dashboard/index.vue +++ b/src/views/Dashboard/index.vue @@ -3,13 +3,15 @@
-
+

果汁调配

累计流量:{{ totalTrafficJuice }}
-
+
{{ item.name }}:
{{ item.value }}
+
-
+

果肉调配

果肉流量:{{ totalTrafficPulp }}
-
+
{{ item.name }}:
{{ item.value }}
+
-
-
+
+

果汁 UHT

-
+
当前配方: {{ processForm_uht.formula }} @@ -87,13 +94,14 @@
-
-
+
+

果肉 UHT

-
+
当前配方: {{ processForm_pulp.formula }} @@ -140,11 +148,12 @@
-
+

果汁无菌罐

- +   已碱洗 @@ -153,30 +162,31 @@
-
+
当前步骤: {{ juiceTank.mixerStep }}
-
- 当前液位: +
+ 当前液位:
{{ juiceTank.liquidLevel }}
+
果汁流量:{{ juiceTank.productFlowRate - }} + }}
-
+

动态混合器

@@ -212,13 +222,14 @@
-
+
果汁流量:{{ pulpTank.productFlowRate - }} + }}

果肉无菌罐

@@ -236,7 +247,7 @@ 当前配方: 果汁配方
-
+
当前液位:
{{ pulpTank.liquidLevel }}
+
@@ -259,6 +271,7 @@ 当班
+
@@ -271,7 +284,19 @@ 流量:{{ productFlowRate }} 配方:{{ formula }} 持续时长:{{ duration }} - 请选择停机原因:{{ }} + {{ selectedReason ? '停机原因:' + selectedReason : '请选择停机原因' }} + + + + + + + +
+ + 确认 +
+
@@ -280,14 +305,28 @@ diff --git a/src/views/Inspection/index.vue b/src/views/Inspection/index.vue index ec8cde1..b5bbdb9 100644 --- a/src/views/Inspection/index.vue +++ b/src/views/Inspection/index.vue @@ -2,10 +2,10 @@
- - - - 查询 + + + + 查询 导出全部
@@ -20,7 +20,7 @@
- + @@ -32,21 +32,21 @@
- 点检项目 + 点检项目 单位 参考值 当前值 - + {{ hour }}
- {{ item.name }} + {{ item.label }} -- {{ item.reference }} - {{ item.current }} + {{ item.current }} {{ item.data[hour] || '--' }} @@ -60,9 +60,11 @@ \ No newline at end of file