完善类型配置,新增L1, L4数据展示界面
This commit is contained in:
2
.env.production
Normal file
2
.env.production
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# 生产环境
|
||||||
|
VITE_APP_BASE_API = '/prod-api'
|
||||||
31
components.d.ts
vendored
31
components.d.ts
vendored
@@ -11,72 +11,53 @@ declare module 'vue' {
|
|||||||
AButton: typeof import('ant-design-vue/es')['Button']
|
AButton: typeof import('ant-design-vue/es')['Button']
|
||||||
ACol: typeof import('ant-design-vue/es')['Col']
|
ACol: typeof import('ant-design-vue/es')['Col']
|
||||||
AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
|
AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
|
||||||
ActionButton: typeof import('./src/components/common/ActionButton/ActionButton.vue')['default']
|
|
||||||
ActionButtons: typeof import('./src/components/common/ActionButtons/index.vue')['default']
|
ActionButtons: typeof import('./src/components/common/ActionButtons/index.vue')['default']
|
||||||
|
ADescriptions: typeof import('ant-design-vue/es')['Descriptions']
|
||||||
|
ADescriptionsItem: typeof import('ant-design-vue/es')['DescriptionsItem']
|
||||||
AForm: typeof import('ant-design-vue/es')['Form']
|
AForm: typeof import('ant-design-vue/es')['Form']
|
||||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||||
AInput: typeof import('ant-design-vue/es')['Input']
|
AInput: typeof import('ant-design-vue/es')['Input']
|
||||||
AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
|
AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
|
||||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||||
AList: typeof import('ant-design-vue/es')['List']
|
|
||||||
AListItem: typeof import('ant-design-vue/es')['ListItem']
|
|
||||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||||
ARadio: typeof import('ant-design-vue/es')['Radio']
|
ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
|
||||||
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
|
||||||
ARow: typeof import('ant-design-vue/es')['Row']
|
ARow: typeof import('ant-design-vue/es')['Row']
|
||||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||||
ASpace: typeof import('ant-design-vue/es')['Space']
|
ASpace: typeof import('ant-design-vue/es')['Space']
|
||||||
|
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||||
ATable: typeof import('ant-design-vue/es')['Table']
|
ATable: typeof import('ant-design-vue/es')['Table']
|
||||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
|
||||||
CameraModal: typeof import('./src/components/CameraModal/index.vue')['default']
|
|
||||||
CameraStatus: typeof import('./src/components/CameraStatus/index.vue')['default']
|
CameraStatus: typeof import('./src/components/CameraStatus/index.vue')['default']
|
||||||
ExecutionResult: typeof import('./src/components/common/ExecutionResult/index.vue')['default']
|
ExecutionResult: typeof import('./src/components/common/ExecutionResult/index.vue')['default']
|
||||||
ILucideActivity: typeof import('~icons/lucide/activity')['default']
|
ILucideActivity: typeof import('~icons/lucide/activity')['default']
|
||||||
ILucideCamera: typeof import('~icons/lucide/camera')['default']
|
ILucideCamera: typeof import('~icons/lucide/camera')['default']
|
||||||
ILucideClock: typeof import('~icons/lucide/clock')['default']
|
|
||||||
ILucideCpu: typeof import('~icons/lucide/cpu')['default']
|
ILucideCpu: typeof import('~icons/lucide/cpu')['default']
|
||||||
ILucideDatabase: typeof import('~icons/lucide/database')['default']
|
ILucideDatabase: typeof import('~icons/lucide/database')['default']
|
||||||
ILucideEdit: typeof import('~icons/lucide/edit')['default']
|
ILucideEdit: typeof import('~icons/lucide/edit')['default']
|
||||||
ILucideFileText: typeof import('~icons/lucide/file-text')['default']
|
|
||||||
ILucideInbox: typeof import('~icons/lucide/inbox')['default']
|
ILucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||||
ILucideLink: typeof import('~icons/lucide/link')['default']
|
|
||||||
ILucideLinkOff: typeof import('~icons/lucide/link-off')['default']
|
|
||||||
ILucideLinOff: typeof import('~icons/lucide/lin-off')['default']
|
|
||||||
ILucideLoader: typeof import('~icons/lucide/loader')['default']
|
ILucideLoader: typeof import('~icons/lucide/loader')['default']
|
||||||
ILucideLock: typeof import('~icons/lucide/lock')['default']
|
ILucideLock: typeof import('~icons/lucide/lock')['default']
|
||||||
ILucideLogIn: typeof import('~icons/lucide/log-in')['default']
|
|
||||||
ILucideLoOff: typeof import('~icons/lucide/lo-off')['default']
|
|
||||||
ILucideLucideDatabase: typeof import('~icons/lucide/lucide-database')['default']
|
|
||||||
ILucideMonitor: typeof import('~icons/lucide/monitor')['default']
|
ILucideMonitor: typeof import('~icons/lucide/monitor')['default']
|
||||||
ILucidePackage: typeof import('~icons/lucide/package')['default']
|
ILucidePackage: typeof import('~icons/lucide/package')['default']
|
||||||
ILucidePlug: typeof import('~icons/lucide/plug')['default']
|
|
||||||
ILucidePlugOff: typeof import('~icons/lucide/plug-off')['default']
|
|
||||||
ILucideRadio: typeof import('~icons/lucide/radio')['default']
|
ILucideRadio: typeof import('~icons/lucide/radio')['default']
|
||||||
ILucideRefreshCw: typeof import('~icons/lucide/refresh-cw')['default']
|
ILucideRefreshCw: typeof import('~icons/lucide/refresh-cw')['default']
|
||||||
ILucideSave: typeof import('~icons/lucide/save')['default']
|
ILucideSave: typeof import('~icons/lucide/save')['default']
|
||||||
|
ILucideSearch: typeof import('~icons/lucide/search')['default']
|
||||||
ILucideShieldCheck: typeof import('~icons/lucide/shield-check')['default']
|
ILucideShieldCheck: typeof import('~icons/lucide/shield-check')['default']
|
||||||
ILucideSquarePen: typeof import('~icons/lucide/square-pen')['default']
|
ILucideSquarePen: typeof import('~icons/lucide/square-pen')['default']
|
||||||
ILucideTrash2: typeof import('~icons/lucide/trash2')['default']
|
ILucideTrash2: typeof import('~icons/lucide/trash2')['default']
|
||||||
ILucideUnlink: typeof import('~icons/lucide/unlink')['default']
|
|
||||||
ILucideUnlinkOff: typeof import('~icons/lucide/unlink-off')['default']
|
|
||||||
ILucideUser: typeof import('~icons/lucide/user')['default']
|
ILucideUser: typeof import('~icons/lucide/user')['default']
|
||||||
ILucideWifi: typeof import('~icons/lucide/wifi')['default']
|
ILucideWifi: typeof import('~icons/lucide/wifi')['default']
|
||||||
ILucideX: typeof import('~icons/lucide/x')['default']
|
ILucideX: typeof import('~icons/lucide/x')['default']
|
||||||
ILucideZap: typeof import('~icons/lucide/zap')['default']
|
ILucideZap: typeof import('~icons/lucide/zap')['default']
|
||||||
MesModal: typeof import('./src/components/MesModal/index.vue')['default']
|
LmsStatus: typeof import('./src/components/LmsStatus/index.vue')['default']
|
||||||
MesStatus: typeof import('./src/components/MesStatus/index.vue')['default']
|
MesStatus: typeof import('./src/components/MesStatus/index.vue')['default']
|
||||||
NetworkModal: typeof import('./src/components/NetworkModal/index.vue')['default']
|
|
||||||
NetworkStatus: typeof import('./src/components/NetworkStatus/index.vue')['default']
|
NetworkStatus: typeof import('./src/components/NetworkStatus/index.vue')['default']
|
||||||
PlcModal: typeof import('./src/components/PlcModal/index.vue')['default']
|
|
||||||
PlcStatus: typeof import('./src/components/PlcStatus/index.vue')['default']
|
PlcStatus: typeof import('./src/components/PlcStatus/index.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
Settings: typeof import('./src/components/Settings/index.vue')['default']
|
|
||||||
SettingsModal: typeof import('./src/components/SettingsModal/index.vue')['default']
|
SettingsModal: typeof import('./src/components/SettingsModal/index.vue')['default']
|
||||||
SSELogs: typeof import('./src/components/SSELogs/index.vue')['default']
|
SSELogs: typeof import('./src/components/SSELogs/index.vue')['default']
|
||||||
SseModal: typeof import('./src/components/SseModal/index.vue')['default']
|
|
||||||
SseStatus: typeof import('./src/components/SseStatus/index.vue')['default']
|
SseStatus: typeof import('./src/components/SseStatus/index.vue')['default']
|
||||||
XxxModal: typeof import('./src/components/xxxModal/index.vue')['default']
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
global.d.ts
vendored
1
global.d.ts
vendored
@@ -2,3 +2,4 @@
|
|||||||
declare module '@/components/*';
|
declare module '@/components/*';
|
||||||
declare module '@/views/*';
|
declare module '@/views/*';
|
||||||
declare module '@/api/*';
|
declare module '@/api/*';
|
||||||
|
declare module '@/App.vue';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "rd_mes_front_hmi",
|
"name": "rd_mes_front_hmi",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --open",
|
"dev": "vite --open",
|
||||||
"build": "vue-tsc -b && vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -6,4 +6,5 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
||||||
|
import 'dayjs/locale/zh-cn';
|
||||||
</script>
|
</script>
|
||||||
7
src/api/common/model.d.ts
vendored
Normal file
7
src/api/common/model.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export interface ApiResponse<T = any> {
|
||||||
|
code?: number;
|
||||||
|
msg?: string;
|
||||||
|
data?: T;
|
||||||
|
rows?: T[];
|
||||||
|
total?: number;
|
||||||
|
}
|
||||||
20
src/api/data/index.ts
Normal file
20
src/api/data/index.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import request from '../request';
|
||||||
|
import type { QueryParams } from './model';
|
||||||
|
|
||||||
|
// 获取 L1 数据
|
||||||
|
export function getL1Data(params: QueryParams) {
|
||||||
|
return request({
|
||||||
|
url: '/jinghua/l1Data/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 L4 数据
|
||||||
|
export function getL4Data(params: QueryParams) {
|
||||||
|
return request({
|
||||||
|
url: '/jinghua/l4Data/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
9
src/api/data/model.d.ts
vendored
Normal file
9
src/api/data/model.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export interface QueryParams {
|
||||||
|
pageNum?: number;
|
||||||
|
pageSize?: number;
|
||||||
|
orderByColumn?: string;
|
||||||
|
isAsc?: boolean;
|
||||||
|
qrCode?: string;
|
||||||
|
createTimeBegin?: string;
|
||||||
|
createTimeEnd?: string;
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import type { LmsWorkMode } from './model';
|
|||||||
// 获取 LMS 工作模式
|
// 获取 LMS 工作模式
|
||||||
export const fetchLmsWorkMode = () => {
|
export const fetchLmsWorkMode = () => {
|
||||||
return request({
|
return request({
|
||||||
url: '/jinghua/mes/work-mode',
|
url: '/jinghua/work-mode',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@ export const fetchLmsWorkMode = () => {
|
|||||||
// 更新 LMS 工作模式
|
// 更新 LMS 工作模式
|
||||||
export const updateLmsWorkMode = (workMode: LmsWorkMode) => {
|
export const updateLmsWorkMode = (workMode: LmsWorkMode) => {
|
||||||
return request({
|
return request({
|
||||||
url: `/jinghua/mes/work-mode/${workMode}`,
|
url: `/jinghua/work-mode/${workMode}`,
|
||||||
method: 'put',
|
method: 'put',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Modal, notification } from 'ant-design-vue';
|
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
|
import { Modal, notification } from 'ant-design-vue';
|
||||||
|
import type { AxiosRequestConfig } from "axios";
|
||||||
|
import type { ApiResponse } from "@/api/common/model";
|
||||||
|
|
||||||
const errCodeMap: { [key: string]: string } = {
|
const errCodeMap: { [key: string]: string } = {
|
||||||
'403': '当前操作没有权限',
|
'403': '当前操作没有权限',
|
||||||
@@ -12,7 +14,7 @@ const errCodeMap: { [key: string]: string } = {
|
|||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: import.meta.env.VITE_APP_BASE_API as string,
|
baseURL: import.meta.env.VITE_APP_BASE_API as string,
|
||||||
timeout: 10000
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
@@ -36,37 +38,46 @@ service.interceptors.request.use(
|
|||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
response => {
|
response => {
|
||||||
console.log(response)
|
console.log(response)
|
||||||
// 未设置状态码则默认成功状态
|
|
||||||
const code = response.data.code || 200;
|
const code = response.data.code || 200;
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
if (code === 200) {
|
switch (code) {
|
||||||
return response.data ?? response;
|
case 200:
|
||||||
} else if (code === 401) {
|
return data ?? response;
|
||||||
Modal.error({
|
case 401:
|
||||||
title: '系统提示',
|
Modal.error({
|
||||||
content: '登录状态已过期,请重新登录',
|
title: '系统提示',
|
||||||
onOk: () => {
|
content: '登录状态已过期,请重新登录',
|
||||||
router.push('/login')
|
onOk: () => {
|
||||||
}
|
router.push('/login')
|
||||||
})
|
}
|
||||||
} else {
|
})
|
||||||
const codeStr = String(code);
|
return Promise.reject(data);
|
||||||
const errMsg = errCodeMap[codeStr] || response.data.msg || errCodeMap['default'];
|
default:
|
||||||
notification.error({
|
const errMsg = errCodeMap[code] || data.msg || errCodeMap['default'];
|
||||||
message: '请求错误',
|
notification.error({
|
||||||
description: errMsg,
|
message: '请求错误',
|
||||||
});
|
description: errMsg,
|
||||||
return Promise.reject(response.data);
|
});
|
||||||
|
return Promise.reject(data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
error.message = error.code === "ECONNABORTED" ? '请求超时,请稍后重试' : error.message;
|
||||||
|
|
||||||
// 网络/服务器错误统一处理
|
// 网络/服务器错误统一处理
|
||||||
notification.error({
|
notification.error({
|
||||||
message: '网络错误',
|
message: "网络错误",
|
||||||
description: error.message || '请求失败',
|
description: error.message,
|
||||||
});
|
});
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export default service;
|
// 类型检查
|
||||||
|
function request<T = any>(config: AxiosRequestConfig): Promise<ApiResponse<T>> {
|
||||||
|
return service(config) as unknown as Promise<ApiResponse<T>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default request;
|
||||||
|
// export default service;
|
||||||
@@ -1,153 +1,9 @@
|
|||||||
@use './variables' as *;
|
@use './variables' as *;
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
// 解决外部图标无法居中问题
|
||||||
width: 100%;
|
.ant-btn:has(svg) {
|
||||||
height: 100%;
|
display: inline-flex;
|
||||||
background-color: #000;
|
align-items: center;
|
||||||
color: #fff;
|
justify-content: center;
|
||||||
display: flex;
|
gap: 4px;
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-row {
|
|
||||||
height: 5vh;
|
|
||||||
min-height: 5vh;
|
|
||||||
|
|
||||||
&.title {
|
|
||||||
height: 6vh;
|
|
||||||
min-height: 6vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-size: $title-font-size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.logList-row {
|
|
||||||
flex: 1 1 auto; // 修改
|
|
||||||
min-height: 0; // 新增
|
|
||||||
|
|
||||||
.logList-col {
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logList {
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.ant-col {
|
|
||||||
border-right: 2px solid #fff;
|
|
||||||
border-bottom: 2px solid #fff;
|
|
||||||
font-size: $content-font-size;
|
|
||||||
|
|
||||||
&.option {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 5px 3px 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.subtitle,
|
|
||||||
&.text,
|
|
||||||
&.label {
|
|
||||||
text-align: center;
|
|
||||||
padding: 0 1rem;
|
|
||||||
line-height: 5vh;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.logList-col {
|
|
||||||
padding: 2px 2px 0 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-btn,
|
|
||||||
.ant-btn.ant-btn-sm {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: #d6d6d6;
|
|
||||||
color: #000;
|
|
||||||
font-size: $content-font-size;
|
|
||||||
overflow: hidden;
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid #000;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #000;
|
|
||||||
font-size: 1vw;
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
transform: scale(.9);
|
|
||||||
transition: 100ms;
|
|
||||||
background-color: #252525;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 隐藏空列表
|
|
||||||
:deep(.ant-list-empty-text) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列表
|
|
||||||
.ant-list {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
padding-right: 0 !important;
|
|
||||||
|
|
||||||
.ant-list-item {
|
|
||||||
padding: 4px 12px;
|
|
||||||
color: #fff;
|
|
||||||
font-size: $log-font-size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下拉框
|
|
||||||
.ant-select {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
margin-top: 1px;
|
|
||||||
|
|
||||||
:deep(.ant-select-selector) {
|
|
||||||
height: 100%;
|
|
||||||
border: none;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
:deep(.ant-select-selection-search-input) {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
:deep(.ant-select-selection-item) {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-size: $content-font-size;
|
|
||||||
color: #adff2f;
|
|
||||||
}
|
|
||||||
:deep(.ant-select-selection-placeholder) {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-size: $content-font-size;
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ant-select-suffix svg) {
|
|
||||||
width: 1.5em;
|
|
||||||
height: 1.5em;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
@forward './base';
|
@forward './base';
|
||||||
@forward './variables';
|
@forward './variables';
|
||||||
|
@forward './ant-design';
|
||||||
@@ -41,7 +41,7 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/assets/styles/_variables.scss';
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
.status-item {
|
.status-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
161
src/components/LmsStatus/index.vue
Normal file
161
src/components/LmsStatus/index.vue
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<template>
|
||||||
|
<!-- Status Item -->
|
||||||
|
<div class="status-item status-button" @click="show">
|
||||||
|
<i-lucide-zap class="status-icon" />
|
||||||
|
<span class="status-label">LMS 状态:</span>
|
||||||
|
<span class="status-value" :class="onlineStatusClass">{{ lmsStatus }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-modal v-model:open="dialogVisible" :title="modalTitle" :footer="null">
|
||||||
|
<a-row :gutter="[0, 12]">
|
||||||
|
<a-col :span="8" class="modal-label">LMS 状态</a-col>
|
||||||
|
<a-col :span="16" class="modal-value">
|
||||||
|
<a-switch v-model:checked="isOnline" checked-children="在线" un-checked-children="离线" @change="handleToggleOnline" />
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="[0, 12]">
|
||||||
|
<template v-for="(item, index) in modalItems" :key="index">
|
||||||
|
<a-col :span="8" class="modal-label">{{ item.label }}</a-col>
|
||||||
|
<a-col :span="16" class="modal-value">{{ item.value }}</a-col>
|
||||||
|
</template>
|
||||||
|
</a-row>
|
||||||
|
<div class="actions">
|
||||||
|
<a-button size="large" @click="redirectTo('L1')">L1 数据</a-button>
|
||||||
|
<a-button size="large" @click="redirectTo('L4')">L4 数据</a-button>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, computed } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useDialog } from '@/utils/useDialog';
|
||||||
|
import { fetchLmsWorkMode, updateLmsWorkMode } from '@/api/lms';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
// useDialog管理弹窗状态
|
||||||
|
const { visible: dialogVisible, show, hide } = useDialog();
|
||||||
|
|
||||||
|
const isOnline = ref(false);
|
||||||
|
const lmsStatus = computed(() => isOnline.value ? '在线' : '离线');
|
||||||
|
|
||||||
|
const onlineStatusClass = computed(() => {
|
||||||
|
return isOnline.value ? 'success' : 'error';
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当请求发送成功后才切换状态
|
||||||
|
async function handleToggleOnline(checked: boolean | string | number) {
|
||||||
|
await updateLmsWorkMode(checked ? 1 : 0).then(() => {
|
||||||
|
isOnline.value = Boolean(checked);
|
||||||
|
message.success('切换成功');
|
||||||
|
}).catch((error) => {
|
||||||
|
message.error('切换失败');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const modalTitle = ref('LMS 状态');
|
||||||
|
const modalItems = ref<{ label: string; value: string }[]>([]);
|
||||||
|
|
||||||
|
// 初始化 LMS 状态
|
||||||
|
async function initLmsStatus() {
|
||||||
|
try {
|
||||||
|
const { msg } = await fetchLmsWorkMode();
|
||||||
|
isOnline.value = msg === "1";
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取 LMS 工作模式失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
function redirectTo(type: string) {
|
||||||
|
router.push(`/${type}-data`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化 LMS 状态
|
||||||
|
onMounted(initLmsStatus);
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
show,
|
||||||
|
hide
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
|
.status-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&.status-button {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: #8395B6;
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
color: $success-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
color: $error-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
color: $warning-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #8395B6;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-value {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
color: $success-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
color: $error-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
color: $warning-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-label {
|
||||||
|
font-size: $text-size;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
margin: 20px 0 10px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.ant-btn {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -42,7 +42,7 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/assets/styles/_variables.scss';
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
.status-item {
|
.status-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/assets/styles/_variables.scss';
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
.status-item {
|
.status-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/assets/styles/_variables.scss';
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
.status-item {
|
.status-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/assets/styles/_variables.scss';
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
.modal-label {
|
.modal-label {
|
||||||
font-size: $text-size;
|
font-size: $text-size;
|
||||||
|
|||||||
@@ -27,10 +27,6 @@
|
|||||||
<i-lucide-trash-2 />
|
<i-lucide-trash-2 />
|
||||||
清空日志
|
清空日志
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button @click="test" class="clear-btn">
|
|
||||||
<i-lucide-trash-2 />
|
|
||||||
测试
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sse-logs" ref="logContainer">
|
<div class="sse-logs" ref="logContainer">
|
||||||
@@ -81,16 +77,14 @@ let cooldownTimer: number | null = null;
|
|||||||
|
|
||||||
// 内部日志管理
|
// 内部日志管理
|
||||||
const logContainer = ref();
|
const logContainer = ref();
|
||||||
function test() {
|
|
||||||
addSseLog('测试日志');
|
|
||||||
}
|
|
||||||
// 使用SSE工具函数
|
// 使用SSE工具函数
|
||||||
const {
|
const {
|
||||||
clientId,
|
clientId,
|
||||||
serverUrl,
|
serverUrl,
|
||||||
isConnected,
|
isConnected,
|
||||||
isConnecting,
|
isConnecting,
|
||||||
sseStatusText,
|
sseStatus,
|
||||||
sseStatusClass,
|
sseStatusClass,
|
||||||
logs,
|
logs,
|
||||||
connect,
|
connect,
|
||||||
@@ -127,12 +121,11 @@ const {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const sseStatus = ref(sseStatusText.value);
|
|
||||||
const modalTitle = ref('SSE 连接状态');
|
const modalTitle = ref('SSE 连接状态');
|
||||||
const modalItems = ref([
|
const modalItems = ref([
|
||||||
{ label: '当前状态', value: sseStatus.value },
|
{ label: '当前状态', value: sseStatus },
|
||||||
{ label: '客户端ID', value: clientId || 'hmi-main-client' },
|
{ label: '客户端ID', value: clientId || 'hmi-main-client' },
|
||||||
{ label: '服务器地址', value: serverUrl.value }
|
{ label: '服务器地址', value: serverUrl }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 启动连接冷却时间
|
// 启动连接冷却时间
|
||||||
@@ -175,13 +168,15 @@ const handleClearSseLogs = () => {
|
|||||||
|
|
||||||
// 监听日志变化,自动滚动
|
// 监听日志变化,自动滚动
|
||||||
watch(() => logs.value.length, () => {
|
watch(() => logs.value.length, () => {
|
||||||
const { scrollTop = 0, scrollHeight = 0, clientHeight = 0 } = logContainer.value;
|
if (logContainer.value) {
|
||||||
const isUserAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
|
const { scrollTop = 0, scrollHeight = 0, clientHeight = 0 } = logContainer.value;
|
||||||
nextTick(() => {
|
const isUserAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
|
||||||
if (logContainer.value && isUserAtBottom) {
|
nextTick(() => {
|
||||||
logContainer.value.scrollTop = logContainer.value.scrollHeight;
|
if (logContainer.value && isUserAtBottom) {
|
||||||
}
|
logContainer.value.scrollTop = logContainer.value.scrollHeight;
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 暴露方法和数据
|
// 暴露方法和数据
|
||||||
@@ -207,7 +202,7 @@ onBeforeUnmount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/assets/styles/_variables.scss';
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
.status-item {
|
.status-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "主键",
|
|
||||||
"processInfoId": "加工信息ID",
|
|
||||||
"pltNo": "PLT No",
|
|
||||||
"processF1": "加工F1",
|
|
||||||
"processF2": "加工F2",
|
|
||||||
"goodProductF1": "良品F1",
|
|
||||||
"goodProductF2": "良品F2",
|
|
||||||
"electricalResult": "电气检测结果",
|
|
||||||
"engraveResult": "印字检测结果",
|
|
||||||
"qrCode": "二维码",
|
|
||||||
"qrCodeLevel": "二维码等级",
|
|
||||||
"pressure15Riveting": "压力1_5#_铆接",
|
|
||||||
"height15Riveting": "高度1_5#_铆接",
|
|
||||||
"pressure25Magnet1": "压力2_5#_磁石1",
|
|
||||||
"height25Magnet1": "高度2_5#_磁石1",
|
|
||||||
"pressure36Magnet2": "压力3_6#_磁石2",
|
|
||||||
"height36Magnet2": "高度3_6#_磁石2",
|
|
||||||
"torque47AxisInsert": "扭矩4_7#_轴旋入",
|
|
||||||
"height47AxisInsert": "高度4_7#_轴旋入",
|
|
||||||
"pressure58LowerCase": "压力5_8#_下壳装入",
|
|
||||||
"height58LowerCase": "高度5_8#_下壳装入",
|
|
||||||
"pressure69UpperCase": "压力6_9#_上壳装入",
|
|
||||||
"height69UpperCase": "高度6_9#_上壳装入",
|
|
||||||
"height79HeightCheck": "高度7_9#_高度检测",
|
|
||||||
"pressure79Laser": "压力7_9#_激光",
|
|
||||||
"height89Laser": "高度8_9#_激光",
|
|
||||||
"value19DcrUpper": "数値1_9#_DCR(上)",
|
|
||||||
"value29DcrLower": "数値2_9#_DCR(下)",
|
|
||||||
"value39LcrUpperLs": "数値3_9#_LCR(上)LS",
|
|
||||||
"value49LcrLowerQ": "数値4_9#_LCR(下)Q",
|
|
||||||
"value59LcrLowerLs": "数値5_9#_LCR(下)LS",
|
|
||||||
"value69LcrLowerQ": "数値6_9#_LCR(下)Q",
|
|
||||||
"value79IrR": "数値7_9#_IR R",
|
|
||||||
"value89IrI": "数値8_9#_IR I",
|
|
||||||
"createTime": "创建时间"
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
// import Antd from "ant-design-vue";
|
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
|
|
||||||
// Pinia 状态管理
|
// Pinia 状态管理
|
||||||
@@ -11,7 +10,7 @@ import router from "./router";
|
|||||||
|
|
||||||
// 样式文件
|
// 样式文件
|
||||||
import "ant-design-vue/dist/reset.css";
|
import "ant-design-vue/dist/reset.css";
|
||||||
import "./assets/styles/index.scss";
|
import "@/assets/styles/index.scss";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
app.use(pinia).use(router).mount("#app");
|
app.use(pinia).use(router).mount("#app");
|
||||||
|
|||||||
@@ -15,6 +15,16 @@ const routes = [
|
|||||||
path: '/package-station',
|
path: '/package-station',
|
||||||
name: 'PackageStation',
|
name: 'PackageStation',
|
||||||
component: () => import('@/views/package-station/index.vue')
|
component: () => import('@/views/package-station/index.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/L1-data',
|
||||||
|
name: 'L1Data',
|
||||||
|
component: () => import('@/views/L1-data-list/index.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/L4-data',
|
||||||
|
name: 'L4Data',
|
||||||
|
component: () => import('@/views/L4-data-list/index.vue')
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
5
src/shim-vue.d.ts
vendored
Normal file
5
src/shim-vue.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
declare module "*.vue" {
|
||||||
|
import type { DefineComponent } from "vue";
|
||||||
|
const component: DefineComponent<{}, {}, any>;
|
||||||
|
export default component;
|
||||||
|
}
|
||||||
@@ -3,7 +3,8 @@ import { EventSourcePolyfill } from 'event-source-polyfill';
|
|||||||
import { generateUUID } from './uuidUtils';
|
import { generateUUID } from './uuidUtils';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
|
|
||||||
const defaultServerUrl = 'http://192.168.1.38:18081/sse';
|
// const defaultServerUrl = 'http://192.168.1.38:18081/sse';
|
||||||
|
const defaultServerUrl = 'http://127.0.0.1:18081/sse';
|
||||||
|
|
||||||
interface EventData {
|
interface EventData {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@@ -66,7 +67,7 @@ export function useSSE(options: SSEOptions) {
|
|||||||
let connectionTimeout: number | null = null;
|
let connectionTimeout: number | null = null;
|
||||||
|
|
||||||
// 计算属性
|
// 计算属性
|
||||||
const sseStatusText = computed(() => {
|
const sseStatus = computed(() => {
|
||||||
if (isConnecting.value) return '连接中';
|
if (isConnecting.value) return '连接中';
|
||||||
if (isConnected.value) return '已连接';
|
if (isConnected.value) return '已连接';
|
||||||
return '未连接';
|
return '未连接';
|
||||||
@@ -234,7 +235,7 @@ export function useSSE(options: SSEOptions) {
|
|||||||
isConnected,
|
isConnected,
|
||||||
clientId,
|
clientId,
|
||||||
serverUrl,
|
serverUrl,
|
||||||
sseStatusText,
|
sseStatus,
|
||||||
sseStatusClass,
|
sseStatusClass,
|
||||||
connect,
|
connect,
|
||||||
disconnect,
|
disconnect,
|
||||||
|
|||||||
48
src/views/L1-data-list/data.ts
Normal file
48
src/views/L1-data-list/data.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import type { TableColumnType, TableColumnsType } from "ant-design-vue";
|
||||||
|
|
||||||
|
const INDEX_COLUMN: TableColumnType = {
|
||||||
|
key: "index",
|
||||||
|
title: "序号",
|
||||||
|
width: 60,
|
||||||
|
fixed: true,
|
||||||
|
align: "center",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// 定义操作列配置
|
||||||
|
const ACTION_COLUMN: TableColumnType = {
|
||||||
|
key: "action",
|
||||||
|
title: "操作",
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
fixed: "right",
|
||||||
|
align: "center",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// 使用 Record 类型确保键值对的安全性
|
||||||
|
export const fields: Record<string, string> = {
|
||||||
|
productStatus: "产品状态",
|
||||||
|
goodFlag: "良品标记",
|
||||||
|
processMemory: "加工记忆",
|
||||||
|
functionSw: "功能SW",
|
||||||
|
axisNumber: "轴号",
|
||||||
|
plugTerminalPressure: "插端子压力值",
|
||||||
|
plugTerminalHeight: "插端子高度值",
|
||||||
|
resistance: "电阻值",
|
||||||
|
inductorLs: "电感LS值",
|
||||||
|
inductorQ: "电感Q值",
|
||||||
|
pressureResistanceR: "耐压R值",
|
||||||
|
pressureResistanceI: "耐压I值",
|
||||||
|
visualResult: "视觉结果",
|
||||||
|
createTime: "创建时间",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// 导出完整的列配置
|
||||||
|
export const columns: TableColumnsType = [
|
||||||
|
INDEX_COLUMN,
|
||||||
|
...Object.entries(fields).map(([key, title]) => ({
|
||||||
|
key,
|
||||||
|
title,
|
||||||
|
ellipsis: true,
|
||||||
|
})),
|
||||||
|
ACTION_COLUMN,
|
||||||
|
];
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
<template>
|
||||||
|
<div class="l1-data-container">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1 class="page-title">L1数据列表</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<a-form layout="inline" :model="formData">
|
||||||
|
<a-form-item label="日期范围">
|
||||||
|
<a-range-picker v-model:value="formData.dateRange" :placeholder="['开始日期', '结束日期']"
|
||||||
|
format="YYYY-MM-DD hh:mm:ss" class="date-range-picker" show-time />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="handleSearch" :loading="loading">
|
||||||
|
<template #icon>
|
||||||
|
<i-lucide-search />
|
||||||
|
</template>
|
||||||
|
搜索
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleReset">
|
||||||
|
<template #icon>
|
||||||
|
<i-lucide-refresh-cw />
|
||||||
|
</template>
|
||||||
|
重置
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<div class="table-section">
|
||||||
|
<a-table :columns="columns" :data-source="tableData" :loading="loading" :pagination="pagination"
|
||||||
|
@change="handleTableChange" row-key="id" size="middle" :scroll="{ x: 1200 }">
|
||||||
|
<template #bodyCell="{ column, record, index }">
|
||||||
|
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
|
||||||
|
<template v-else-if="column.key === 'createTime'">
|
||||||
|
<span>{{ formatDateTime(record.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
<!-- <template v-else-if="column.key === 'productStatus'">
|
||||||
|
<a-tag :color="record.productStatus === 1 ? 'success' : 'default'">
|
||||||
|
{{ record.productStatus === 1 ? '有' : '无' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'goodFlag'">
|
||||||
|
<a-tag :color="record.goodFlag === 1 ? 'success' : 'error'">
|
||||||
|
{{ record.goodFlag === 1 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'processMemory'">
|
||||||
|
<a-tag :color="record.processMemory === 1 ? 'success' : 'default'">
|
||||||
|
{{ record.processMemory === 1 ? '已加工' : '未开工' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'functionSw'">
|
||||||
|
<a-tag :color="record.functionSw === 1 ? 'success' : 'default'">
|
||||||
|
{{ record.functionSw === 1 ? '有效' : '无效' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'visualResult'">
|
||||||
|
<a-tag :color="record.visualResult === 1 ? 'success' : 'error'">
|
||||||
|
{{ record.visualResult === 1 ? 'OK' : 'NG' }}
|
||||||
|
</a-tag>
|
||||||
|
</template> -->
|
||||||
|
<template v-else-if="column.key === 'action'">
|
||||||
|
<a-button type="link" size="small" @click="handleView(record as L1Data)">
|
||||||
|
查看详情
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ record[column.key as string] }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 详情弹窗 -->
|
||||||
|
<a-modal v-model:open="detailVisible" title="详情信息" :footer="null" width="800px">
|
||||||
|
<div v-if="selectedRecord" class="detail-content">
|
||||||
|
<a-descriptions :column="2" bordered>
|
||||||
|
<a-descriptions-item
|
||||||
|
v-for="(value, key) in selectedRecord"
|
||||||
|
:key="key"
|
||||||
|
:label="columns.find((col) => col.key === key)?.title || key"
|
||||||
|
>
|
||||||
|
<template v-if="key === 'createTime'">
|
||||||
|
{{ formatDateTime(value) }}
|
||||||
|
</template>
|
||||||
|
<!-- <template v-else-if="key === 'productStatus'">
|
||||||
|
<a-tag :color="selectedRecord.productStatus === 1 ? 'success' : 'default'">
|
||||||
|
{{ selectedRecord.productStatus === 1 ? '有' : '无' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'goodFlag'">
|
||||||
|
<a-tag :color="selectedRecord.goodFlag === 1 ? 'success' : 'error'">
|
||||||
|
{{ selectedRecord.goodFlag === 1 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'processMemory'">
|
||||||
|
<a-tag :color="selectedRecord.processMemory === 1 ? 'success' : 'default'">
|
||||||
|
{{ selectedRecord.processMemory === 1 ? '已加工' : '未开工' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'functionSw'">
|
||||||
|
<a-tag :color="selectedRecord.functionSw === 1 ? 'success' : 'default'">
|
||||||
|
{{ selectedRecord.functionSw === 1 ? '有效' : '无效' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'visualResult'">
|
||||||
|
<a-tag :color="selectedRecord.visualResult === 1 ? 'success' : 'error'">
|
||||||
|
{{ selectedRecord.visualResult === 1 ? 'OK' : 'NG' }}
|
||||||
|
</a-tag>
|
||||||
|
</template> -->
|
||||||
|
<template v-else>
|
||||||
|
{{ value }}
|
||||||
|
</template>
|
||||||
|
</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted } from "vue";
|
||||||
|
import { message } from "ant-design-vue";
|
||||||
|
import { getL1Data } from "@/api/data";
|
||||||
|
import type { QueryParams } from "@/api/data/model";
|
||||||
|
import type { L1Data } from "./types";
|
||||||
|
import type { Dayjs } from "dayjs";
|
||||||
|
import { columns } from "./data";
|
||||||
|
|
||||||
|
type DateRangeType = [Dayjs, Dayjs] | undefined;
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const loading = ref(false);
|
||||||
|
const tableData = ref<L1Data[]>([]);
|
||||||
|
const formData = reactive<{ dateRange: DateRangeType }>({
|
||||||
|
dateRange: undefined,
|
||||||
|
});
|
||||||
|
const detailVisible = ref(false);
|
||||||
|
const selectedRecord = ref<L1Data | null>(null);
|
||||||
|
|
||||||
|
// 分页配置
|
||||||
|
const pagination = reactive({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total: number) => `共 ${total} 条`,
|
||||||
|
pageSizeOptions: ["10", "20", "50", "100"],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const params: QueryParams = {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加日期范围筛选
|
||||||
|
if (formData.dateRange && formData.dateRange.length === 2) {
|
||||||
|
params.createTimeBegin = formData.dateRange[0].format("YYYY-MM-DD hh:mm:ss");
|
||||||
|
params.createTimeEnd = formData.dateRange[1].format("YYYY-MM-DD hh:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await getL1Data(params);
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
tableData.value = res.rows || [];
|
||||||
|
pagination.total = res.total || 0;
|
||||||
|
} else {
|
||||||
|
message.error(res.msg || "获取数据失败");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取L1数据失败:", error);
|
||||||
|
message.error("获取数据失败,请稍后重试");
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索处理
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.current = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置处理
|
||||||
|
const handleReset = () => {
|
||||||
|
formData.dateRange = undefined;
|
||||||
|
pagination.current = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格变化处理(分页、排序等)
|
||||||
|
const handleTableChange = (pag: any, filters: any, sorter: any) => {
|
||||||
|
pagination.current = pag.current;
|
||||||
|
pagination.pageSize = pag.pageSize;
|
||||||
|
|
||||||
|
// 处理排序
|
||||||
|
if (sorter.field) {
|
||||||
|
// 这里可以根据需要添加排序逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查看详情
|
||||||
|
const handleView = (record: L1Data) => {
|
||||||
|
selectedRecord.value = record;
|
||||||
|
detailVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime: string | number) => {
|
||||||
|
if (!dateTime) return null;
|
||||||
|
return new Date(dateTime).toLocaleString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组件挂载时获取数据
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l1-data-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
padding: $spacing-lg;
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
margin-bottom: $spacing-lg;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-size: $title-font-size;
|
||||||
|
color: $text-dark;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-section {
|
||||||
|
background: $bg-light;
|
||||||
|
padding: $spacing-lg;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
margin-bottom: $spacing-lg;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.filter-label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: $text-dark;
|
||||||
|
font-size: $content-font-size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-section {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
:deep(.ant-table-wrapper) {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.ant-spin-container,
|
||||||
|
.ant-table {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-container {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-body {
|
||||||
|
overflow-y: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
.ant-descriptions {
|
||||||
|
margin-top: $spacing-md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-btn-primary) {
|
||||||
|
background: $primary-color;
|
||||||
|
border-color: $primary-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $primary-light;
|
||||||
|
border-color: $primary-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.l1-data-container {
|
||||||
|
padding: $spacing-md;
|
||||||
|
|
||||||
|
.filter-section {
|
||||||
|
.ant-row {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-md;
|
||||||
|
|
||||||
|
.ant-col {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-range-picker {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
58
src/views/L1-data-list/types.ts
Normal file
58
src/views/L1-data-list/types.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
export interface L1Data {
|
||||||
|
/** 加工信息ID */
|
||||||
|
processInfoId: number;
|
||||||
|
|
||||||
|
/** 产品状态: 0-无, 1-有 */
|
||||||
|
productStatus: 0 | 1;
|
||||||
|
|
||||||
|
/** 良品标记: 0-不良品, 1-良品 */
|
||||||
|
goodFlag: 0 | 1;
|
||||||
|
|
||||||
|
/** 加工记忆: 0-未开工, 1-已加工 */
|
||||||
|
processMemory: 0 | 1;
|
||||||
|
|
||||||
|
/** 功能SW: 0-无效, 1-有效 */
|
||||||
|
functionSw: 0 | 1;
|
||||||
|
|
||||||
|
/** 轴号 */
|
||||||
|
axisNumber: number;
|
||||||
|
|
||||||
|
/** 上骨架时间: 年, 00~99 */
|
||||||
|
loadSkeletonYear: number;
|
||||||
|
|
||||||
|
/** 上骨架时间: 月日, 0101~1231 */
|
||||||
|
loadSkeletonMonthDay: number;
|
||||||
|
|
||||||
|
/** 上骨架时间: 时分, 0000~2459 */
|
||||||
|
loadSkeletonHourMin: number;
|
||||||
|
|
||||||
|
/** 上骨架时间: 秒, 00~59 */
|
||||||
|
loadSkeletonSecond: number;
|
||||||
|
|
||||||
|
/** 插端子压力值 */
|
||||||
|
plugTerminalPressure: number;
|
||||||
|
|
||||||
|
/** 插端子高度值 */
|
||||||
|
plugTerminalHeight: number;
|
||||||
|
|
||||||
|
/** 电阻值 */
|
||||||
|
resistance: number;
|
||||||
|
|
||||||
|
/** 电感LS值 */
|
||||||
|
inductorLs: number;
|
||||||
|
|
||||||
|
/** 电感Q值 */
|
||||||
|
inductorQ: number;
|
||||||
|
|
||||||
|
/** 耐压R值 */
|
||||||
|
pressureResistanceR: number;
|
||||||
|
|
||||||
|
/** 耐压I值 */
|
||||||
|
pressureResistanceI: number;
|
||||||
|
|
||||||
|
/** 视觉结果: 0-NG, 1-OK */
|
||||||
|
visualResult: 0 | 1;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime: string; // ISO 8601 格式,如 "2025-09-23T12:34:56"
|
||||||
|
}
|
||||||
69
src/views/L4-data-list/data.ts
Normal file
69
src/views/L4-data-list/data.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import type { TableColumnType, TableColumnsType } from "ant-design-vue";
|
||||||
|
|
||||||
|
const INDEX_COLUMN: TableColumnType = {
|
||||||
|
key: "index",
|
||||||
|
title: "序号",
|
||||||
|
width: 60,
|
||||||
|
fixed: true,
|
||||||
|
align: "center",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// 定义操作列配置
|
||||||
|
const ACTION_COLUMN: TableColumnType = {
|
||||||
|
key: "action",
|
||||||
|
title: "操作",
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
fixed: "right",
|
||||||
|
align: "center",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// 使用 Record 类型确保键值对的安全性
|
||||||
|
export const fields: Record<string, string> = {
|
||||||
|
processInfoId: "加工信息ID",
|
||||||
|
pltNo: "PLT No",
|
||||||
|
processF1: "加工F1",
|
||||||
|
processF2: "加工F2",
|
||||||
|
goodProductF1: "良品F1",
|
||||||
|
goodProductF2: "良品F2",
|
||||||
|
electricalResult: "电气检测结果",
|
||||||
|
engraveResult: "印字检测结果",
|
||||||
|
qrCode: "二维码",
|
||||||
|
qrCodeLevel: "二维码等级",
|
||||||
|
pressure15Riveting: "压力1_5#_铆接",
|
||||||
|
height15Riveting: "高度1_5#_铆接",
|
||||||
|
pressure25Magnet1: "压力2_5#_磁石1",
|
||||||
|
height25Magnet1: "高度2_5#_磁石1",
|
||||||
|
pressure36Magnet2: "压力3_6#_磁石2",
|
||||||
|
height36Magnet2: "高度3_6#_磁石2",
|
||||||
|
torque47AxisInsert: "扭矩4_7#_轴旋入",
|
||||||
|
height47AxisInsert: "高度4_7#_轴旋入",
|
||||||
|
pressure58LowerCase: "压力5_8#_下壳装入",
|
||||||
|
height58LowerCase: "高度5_8#_下壳装入",
|
||||||
|
pressure69UpperCase: "压力6_9#_上壳装入",
|
||||||
|
height69UpperCase: "高度6_9#_上壳装入",
|
||||||
|
height79HeightCheck: "高度7_9#_高度检测",
|
||||||
|
pressure79Laser: "压力7_9#_激光",
|
||||||
|
height89Laser: "高度8_9#_激光",
|
||||||
|
value19DcrUpper: "数値1_9#_DCR(上)",
|
||||||
|
value29DcrLower: "数値2_9#_DCR(下)",
|
||||||
|
value39LcrUpperLs: "数値3_9#_LCR(上)LS",
|
||||||
|
value49LcrLowerQ: "数値4_9#_LCR(下)Q",
|
||||||
|
value59LcrLowerLs: "数値5_9#_LCR(下)LS",
|
||||||
|
value69LcrLowerQ: "数値6_9#_LCR(下)Q",
|
||||||
|
value79IrR: "数値7_9#_IR R",
|
||||||
|
value89IrI: "数値8_9#_IR I",
|
||||||
|
createTime: "创建时间"
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// 导出完整的列配置
|
||||||
|
export const columns: TableColumnsType = [
|
||||||
|
INDEX_COLUMN,
|
||||||
|
...Object.entries(fields).map(([key, title]) => ({
|
||||||
|
key,
|
||||||
|
title,
|
||||||
|
width: 150,
|
||||||
|
ellipsis: true,
|
||||||
|
})),
|
||||||
|
ACTION_COLUMN,
|
||||||
|
];
|
||||||
@@ -0,0 +1,336 @@
|
|||||||
|
<template>
|
||||||
|
<div class="l4-data-container">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1 class="page-title">L4数据列表</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<a-form layout="inline" :model="formData">
|
||||||
|
<a-form-item label="日期范围">
|
||||||
|
<a-range-picker
|
||||||
|
v-model:value="formData.dateRange"
|
||||||
|
:placeholder="['开始日期', '结束日期']"
|
||||||
|
format="YYYY-MM-DD hh:mm:ss"
|
||||||
|
class="date-range-picker"
|
||||||
|
show-time
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="handleSearch" :loading="loading">
|
||||||
|
<template #icon>
|
||||||
|
<i-lucide-search />
|
||||||
|
</template>
|
||||||
|
搜索
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleReset">
|
||||||
|
<template #icon>
|
||||||
|
<i-lucide-refresh-cw />
|
||||||
|
</template>
|
||||||
|
重置
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<div class="table-section">
|
||||||
|
<a-table
|
||||||
|
:columns="columns"
|
||||||
|
:data-source="tableData"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
@change="handleTableChange"
|
||||||
|
row-key="id"
|
||||||
|
size="middle"
|
||||||
|
:scroll="{ x: 1200 }"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'createTime'">
|
||||||
|
{{ formatDateTime(record.createTime) }}
|
||||||
|
</template>
|
||||||
|
<!-- <template v-else-if="column.key === 'processF1'">
|
||||||
|
<a-tag :color="record.processF1 === 1 ? 'green' : 'red'">
|
||||||
|
{{ record.processF1 === 1 ? '已加工' : '未加工' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'processF2'">
|
||||||
|
<a-tag :color="record.processF2 === 1 ? 'green' : 'red'">
|
||||||
|
{{ record.processF2 === 1 ? '已加工' : '未加工' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'goodProductF1'">
|
||||||
|
<a-tag :color="record.goodProductF1 === 1 ? 'green' : 'red'">
|
||||||
|
{{ record.goodProductF1 === 1 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'goodProductF2'">
|
||||||
|
<a-tag :color="record.goodProductF2 === 1 ? 'green' : 'red'">
|
||||||
|
{{ record.goodProductF2 === 1 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'electricalResult'">
|
||||||
|
<a-tag :color="getElectricalResultColor(record.electricalResult)">
|
||||||
|
{{ getElectricalResultText(record.electricalResult) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'engraveResult'">
|
||||||
|
<a-tag :color="record.engraveResult === 0 ? 'green' : 'red'">
|
||||||
|
{{ record.engraveResult === 0 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template> -->
|
||||||
|
<template v-else-if="column.key === 'action'">
|
||||||
|
<a-button type="link" size="small" @click="handleView(record as L4Data)">
|
||||||
|
查看详情
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 详情弹窗 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="detailModalVisible"
|
||||||
|
title="L4数据详情"
|
||||||
|
width="800px"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<div v-if="selectedRecord" class="detail-content">
|
||||||
|
<a-descriptions :column="2" bordered>
|
||||||
|
<a-descriptions-item
|
||||||
|
v-for="(value, key) in selectedRecord"
|
||||||
|
:key="key"
|
||||||
|
:label="columns.find((col) => col.key === key)?.title || key"
|
||||||
|
>
|
||||||
|
<template v-if="key === 'createTime'">
|
||||||
|
{{ formatDateTime(value) }}
|
||||||
|
</template>
|
||||||
|
<!-- <template v-else-if="key === 'processF1'">
|
||||||
|
<a-tag :color="value === 1 ? 'green' : 'red'">
|
||||||
|
{{ value === 1 ? '已加工' : '未加工' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'processF2'">
|
||||||
|
<a-tag :color="value === 1 ? 'green' : 'red'">
|
||||||
|
{{ value === 1 ? '已加工' : '未加工' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'goodProductF1'">
|
||||||
|
<a-tag :color="value === 1 ? 'green' : 'red'">
|
||||||
|
{{ value === 1 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'goodProductF2'">
|
||||||
|
<a-tag :color="value === 1 ? 'green' : 'red'">
|
||||||
|
{{ value === 1 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'electricalResult'">
|
||||||
|
<a-tag :color="getElectricalResultColor(value)">
|
||||||
|
{{ getElectricalResultText(value) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="key === 'engraveResult'">
|
||||||
|
<a-tag :color="value === 0 ? 'green' : 'red'">
|
||||||
|
{{ value === 0 ? '良品' : '不良品' }}
|
||||||
|
</a-tag>
|
||||||
|
</template> -->
|
||||||
|
<template v-else>
|
||||||
|
{{ value }}
|
||||||
|
</template>
|
||||||
|
</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed, onMounted } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import { getL4Data } from '@/api/data';
|
||||||
|
import { columns } from './data';
|
||||||
|
import type { QueryParams } from '@/api/data/model';
|
||||||
|
import type { L4Data } from './types';
|
||||||
|
import type { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
|
type DateRangeType = [Dayjs, Dayjs] | undefined;
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const loading = ref(false);
|
||||||
|
const tableData = ref<L4Data[]>([]);
|
||||||
|
const detailModalVisible = ref(false);
|
||||||
|
const selectedRecord = ref<L4Data | null>(null);
|
||||||
|
|
||||||
|
// 筛选参数
|
||||||
|
const formData = reactive<{ dateRange: DateRangeType }>({
|
||||||
|
dateRange: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 分页配置
|
||||||
|
const pagination = reactive({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total: number, range: [number, number]) =>
|
||||||
|
`共 ${total} 条记录,当前显示第 ${range[0]}-${range[1]} 条`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 电气检测结果颜色
|
||||||
|
const getElectricalResultColor = (result: number) => {
|
||||||
|
switch (result) {
|
||||||
|
case 7: return 'green';
|
||||||
|
case 0: return 'red';
|
||||||
|
case 1: return 'orange';
|
||||||
|
case 3: return 'purple';
|
||||||
|
default: return 'default';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 电气检测结果文本
|
||||||
|
const getElectricalResultText = (result: number) => {
|
||||||
|
switch (result) {
|
||||||
|
case 0: return 'DCR不良';
|
||||||
|
case 1: return 'LCR不良';
|
||||||
|
case 3: return 'IR不良';
|
||||||
|
case 7: return '良品';
|
||||||
|
default: return '未知';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const params: QueryParams = {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加日期范围筛选
|
||||||
|
if (formData.dateRange && formData.dateRange.length === 2) {
|
||||||
|
params.createTimeBegin = formData.dateRange[0].format("YYYY-MM-DD hh:mm:ss");
|
||||||
|
params.createTimeEnd = formData.dateRange[1].format("YYYY-MM-DD hh:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await getL4Data(params);
|
||||||
|
|
||||||
|
if (response.code === 200) {
|
||||||
|
tableData.value = response.rows || [];
|
||||||
|
pagination.total = response.total || 0;
|
||||||
|
} else {
|
||||||
|
message.error(response.msg || "获取数据失败");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取L4数据失败:", error);
|
||||||
|
message.error("获取数据失败,请稍后重试");
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索处理
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.current = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置处理
|
||||||
|
const handleReset = () => {
|
||||||
|
formData.dateRange = undefined;
|
||||||
|
pagination.current = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格变化处理(分页、排序等)
|
||||||
|
const handleTableChange = (paginationInfo: any) => {
|
||||||
|
pagination.current = paginationInfo.current;
|
||||||
|
pagination.pageSize = paginationInfo.pageSize;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查看详情
|
||||||
|
const handleView = (record: L4Data) => {
|
||||||
|
selectedRecord.value = record;
|
||||||
|
detailModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 日期时间格式化
|
||||||
|
const formatDateTime = (dateTime: string | number) => {
|
||||||
|
if (!dateTime) return '-';
|
||||||
|
return new Date(dateTime).toLocaleString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组件挂载时获取数据
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.l4-data-container {
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1f2937;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-section {
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-range-picker {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-section {
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-table-thead > tr > th) {
|
||||||
|
background: #f8fafc;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-table-tbody > tr:hover > td) {
|
||||||
|
background: #f0f9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-descriptions-item-label) {
|
||||||
|
font-weight: 600;
|
||||||
|
background: #f8fafc;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
106
src/views/L4-data-list/types.ts
Normal file
106
src/views/L4-data-list/types.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
export interface L4Data {
|
||||||
|
/** 加工信息ID */
|
||||||
|
processInfoId: number;
|
||||||
|
|
||||||
|
/** PLT No */
|
||||||
|
pltNo: number;
|
||||||
|
|
||||||
|
/** 加工F1, 0:未加工 */
|
||||||
|
processF1: 0 | 1;
|
||||||
|
|
||||||
|
/** 加工F2, 1:已加工 */
|
||||||
|
processF2: 0 | 1;
|
||||||
|
|
||||||
|
/** 良品F1, 0:不良品 */
|
||||||
|
goodProductF1: 0 | 1;
|
||||||
|
|
||||||
|
/** 良品F2, 1:良品 */
|
||||||
|
goodProductF2: 0 | 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电气检测结果
|
||||||
|
* 0-DCR不良, 1-LCR不良, 3-IR不良, 7-良品
|
||||||
|
*/
|
||||||
|
electricalResult: 0 | 1 | 3 | 7;
|
||||||
|
|
||||||
|
/** 印字检测结果, 0-良品, 1-不良品 */
|
||||||
|
engraveResult: 0 | 1;
|
||||||
|
|
||||||
|
/** 二维码 */
|
||||||
|
qrCode: string;
|
||||||
|
|
||||||
|
/** 二维码等级 */
|
||||||
|
qrCodeLevel: string;
|
||||||
|
|
||||||
|
/** 压力1_5#_铆接 */
|
||||||
|
pressure15Riveting: number;
|
||||||
|
|
||||||
|
/** 高度1_5#_铆接 */
|
||||||
|
height15Riveting: number;
|
||||||
|
|
||||||
|
/** 压力2_5#_磁石1 */
|
||||||
|
pressure25Magnet1: number;
|
||||||
|
|
||||||
|
/** 高度2_5#_磁石1 */
|
||||||
|
height25Magnet1: number;
|
||||||
|
|
||||||
|
/** 压力3_6#_磁石2 */
|
||||||
|
pressure36Magnet2: number;
|
||||||
|
|
||||||
|
/** 高度3_6#_磁石2 */
|
||||||
|
height36Magnet2: number;
|
||||||
|
|
||||||
|
/** 扭矩4_7#_轴旋入 */
|
||||||
|
torque47AxisInsert: number;
|
||||||
|
|
||||||
|
/** 高度4_7#_轴旋入 */
|
||||||
|
height47AxisInsert: number;
|
||||||
|
|
||||||
|
/** 压力5_8#_下壳装入 */
|
||||||
|
pressure58LowerCase: number;
|
||||||
|
|
||||||
|
/** 高度5_8#_下壳装入 */
|
||||||
|
height58LowerCase: number;
|
||||||
|
|
||||||
|
/** 压力6_9#_上壳装入 */
|
||||||
|
pressure69UpperCase: number;
|
||||||
|
|
||||||
|
/** 高度6_9#_上壳装入 */
|
||||||
|
height69UpperCase: number;
|
||||||
|
|
||||||
|
/** 高度7_9#_高度检测 */
|
||||||
|
height79HeightCheck: number;
|
||||||
|
|
||||||
|
/** 压力7_9#_激光 */
|
||||||
|
pressure79Laser: number;
|
||||||
|
|
||||||
|
/** 高度8_9#_激光 */
|
||||||
|
height89Laser: number;
|
||||||
|
|
||||||
|
/** 数値1_9#_DCR(上) */
|
||||||
|
value19DcrUpper: number;
|
||||||
|
|
||||||
|
/** 数値2_9#_DCR(下) */
|
||||||
|
value29DcrLower: number;
|
||||||
|
|
||||||
|
/** 数値3_9#_LCR(上)LS */
|
||||||
|
value39LcrUpperLs: number;
|
||||||
|
|
||||||
|
/** 数値4_9#_LCR(下)Q */
|
||||||
|
value49LcrLowerQ: number;
|
||||||
|
|
||||||
|
/** 数値5_9#_LCR(下)LS */
|
||||||
|
value59LcrLowerLs: number;
|
||||||
|
|
||||||
|
/** 数値6_9#_LCR(下)Q */
|
||||||
|
value69LcrLowerQ: number;
|
||||||
|
|
||||||
|
/** 数値7_9#_IR R */
|
||||||
|
value79IrR: number;
|
||||||
|
|
||||||
|
/** 数値8_9#_IR I */
|
||||||
|
value89IrI: number;
|
||||||
|
|
||||||
|
/** 创建时间 (ISO 8601) */
|
||||||
|
createTime: string;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { ref, onMounted, onBeforeUnmount, reactive, nextTick } from 'vue';
|
|||||||
import { useRealTime } from '@/utils/dateUtils';
|
import { useRealTime } from '@/utils/dateUtils';
|
||||||
import { checkOrderNumberApi, addProcessInfoApi } from '@/api/detect';
|
import { checkOrderNumberApi, addProcessInfoApi } from '@/api/detect';
|
||||||
import type { Rule } from 'ant-design-vue/es/form';
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
// 检测设备表单规则
|
// 检测设备表单规则
|
||||||
const rules: Record<string, Rule[]> = {
|
const rules: Record<string, Rule[]> = {
|
||||||
@@ -44,23 +45,9 @@ const detectFormRef = ref();
|
|||||||
const packageFormRef = ref();
|
const packageFormRef = ref();
|
||||||
|
|
||||||
// 执行结果日志
|
// 执行结果日志
|
||||||
const executionLogs = ref([
|
const executionLogs = ref<string[]>([]);
|
||||||
'14:25:32 - 开始检测流程 SN-A538-09-2023-00018',
|
|
||||||
'14:25:33 - 读取产品参数完成',
|
|
||||||
'14:25:36 - 尺寸检测: 通过 (0.15mm)',
|
|
||||||
'14:25:36 - 电压检测: 通过 (3.25V)',
|
|
||||||
'14:25:37 - 精度检测: 通过 (98.7%)',
|
|
||||||
'14:25:38 - 检测结果: 合格'
|
|
||||||
]);
|
|
||||||
|
|
||||||
const packageLogs = ref([
|
const packageLogs = ref<string[]>([]);
|
||||||
'14:25:45 - 包装流程: SN-A538-09-2023-00018',
|
|
||||||
'14:25:46 - 读取产品标签完成',
|
|
||||||
'14:25:49 - 包装材料准备完成',
|
|
||||||
'14:25:52 - 产品包装完成',
|
|
||||||
'14:25:53 - 更新库存: 已包装 (18/25)',
|
|
||||||
'14:25:54 - 包装结果: 正常'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 滚动到检测设备日志底部的函数
|
// 滚动到检测设备日志底部的函数
|
||||||
const scrollToExecutionBottom = () => {
|
const scrollToExecutionBottom = () => {
|
||||||
@@ -262,6 +249,7 @@ const saveDetectingEdit = () => {
|
|||||||
fixtureCode: detectForm.fixtureCode
|
fixtureCode: detectForm.fixtureCode
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
|
message.success('保存成功');
|
||||||
})
|
})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
console.log('检测设备表单验证失败');
|
console.log('检测设备表单验证失败');
|
||||||
@@ -350,6 +338,9 @@ onBeforeUnmount(() => {
|
|||||||
:on-mes-event="handleMESEvent"
|
:on-mes-event="handleMESEvent"
|
||||||
:on-sse-message="handleSseMessage"
|
:on-sse-message="handleSseMessage"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- LMS 状态 -->
|
||||||
|
<LmsStatus />
|
||||||
</div>
|
</div>
|
||||||
<SettingsModal />
|
<SettingsModal />
|
||||||
<!-- <div class="right-info" @click="showSettings">
|
<!-- <div class="right-info" @click="showSettings">
|
||||||
@@ -569,7 +560,7 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/assets/styles/_variables.scss';
|
@use "@/assets/styles/variables" as *;
|
||||||
|
|
||||||
.hmi-container {
|
.hmi-container {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"composite": true,
|
"composite": true,
|
||||||
|
|
||||||
/* Bundler mode */
|
/* Bundler mode */
|
||||||
|
"noEmit": true,
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"vite.config.ts",
|
"vite.config.ts",
|
||||||
"src/**/*.d.ts"
|
"src/**/*.d.ts",
|
||||||
|
"src/shim-vue.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defineConfig, loadEnv } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import Components from "unplugin-vue-components/vite"; // 按需组件自动导入
|
import Components from "unplugin-vue-components/vite"; // 按需组件自动导入
|
||||||
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
|
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
|
||||||
import vue from '@vitejs/plugin-vue';
|
import vue from '@vitejs/plugin-vue';
|
||||||
@@ -8,19 +8,38 @@ import path from 'path';
|
|||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
"/api": {
|
||||||
|
target: "http://192.168.1.38:18081",
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||||
|
},
|
||||||
|
"/prod-api": {
|
||||||
|
target: "http://127.0.0.1:18081",
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
Components({
|
Components({
|
||||||
dts: true, //生成components.d.ts 全局定义文件
|
dts: true, //生成components.d.ts 全局定义文件
|
||||||
resolvers: [
|
resolvers: [
|
||||||
AntDesignVueResolver({ //对使用到的全局ant design vue组件进行类型导入
|
AntDesignVueResolver({
|
||||||
importStyle: false, // 不动态引入css,这个不强求
|
//对使用到的全局ant design vue组件进行类型导入
|
||||||
|
importStyle: false, // 不动态引入css,这个不强求
|
||||||
}),
|
}),
|
||||||
// 自动导入 lucide 图标
|
// 自动导入 lucide 图标
|
||||||
IconsResolver({
|
IconsResolver({
|
||||||
prefix: 'i', // 比如用 <i-a-arrow-down />
|
prefix: "i", // 比如用 <i-a-arrow-down />
|
||||||
enabledCollections: ['lucide']
|
enabledCollections: ["lucide"],
|
||||||
})
|
}),
|
||||||
],
|
],
|
||||||
include: [/\.vue$/, /\.vue\?vue/, /\.md$/, /\.tsx$/], //包含的文件类型
|
include: [/\.vue$/, /\.vue\?vue/, /\.md$/, /\.tsx$/], //包含的文件类型
|
||||||
}),
|
}),
|
||||||
@@ -28,18 +47,4 @@ export default defineConfig({
|
|||||||
autoInstall: true, // 没安装的图标库会自动下载
|
autoInstall: true, // 没安装的图标库会自动下载
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
resolve: {
|
});
|
||||||
alias: {
|
|
||||||
'@': path.resolve(__dirname, 'src'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
proxy: {
|
|
||||||
'/api': {
|
|
||||||
target: 'http://192.168.1.38:18081',
|
|
||||||
changeOrigin: true,
|
|
||||||
rewrite: path => path.replace(/^\/api/, '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|||||||
Reference in New Issue
Block a user