From 212c2b16eb6e1c00a3c4cdaec443ee0fdd7797e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Mon, 19 Jan 2026 13:29:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E9=94=8C=E7=BA=BF?= =?UTF-8?q?=E7=94=9F=E4=BA=A7=E7=9B=91=E6=8E=A7=E6=A8=A1=E5=9D=97=E5=8F=8A?= =?UTF-8?q?=E7=9B=B8=E5=85=B3API=E5=92=8C=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor(auth): 增加锌线系统token管理功能 feat(api): 添加锌线停机记录、生产报表和设备快照API feat(views): 实现锌线实时监控、生产统计和停机统计页面 feat(components): 开发锌线生产报表、停机统计和班组绩效组件 feat(utils): 新增锌线专用请求工具zinc1Request chore(vue.config): 配置锌线API代理 --- klp-ui/src/api/lines/zinc/dashboard.js | 18 + klp-ui/src/api/lines/zinc/report.js | 20 + klp-ui/src/api/lines/zinc/stoppage.js | 11 + klp-ui/src/api/pocket/deviceEnum.js | 9 + klp-ui/src/api/pocket/deviceFieldMeta.js | 9 + klp-ui/src/api/pocket/deviceSnapshot.js | 20 + klp-ui/src/api/pocket/plantState.js | 162 ++++ klp-ui/src/utils/auth.js | 15 + klp-ui/src/utils/zinc1Request.js | 142 +++ .../acid/components/product-statistic.vue | 640 ++++++++++++ .../acid/components/real-time-monitoring.vue | 837 ++++++++++++++++ .../acid/components/shutdown-statistic.vue | 908 ++++++++++++++++++ .../acid/components/team-performance.vue | 526 ++++++++++ klp-ui/src/views/lines/acid/index.vue | 56 ++ .../zinc/components/product-statistic.vue | 155 +++ .../zinc/components/real-time-monitoring.vue | 5 + .../zinc/components/shutdown-statistic.vue | 165 ++++ klp-ui/src/views/lines/zinc/index.vue | 56 ++ klp-ui/vue.config.js | 8 + 19 files changed, 3762 insertions(+) create mode 100644 klp-ui/src/api/lines/zinc/dashboard.js create mode 100644 klp-ui/src/api/lines/zinc/report.js create mode 100644 klp-ui/src/api/lines/zinc/stoppage.js create mode 100644 klp-ui/src/api/pocket/deviceEnum.js create mode 100644 klp-ui/src/api/pocket/deviceFieldMeta.js create mode 100644 klp-ui/src/api/pocket/deviceSnapshot.js create mode 100644 klp-ui/src/api/pocket/plantState.js create mode 100644 klp-ui/src/utils/zinc1Request.js create mode 100644 klp-ui/src/views/lines/acid/components/product-statistic.vue create mode 100644 klp-ui/src/views/lines/acid/components/real-time-monitoring.vue create mode 100644 klp-ui/src/views/lines/acid/components/shutdown-statistic.vue create mode 100644 klp-ui/src/views/lines/acid/components/team-performance.vue create mode 100644 klp-ui/src/views/lines/acid/index.vue create mode 100644 klp-ui/src/views/lines/zinc/components/product-statistic.vue create mode 100644 klp-ui/src/views/lines/zinc/components/real-time-monitoring.vue create mode 100644 klp-ui/src/views/lines/zinc/components/shutdown-statistic.vue create mode 100644 klp-ui/src/views/lines/zinc/index.vue diff --git a/klp-ui/src/api/lines/zinc/dashboard.js b/klp-ui/src/api/lines/zinc/dashboard.js new file mode 100644 index 00000000..9a105c63 --- /dev/null +++ b/klp-ui/src/api/lines/zinc/dashboard.js @@ -0,0 +1,18 @@ +import zinc1Request from '@/utils/zinc1Request' + +// 获取当前生产中的计划信息 +export function getCurrentPlan() { + return zinc1Request({ + url: '/business/dashboard/currentPlan', + method: 'get' + }) +} + +// 获取当前生产卷的关键工艺参数 +export function getCurrentProcess() { + return zinc1Request({ + url: '/business/dashboard/currentProcess', + method: 'get' + }) +} + diff --git a/klp-ui/src/api/lines/zinc/report.js b/klp-ui/src/api/lines/zinc/report.js new file mode 100644 index 00000000..96177ae3 --- /dev/null +++ b/klp-ui/src/api/lines/zinc/report.js @@ -0,0 +1,20 @@ +import zinc1Request from '@/utils/zinc1Request' + +// 生产实绩汇总 +export function getReportSummary(params) { + return zinc1Request({ + url: '/report/summary', + method: 'get', + params + }) +} + +// 生产实绩明细 +export function getReportDetails(params) { + return zinc1Request({ + url: '/report/details', + method: 'get', + params + }) +} + diff --git a/klp-ui/src/api/lines/zinc/stoppage.js b/klp-ui/src/api/lines/zinc/stoppage.js new file mode 100644 index 00000000..a86477b4 --- /dev/null +++ b/klp-ui/src/api/lines/zinc/stoppage.js @@ -0,0 +1,11 @@ +import zinc1Request from '@/utils/zinc1Request' + +// 停机记录列表 +export function listStoppage(data) { + return zinc1Request({ + url: '/stoppage/list', + method: 'post', + data + }) +} + diff --git a/klp-ui/src/api/pocket/deviceEnum.js b/klp-ui/src/api/pocket/deviceEnum.js new file mode 100644 index 00000000..1c6ba41f --- /dev/null +++ b/klp-ui/src/api/pocket/deviceEnum.js @@ -0,0 +1,9 @@ +import zinc1Request from '@/utils/zinc1Request' + +export function listDeviceEnumAll() { + return zinc1Request({ + url: '/api/deviceEnum/all', + method: 'get' + }) +} + diff --git a/klp-ui/src/api/pocket/deviceFieldMeta.js b/klp-ui/src/api/pocket/deviceFieldMeta.js new file mode 100644 index 00000000..dfc60d74 --- /dev/null +++ b/klp-ui/src/api/pocket/deviceFieldMeta.js @@ -0,0 +1,9 @@ +import zinc1Request from '@/utils/zinc1Request' + +export function getDeviceFieldMetaAll() { + return zinc1Request({ + url: '/api/deviceFieldMeta/all', + method: 'get' + }) +} + diff --git a/klp-ui/src/api/pocket/deviceSnapshot.js b/klp-ui/src/api/pocket/deviceSnapshot.js new file mode 100644 index 00000000..2d8a6c76 --- /dev/null +++ b/klp-ui/src/api/pocket/deviceSnapshot.js @@ -0,0 +1,20 @@ +import zinc1Request from '@/utils/zinc1Request' + +// 获取最新N条设备快照 +export function listDeviceSnapshotLatest(params) { + return zinc1Request({ + url: '/api/deviceSnapshot/latest', + method: 'get', + params + }) +} + +// 按时间范围查询设备快照 +export function listDeviceSnapshotRange(params) { + return zinc1Request({ + url: '/api/deviceSnapshot/range', + method: 'get', + params + }) +} + diff --git a/klp-ui/src/api/pocket/plantState.js b/klp-ui/src/api/pocket/plantState.js new file mode 100644 index 00000000..34f597e5 --- /dev/null +++ b/klp-ui/src/api/pocket/plantState.js @@ -0,0 +1,162 @@ +import request from '@/utils/request' + +// =========================== 状态定义相关 =========================== + +/** + * 获取所有状态定义及其当前值(用于初始化缓存) + * 返回数据结构: + * { + * id: 定义ID (对应VALUE字段编号,如id=14对应VALUE14), + * name: 指标名称, + * units: 单位, + * comments: 说明, + * currentValue: 当前值, + * currentInsdate: 当前值时间 + * } + */ +export function getAllPlantStateDefines() { + return request({ + url: '/pocket/proPlantStateDefine/allWithValues', + method: 'get' + }) +} + +// =========================== 当前数据相关 =========================== + +// 查询设备状态当前数据列表 +export function listPlantStateCurrent(query) { + return request({ + url: '/pocket/proPlantStateCurrent/selectAll', + method: 'get', + params: query + }) +} + +// 查询单条设备状态当前数据 +export function getPlantStateCurrent(type, insdate) { + return request({ + url: '/pocket/proPlantStateCurrent/one', + method: 'get', + params: { type, insdate } + }) +} + +// 查询设备状态历史数据列表 +export function listPlantStateHistory(query) { + return request({ + url: '/pocket/proPlantStateHistory/list', + method: 'get', + params: query + }) +} + +// 查询设备状态历史数据详情 +export function getPlantStateHistory(insdate) { + return request({ + url: '/pocket/proPlantStateHistory/' + insdate, + method: 'get' + }) +} + +// 查询停机列表 +export function listStoppage(query) { + return request({ + url: '/pocket/proStoppage/list', + method: 'get', + params: query + }) +} + +// 查询停机详情 +export function getStoppage(stopId) { + return request({ + url: '/pocket/proStoppage/' + stopId, + method: 'get' + }) +} + +// =========================== 班组信息相关 =========================== + +/** + * 获取当前班组信息 + * 返回数据结构: + * { + * shift: 班次 (如:A/B/C 或 早/中/晚), + * crew: 班组编号, + * seqNum: 序列号, + * sysTime: 系统时间 + * } + */ +export function getCurrentShift() { + return request({ + url: '/pocket/shiftCurrent/current', + method: 'get' + }) +} + +// =========================== 生产统计相关 =========================== + +/** + * 获取生产统计汇总数据 + * @param {string} startDate - 开始日期 (yyyy-MM-dd) + * @param {string} endDate - 结束日期 (yyyy-MM-dd) + */ +export function getProductionSummary(startDate, endDate) { + return request({ + url: '/pocket/productionStatistics/summary', + method: 'get', + params: { startDate, endDate } + }) +} + +/** + * 获取班组产量统计 + * @param {string} startDate - 开始日期 + * @param {string} endDate - 结束日期 + */ +export function getCrewProduction(startDate, endDate) { + return request({ + url: '/pocket/productionStatistics/crewProduction', + method: 'get', + params: { startDate, endDate } + }) +} + +/** + * 获取厚度分布统计 + * @param {string} startDate - 开始日期 + * @param {string} endDate - 结束日期 + */ +export function getThicknessDistribution(startDate, endDate) { + return request({ + url: '/pocket/productionStatistics/thicknessDistribution', + method: 'get', + params: { startDate, endDate } + }) +} + +/** + * 获取宽度分布统计 + * @param {string} startDate - 开始日期 + * @param {string} endDate - 结束日期 + */ +export function getWidthDistribution(startDate, endDate) { + return request({ + url: '/pocket/productionStatistics/widthDistribution', + method: 'get', + params: { startDate, endDate } + }) +} + +/** + * 获取班组绩效统计 + * @param {string} startDate - 开始日期 + * @param {string} endDate - 结束日期 + */ +export function getTeamPerformance(startDate, endDate) { + return request({ + url: '/pocket/productionStatistics/teamPerformance', + method: 'get', + params: { startDate, endDate } + }) +} diff --git a/klp-ui/src/utils/auth.js b/klp-ui/src/utils/auth.js index 08a43d6e..e0b3e16f 100644 --- a/klp-ui/src/utils/auth.js +++ b/klp-ui/src/utils/auth.js @@ -1,7 +1,9 @@ import Cookies from 'js-cookie' const TokenKey = 'Admin-Token' +const ZincTokenKey = 'Zinc-Token' +// L3 Token管理 export function getToken() { return Cookies.get(TokenKey) } @@ -13,3 +15,16 @@ export function setToken(token) { export function removeToken() { return Cookies.remove(TokenKey) } + +// Zinc Token管理 +export function getZincToken() { + return Cookies.get(ZincTokenKey) +} + +export function setZincToken(token) { + return Cookies.set(ZincTokenKey, token) +} + +export function removeZincToken() { + return Cookies.remove(ZincTokenKey) +} diff --git a/klp-ui/src/utils/zinc1Request.js b/klp-ui/src/utils/zinc1Request.js new file mode 100644 index 00000000..ec6d7b57 --- /dev/null +++ b/klp-ui/src/utils/zinc1Request.js @@ -0,0 +1,142 @@ +import axios from 'axios' +import { Notification, MessageBox, Message } from 'element-ui' +import store from '@/store' +import { getZincToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { tansParams } from "@/utils/klp"; +import cache from '@/plugins/cache' +// 是否显示重新登录 +export let isRelogin = { show: false }; + +axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' +// 对应国际化资源文件后缀 +axios.defaults.headers['Content-Language'] = 'zh_CN' +// 创建axios实例 +const service = axios.create({ + // axios中请求配置有baseURL选项,表示请求URL公共部分 + baseURL: '/zinc-api', + // 超时 + timeout: 10000 +}) + +// request拦截器 +service.interceptors.request.use(config => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false + // 是否需要防止数据重复提交 + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false + if (getZincToken() && !isToken) { + config.headers['Authorization'] = 'Bearer ' + getZincToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + } + // get请求映射params参数 + if (config.method === 'get' && config.params) { + let url = config.url + '?' + tansParams(config.params); + url = url.slice(0, -1); + config.params = {}; + config.url = url; + } + if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { + // 对于盖章请求,添加特殊处理确保 0 值不被过滤 + if (config.url && config.url.includes('/stamp/java')) { + console.log('Stamp request - original data:', JSON.stringify(config.data, null, 2)) + if (config.data && typeof config.data === 'object') { + // 确保 yPx 和 xPx 即使是 0 也被正确包含 + // 创建一个新对象,确保所有值都被正确设置 + const cleanData = { + targetFileUrl: String(config.data.targetFileUrl || ''), + stampImageUrl: String(config.data.stampImageUrl || ''), + pageNo: Number(config.data.pageNo) || 1, + xPx: Number(config.data.xPx) || 0, + yPx: Number(config.data.yPx) || 0 + } + if (config.data.widthPx !== undefined && config.data.widthPx !== null) { + cleanData.widthPx = Number(config.data.widthPx) + } + if (config.data.heightPx !== undefined && config.data.heightPx !== null) { + cleanData.heightPx = Number(config.data.heightPx) + } + console.log('Stamp request - cleaned data:', JSON.stringify(cleanData, null, 2)) + console.log('yPx in cleaned data:', cleanData.yPx, typeof cleanData.yPx) + config.data = cleanData + } + } + const requestObj = { + url: config.url, + data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, + time: new Date().getTime() + } + const sessionObj = cache.session.getJSON('sessionObj') + if (sessionObj === undefined || sessionObj === null || sessionObj === '') { + cache.session.setJSON('sessionObj', requestObj) + } else { + const s_url = sessionObj.url; // 请求地址 + const s_data = sessionObj.data; // 请求数据 + const s_time = sessionObj.time; // 请求时间 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 + if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { + const message = '数据正在处理,请勿重复提交'; + console.warn(`[${s_url}]: ` + message) + return Promise.reject(new Error(message)) + } else { + cache.session.setJSON('sessionObj', requestObj) + } + } + } + return config +}, error => { + console.log(error) + Promise.reject(error) +}) + +// 响应拦截器 +service.interceptors.response.use(res => { + // 未设置状态码则默认成功状态 + const code = res.data.code || 200; + // 获取错误信息 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + // 二进制数据则直接返回 + if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { + return res.data + } + if (code === 401) { + if (!isRelogin.show) { + isRelogin.show = true; + MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { + isRelogin.show = false; + store.dispatch('LogOut').then(() => { + location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; + }) + }).catch(() => { + isRelogin.show = false; + }); + } + return Promise.reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code === 500) { + Message({ message: msg, type: 'error' }) + return Promise.reject(new Error(msg)) + } else if (code === 601) { + Message({ message: msg, type: 'warning' }) + return Promise.reject('error') + } else if (code !== 200) { + Notification.error({ title: msg }) + return Promise.reject('error') + } else { + return res.data + } + }, + error => { + console.log('err' + error) + let { message } = error; + if (message == "Network Error") { + message = "后端接口连接异常"; + } else if (message.includes("timeout")) { + message = "系统接口请求超时"; + } else if (message.includes("Request failed with status code")) { + message = "系统接口" + message.substr(message.length - 3) + "异常"; + } + Message({ message: message, type: 'error', duration: 5 * 1000 }) + return Promise.reject(error) + } +) + +export default service diff --git a/klp-ui/src/views/lines/acid/components/product-statistic.vue b/klp-ui/src/views/lines/acid/components/product-statistic.vue new file mode 100644 index 00000000..2ce9cee4 --- /dev/null +++ b/klp-ui/src/views/lines/acid/components/product-statistic.vue @@ -0,0 +1,640 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/src/views/lines/acid/components/real-time-monitoring.vue b/klp-ui/src/views/lines/acid/components/real-time-monitoring.vue new file mode 100644 index 00000000..48625e38 --- /dev/null +++ b/klp-ui/src/views/lines/acid/components/real-time-monitoring.vue @@ -0,0 +1,837 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/src/views/lines/acid/components/shutdown-statistic.vue b/klp-ui/src/views/lines/acid/components/shutdown-statistic.vue new file mode 100644 index 00000000..c38aa1c0 --- /dev/null +++ b/klp-ui/src/views/lines/acid/components/shutdown-statistic.vue @@ -0,0 +1,908 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/src/views/lines/acid/components/team-performance.vue b/klp-ui/src/views/lines/acid/components/team-performance.vue new file mode 100644 index 00000000..50f2ba88 --- /dev/null +++ b/klp-ui/src/views/lines/acid/components/team-performance.vue @@ -0,0 +1,526 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/src/views/lines/acid/index.vue b/klp-ui/src/views/lines/acid/index.vue new file mode 100644 index 00000000..5c4e1b4b --- /dev/null +++ b/klp-ui/src/views/lines/acid/index.vue @@ -0,0 +1,56 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/src/views/lines/zinc/components/product-statistic.vue b/klp-ui/src/views/lines/zinc/components/product-statistic.vue new file mode 100644 index 00000000..ffb66d9b --- /dev/null +++ b/klp-ui/src/views/lines/zinc/components/product-statistic.vue @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/src/views/lines/zinc/components/real-time-monitoring.vue b/klp-ui/src/views/lines/zinc/components/real-time-monitoring.vue new file mode 100644 index 00000000..49df4da4 --- /dev/null +++ b/klp-ui/src/views/lines/zinc/components/real-time-monitoring.vue @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/klp-ui/src/views/lines/zinc/components/shutdown-statistic.vue b/klp-ui/src/views/lines/zinc/components/shutdown-statistic.vue new file mode 100644 index 00000000..e02f037c --- /dev/null +++ b/klp-ui/src/views/lines/zinc/components/shutdown-statistic.vue @@ -0,0 +1,165 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/src/views/lines/zinc/index.vue b/klp-ui/src/views/lines/zinc/index.vue new file mode 100644 index 00000000..bfce7f7d --- /dev/null +++ b/klp-ui/src/views/lines/zinc/index.vue @@ -0,0 +1,56 @@ + + + + + \ No newline at end of file diff --git a/klp-ui/vue.config.js b/klp-ui/vue.config.js index 8a28edf3..5d67a76d 100644 --- a/klp-ui/vue.config.js +++ b/klp-ui/vue.config.js @@ -45,6 +45,14 @@ module.exports = { ['^' + process.env.VUE_APP_BASE_API]: '' } }, + // 直接代理Zinc1相关路径 + '/zinc-api': { + target: `http://140.143.206.120:18082/prod-api`, + changeOrigin: true, + pathRewrite: { + ['^' + process.env.VUE_APP_BASE_API]: '' + } + }, // 直接代理WebSocket相关路径 '/websocket': { target: `http://localhost:8080`,