Files
frontend_hmi/src/views/index.vue
2025-09-22 17:45:53 +08:00

975 lines
27 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, reactive, nextTick } from 'vue';
import { useRealTime } from '@/utils/dateUtils';
import { checkOrderNumberApi, addProcessInfoApi } from '@/api/detect';
import type { Rule } from 'ant-design-vue/es/form';
// 检测设备表单规则
const rules: Record<string, Rule[]> = {
workOrderCode: [{ required: true, message: '请输入工单号', trigger: 'change' }],
productCode: [{ required: true, message: '请输入产品编码', trigger: 'change' }],
employeeCode: [{ required: true, message: '请输入员工号', trigger: 'change' }],
processName: [{ required: true, message: '请输入工序名称', trigger: 'change' }],
resourceName: [{ required: true, message: '请输入资源名称', trigger: 'change' }],
equipmentCode: [{ required: true, message: '请输入设备编码', trigger: 'change' }],
fixtureCode: [{ required: true, message: '请输入治具编码', trigger: 'change' }],
};
// 包装设备表单规则
const packageRules: Record<string, Rule[]> = {
customerSelection: [{ required: true, message: '请选择客户', trigger: 'change' }],
productModel: [{ required: true, message: '请输入产品型号', trigger: 'change' }],
employeeCode: [{ required: true, message: '请输入员工号', trigger: 'change' }],
processName: [{ required: true, message: '请输入工序名称', trigger: 'change' }],
resourceName: [{ required: true, message: '请输入资源名称', trigger: 'change' }],
equipmentCode: [{ required: true, message: '请输入设备编码', trigger: 'change' }],
fixtureCode: [{ required: true, message: '请输入治具编码', trigger: 'change' }],
packingResult: [{ required: true, message: '请选择装箱结果', trigger: 'change' }],
};
// 实时时间
const { currentTime } = useRealTime('HH:mm:ss');
const currentDate = ref('');
// 可编辑表单状态管理
const isDetectingEditMode = ref(false);
const isPackageEditMode = ref(false);
// 初始副本存储
let detectFormBackup: any = null;
let packageFormBackup: any = null;
// 表单引用
const detectFormRef = ref();
const packageFormRef = ref();
// 执行结果日志
const executionLogs = ref([
'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([
'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 logsContainer = document.querySelector('.execution-logs-content');
if (logsContainer) {
logsContainer.scrollTop = logsContainer.scrollHeight;
}
};
// 底部操作按钮配置
const actionButtons = ref([
{ label: '工序过站', handler: 'handleProcessPass', type: 'primary' as const, status: 'idle' as const },
{ label: '复检序号检查', handler: 'handleRecheckSequence', type: 'default' as const, status: 'idle' as const },
{ label: '扫码', handler: 'handleScanCode', type: 'default' as const, status: 'idle' as const },
{ label: '序号检查', handler: 'handleSequenceCheck', type: 'default' as const, status: 'idle' as const },
{ label: '包装过站', handler: 'handlePackagePass', type: 'primary' as const, status: 'idle' as const }
]);
// 执行按钮操作
const executeButtonAction = (handlerName: string) => {
const handlers: { [key: string]: () => void } = {
handleOrderCheck,
handleProcessPass,
handleRecheckSequence,
handleSequenceCheck,
handlePackagePass
};
const handler = handlers[handlerName];
if (handler) {
handler();
}
};
// 日志记录工具函数
const addDetectionLog = (message: string) => {
const timestamp = new Date().toLocaleTimeString('zh-CN', { hour12: false });
const logEntry = `${timestamp} - ${message}`;
executionLogs.value.push(logEntry);
// 自动滚动到底部
nextTick(() => {
scrollToExecutionBottom();
});
};
const addPackageLog = (message: string) => {
const timestamp = new Date().toLocaleTimeString('zh-CN', { hour12: false });
const logEntry = `${timestamp} - ${message}`;
packageLogs.value.push(logEntry);
// 自动滚动到底部
nextTick(() => {
const logContainers = document.querySelectorAll('.log-container');
logContainers.forEach(container => {
container.scrollTop = container.scrollHeight;
});
});
};
// 清空检测设备执行日志
const clearExecutionLogs = () => {
executionLogs.value = [];
};
// 清空自动包装执行日志
const clearPackageLogs = () => {
packageLogs.value = [];
};
// 单号检查
const handleOrderCheck = () => {
checkOrderNumberApi({
workOrderCode: detectForm.workOrderCode,
productCode: detectForm.productCode
}).then(res => {
if (res) {
addDetectionLog('单号检查成功');
} else {
addDetectionLog('单号检查失败');
}
})
addDetectionLog('开始执行单号检查操作');
console.log('单号检查');
};
// 工序过站
const handleProcessPass = () => {
addDetectionLog('开始执行工序过站操作');
console.log('工序过站');
};
// 复检序号检查
const handleRecheckSequence = () => {
addPackageLog('开始执行复检序号检查操作');
console.log('复检序号检查');
};
// 序号检查
const handleSequenceCheck = () => {
addPackageLog('开始执行序号检查操作');
console.log('序号检查');
};
// 包装过站
const handlePackagePass = () => {
addPackageLog('开始执行包装过站操作');
console.log('包装过站');
};
// SSE事件处理函数
const handleL1Event = (data: any) => {
// L1_EVENT放到自动包装日志区
addPackageLog(`L1事件: ${JSON.stringify(data)}`);
};
const handleL4Event = (data: any) => {
// L4_EVENT放到检测设备日志区
addDetectionLog(`L4事件: ${JSON.stringify(data)}`);
if(data.code === 201) {
detectForm.confirmSequence = data.data
}
};
const handleMESEvent = (data: any) => {
// MES_EVENT放到检测设备日志区
addDetectionLog(`MES事件: ${JSON.stringify(data)}`);
};
const handleSseMessage = (data: string) => {
// 处理SSE原始消息如果需要的话
console.log('收到SSE消息:', data);
};
// Status handlers are now managed by individual modal components
// 检测设备表单数据
const detectForm = reactive({
workOrderCode: 'SKT202507220001',
productCode: 'JH1008611',
employeeCode: 'ZDXTEST',
processName: 'T-自动组装测试',
resourceName: 'T-A自动组装测试',
equipmentCode: 'JH.02.101.13-219',
fixtureCode: 'JH0001',
confirmSequence: '',
detectionData: '',
sequenceCount: 1
});
// 包装设备表单数据
const packageForm = reactive({
customerSelection: '上海电子科技有限公司',
productModel: 'A538-09-高精度传感器',
employeeCode: 'OP-7853',
processName: '自动包装',
resourceName: '包装台2号',
equipmentCode: 'EQ-PK-002',
fixtureCode: 'FX-PK-002-B',
packingResult: '正常',
sequenceNumber: 'SN-A538-09-2023-00018',
passStationCount: 18,
fullBoxCount: 25,
passStationSequence: 'SN-A538-09-2023-00018'
});
// 编辑模式切换
const toggleDetectingEditMode = () => {
if (!isDetectingEditMode.value) {
// 进入编辑模式,保存初始副本
detectFormBackup = JSON.parse(JSON.stringify(detectForm));
}
isDetectingEditMode.value = !isDetectingEditMode.value;
};
const togglePackageEditMode = () => {
if (!isPackageEditMode.value) {
// 进入编辑模式,保存初始副本
packageFormBackup = JSON.parse(JSON.stringify(packageForm));
}
isPackageEditMode.value = !isPackageEditMode.value;
};
// 保存检测设备编辑
const saveDetectingEdit = () => {
detectFormRef.value.validate().then(() => {
console.log('保存检测设备数据:', detectForm);
isDetectingEditMode.value = false;
// 保存成功,清除备份
detectFormBackup = null;
addProcessInfoApi({
workOrderCode: detectForm.workOrderCode,
productCode: detectForm.productCode,
employeeCode: detectForm.employeeCode,
processName: detectForm.processName,
resourceName: detectForm.resourceName,
equipmentCode: detectForm.equipmentCode,
fixtureCode: detectForm.fixtureCode
}).then(res => {
console.log(res)
})
}).catch(() => {
console.log('检测设备表单验证失败');
});
};
// 保存包装设备编辑
const savePackageEdit = () => {
packageFormRef.value.validate().then(() => {
console.log('保存包装设备数据:', packageForm);
isPackageEditMode.value = false;
// 保存成功,清除备份
packageFormBackup = null;
}).catch(() => {
console.log('包装设备表单验证失败');
});
};
// 取消检测设备编辑
const cancelDetectingEdit = () => {
isDetectingEditMode.value = false;
if (detectFormBackup) {
// 恢复到初始副本
Object.assign(detectForm, detectFormBackup);
detectFormBackup = null;
}
// 清除表单验证状态
detectFormRef.value?.clearValidate();
};
// 取消包装设备编辑
const cancelPackageEdit = () => {
isPackageEditMode.value = false;
if (packageFormBackup) {
// 恢复到初始副本
Object.assign(packageForm, packageFormBackup);
packageFormBackup = null;
}
// 清除表单验证状态
packageFormRef.value?.clearValidate();
};
// 初始化
onMounted(() => {
// 设置当前日期
const now = new Date();
currentDate.value = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`;
// SSE连接逻辑已迁移到SseStatus组件中
});
// 清理事件监听
onBeforeUnmount(() => {
// SSE断开连接逻辑已迁移到SseStatus组件中
});
</script>
<template>
<div class="hmi-container">
<!-- 顶部状态栏 -->
<div class="header-status">
<div class="left-info">
<span class="app-title">
<i-lucide-cpu class="app-icon" /> 工业控制系统 HMI
</span>
</div>
<div class="center-status">
<!-- MES状态 -->
<MesStatus />
<!-- 网络通讯状态 -->
<NetworkStatus />
<!-- PLC通讯状态 -->
<PlcStatus />
<!-- 摄像头状态 -->
<CameraStatus />
<!-- SSE 日志 -->
<SseStatus
:on-l1-event="handleL1Event"
:on-l4-event="handleL4Event"
:on-mes-event="handleMESEvent"
:on-sse-message="handleSseMessage"
/>
</div>
<SettingsModal />
<!-- <div class="right-info" @click="showSettings">
<span class="time-info">{{ currentTime }}</span>
<span class="date-info">{{ currentDate }}</span>
</div> -->
</div>
<!-- 主要内容区域 -->
<div class="main-content">
<!-- 检测设备区域 -->
<div class="device-section detecting-section">
<div class="section-header">
<h3 class="section-title">
<i-lucide-monitor class="title-icon" />
检测设备
</h3>
<div class="edit-controls" v-if="!isDetectingEditMode">
<a-button size="small" @click="toggleDetectingEditMode" class="edit-btn">
<i-lucide-edit class="btn-icon" />
编辑
</a-button>
</div>
<div class="edit-controls" v-else>
<a-button size="small" type="primary" @click="saveDetectingEdit" class="save-btn">
<i-lucide-save class="btn-icon" />
保存
</a-button>
<a-button size="small" @click="cancelDetectingEdit" class="cancel-btn">
<i-lucide-x class="btn-icon" />
取消
</a-button>
</div>
</div>
<a-form :model="detectForm" :rules="rules" class="device-info" ref="detectFormRef" :colon="false"
hideRequiredMark :labelCol="{ span: 4 }" :wrapperCol="{ span: 20 }">
<a-row :gutter="32">
<a-col :span="12">
<a-form-item label="工单号" name="workOrderCode">
<a-input-group compact>
<a-input v-model:value="detectForm.workOrderCode" class="edit-input"
:disabled="!isDetectingEditMode" />
<a-button type="primary" @click="handleOrderCheck">单号检查</a-button>
</a-input-group>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="产品编码" name="productCode">
<a-input v-model:value="detectForm.productCode" class="edit-input"
:disabled="!isDetectingEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="员工工号" name="employeeCode">
<a-input v-model:value="detectForm.employeeCode" class="edit-input"
:disabled="!isDetectingEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="工序名称" name="processName">
<a-input v-model:value="detectForm.processName" class="edit-input"
:disabled="!isDetectingEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="资源名称" name="resourceName">
<a-input v-model:value="detectForm.resourceName" class="edit-input"
:disabled="!isDetectingEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="设备编码" name="equipmentCode">
<a-input v-model:value="detectForm.equipmentCode" class="edit-input"
:disabled="!isDetectingEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="治具编码" name="fixtureCode">
<a-input v-model:value="detectForm.fixtureCode" class="edit-input"
:disabled="!isDetectingEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="序号数量">
<a-input v-model:value="detectForm.sequenceCount" class="edit-input" disabled />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="确认序号" name="confirmSequence" :labelCol="{ span: 2 }" :wrapperCol="{ span: 22 }">
<a-input-group compact>
<a-input v-model:value="detectForm.confirmSequence" class="edit-input" disabled />
<a-button type="primary" @click="handleSequenceCheck">序号检查</a-button>
<a-button type="primary" @click="handleRecheckSequence" style="border-left: 1px solid #8395B6;">复检序号检查</a-button>
</a-input-group>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="检测数据" name="fixtureCode" :labelCol="{ span: 2 }" :wrapperCol="{ span: 22 }">
<a-input v-model:value="detectForm.detectionData" class="edit-input"
disabled />
</a-form-item>
</a-col>
</a-row>
</a-form>
<ExecutionResult title="执行结果" :logs="executionLogs" @clear="clearExecutionLogs" />
</div>
<!-- 自动包装区域 -->
<div class="device-section package-section">
<div class="section-header">
<h3 class="section-title">
<i-lucide-package class="title-icon" />
自动包装
</h3>
<div class="edit-controls" v-if="!isPackageEditMode">
<a-button size="small" @click="togglePackageEditMode" class="edit-btn">
<i-lucide-square-pen class="btn-icon" />
编辑
</a-button>
</div>
<div class="edit-controls" v-else>
<a-button size="small" type="primary" @click="savePackageEdit" class="save-btn">
<i-lucide-save class="btn-icon" />
保存
</a-button>
<a-button size="small" @click="cancelPackageEdit" class="cancel-btn">
<i-lucide-x class="btn-icon" />
取消
</a-button>
</div>
</div>
<a-form :model="packageForm" :rules="packageRules" class="device-info" ref="packageFormRef" :colon="false"
hideRequiredMark :labelCol="{ span: 4 }" :wrapperCol="{ span: 20 }">
<a-row :gutter="32">
<a-col :span="12">
<a-form-item label="客户选择" name="customerSelection">
<a-input v-model:value="packageForm.customerSelection" class="edit-input"
:disabled="!isPackageEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="产品型号" name="productModel">
<a-input v-model:value="packageForm.productModel" class="edit-input"
:disabled="!isPackageEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="工号" name="employeeCode">
<a-input v-model:value="packageForm.employeeCode" class="edit-input"
:disabled="!isPackageEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="工序名称" name="processName">
<a-input v-model:value="packageForm.processName" class="edit-input"
:disabled="!isPackageEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="资源名称" name="resourceName">
<a-input v-model:value="packageForm.resourceName" class="edit-input"
:disabled="!isPackageEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="设备编码" name="equipmentCode">
<a-input v-model:value="packageForm.equipmentCode" class="edit-input"
:disabled="!isPackageEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="治具编码" name="fixtureCode">
<a-input v-model:value="packageForm.fixtureCode" class="edit-input"
:disabled="!isPackageEditMode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="装箱结果" name="packingResult">
<a-select v-model:value="packageForm.packingResult" class="edit-input"
:disabled="!isPackageEditMode">
<a-select-option value="正常">正常</a-select-option>
<a-select-option value="异常">异常</a-select-option>
<a-select-option value="待检">待检</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="序号" name="fixtureCode">
<a-input v-model:value="packageForm.sequenceNumber" class="edit-input" disabled />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="过站数量" name="fixtureCode">
<a-input v-model:value="packageForm.passStationCount" class="edit-input" disabled />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="满箱数量" name="fixtureCode">
<a-input v-model:value="packageForm.fullBoxCount" class="edit-input" disabled />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="过站序号" name="fixtureCode">
<a-input v-model:value="packageForm.passStationSequence" class="edit-input" disabled />
</a-form-item>
</a-col>
</a-row>
</a-form>
<ExecutionResult title="执行结果" :logs="packageLogs" @clear="clearPackageLogs" />
</div>
</div>
<!-- 底部操作按钮区域 -->
<!-- <ActionButtons :buttons="actionButtons" @execute="executeButtonAction" /> -->
</div>
</template>
<style scoped lang="scss">
@import '@/assets/styles/_variables.scss';
.hmi-container {
width: 100vw;
height: 100vh;
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
color: $white;
font-family: $font-family;
display: flex;
flex-direction: column;
overflow: hidden;
font-size: clamp(14px, 1.4vw, 18px);
/* 响应式字体大小 */
@media (max-width: 1024px) {
font-size: clamp(12px, 1.7vw, 16px);
}
@media (min-width: 1025px) and (max-width: 1366px) {
font-size: clamp(14px, 1.5vw, 17px);
}
@media (min-width: 1367px) {
font-size: clamp(16px, 1.3vw, 20px);
}
}
// 响应式字体大小的具体元素
@media (max-width: 1024px) {
.app-title {
font-size: clamp(16px, 2.8vw, 20px) !important;
}
.status-label,
.status-value {
font-size: clamp(12px, 1.4vw, 14px) !important;
}
.section-header h3 {
font-size: clamp(16px, 2.0vw, 18px) !important;
}
.info-item .label,
.info-item .value {
font-size: clamp(12px, 1.4vw, 14px) !important;
}
.action-button {
font-size: clamp(12px, 1.4vw, 14px) !important;
}
}
@media (min-width: 1025px) and (max-width: 1366px) {
.app-title {
font-size: clamp(18px, 2.4vw, 20px) !important;
}
.status-label,
.status-value {
font-size: clamp(13px, 1.3vw, 15px) !important;
}
.section-header h3 {
font-size: clamp(17px, 1.8vw, 19px) !important;
}
.info-item .label,
.info-item .value {
font-size: clamp(13px, 1.3vw, 15px) !important;
}
.action-button {
font-size: clamp(14px, 1.3vw, 16px) !important;
}
}
@media (min-width: 1367px) {
.app-title {
font-size: clamp(20px, 2.0vw, 22px) !important;
}
.status-label,
.status-value {
font-size: clamp(14px, 1.2vw, 16px) !important;
}
.section-header h3 {
font-size: clamp(18px, 1.6vw, 20px) !important;
}
.info-item .label,
.info-item .value {
font-size: clamp(14px, 1.2vw, 16px) !important;
}
.action-button {
font-size: clamp(15px, 1.2vw, 17px) !important;
}
}
/* 顶部状态栏 */
.header-status {
height: 50px;
background: $bg-dark;
border-bottom: 2px solid $primary-color;
@include flex-between;
padding: 0 $spacing-lg;
flex-shrink: 0;
.left-info {
.app-title {
font-size: 18px;
font-weight: bold;
color: $white;
}
}
.center-status {
display: flex;
gap: $spacing-xxl;
align-items: center;
}
.status-button {
padding: $spacing-sm $spacing-md;
@include button-base;
@include button-hover($bg-overlay, rgba(255, 255, 255, 0.2), $white);
}
}
/* 主要内容区域 */
.main-content {
flex: 1;
display: flex;
gap: $spacing-lg;
padding: $spacing-lg;
overflow: hidden;
}
.device-section {
flex: 1;
background: $bg-overlay;
border: 2px solid $primary-color;
border-radius: $border-radius-lg;
padding: $spacing-lg;
display: flex;
flex-direction: column;
overflow: hidden;
}
.section-header {
margin-bottom: $spacing-md;
border-bottom: 1px solid $primary-color;
padding-bottom: 6px;
@include flex-between;
h3 {
margin: 0;
color: $white;
font-size: 18px;
font-weight: bold;
}
}
.section-title {
display: flex;
align-items: center;
gap: $spacing-sm;
margin: 0;
color: $white;
font-size: 18px;
font-weight: bold;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
.title-icon {
width: 20px;
height: 20px;
filter: drop-shadow(0 2px 4px rgba(74, 144, 226, 0.3));
}
.app-icon {
width: 18px;
height: 18px;
color: $primary-color;
margin-right: $spacing-sm;
}
.status-icon {
width: 14px;
height: 14px;
margin-right: 6px;
color: $text-light;
}
.btn-icon {
width: 12px;
height: 12px;
margin-right: $spacing-xs;
}
.rotate {
animation: rotation 2s infinite linear;
/* 添加旋转动画 */
}
@keyframes rotation {
from {
transform: rotate(0deg);
/* 从 0 度开始 */
}
to {
transform: rotate(360deg);
/* 旋转到 360 度 */
}
}
/* 编辑控制按钮 */
.edit-controls {
display: flex;
gap: $spacing-sm;
}
.edit-btn {
@include status-button($bg-primary, $bg-primary-hover, $primary-color, $primary-light, $text-light, $white);
}
.save-btn {
@include status-button($success-bg, $success-bg-hover, $success-color, $success-light, $text-success, $white);
}
.cancel-btn {
@include status-button($error-bg, $error-bg-hover, $error-color, $error-light, $text-error, $white);
}
/* 编辑输入框样式 */
.edit-input {
background: $bg-input !important;
border: $border-light !important;
color: $white !important;
width: 100%;
&.bn {
border: none !important;
}
&:focus {
background: $bg-input-focus !important;
border-color: #fff !important;
box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2) !important;
}
&.ant-input-disabled {
color: $text-light !important;
}
input {
background: transparent !important;
color: $white !important;
}
&.ant-select.ant-select-in-form-item {
border: none !important;
border-radius: 6px;
}
}
:deep(.ant-select.ant-select-disabled) {
.ant-select-selection-item {
color: $white;
}
.ant-select-selector {
border: $border-light !important;
}
.ant-select-arrow {
color: #bdbdbd;
}
}
.device-info {
flex-shrink: 0;
margin-bottom: $spacing-xl;
:deep(.ant-form-item-label > label) {
color: $text-light;
font-size: 16px;
}
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 5px;
min-height: 20px;
.value {
color: $white;
font-size: 14px;
font-weight: 500;
&.success {
color: $success-color;
}
}
}
/* SSE日志对话框样式 */
.sse-logs-dialog {
:deep(.ant-modal-content) {
background: rgba(30, 30, 45, 0.95);
border: 1px solid $primary-color;
}
.sse-controls {
display: flex;
gap: $spacing-sm;
margin-bottom: $spacing-md;
.sse-control-btn {
display: flex;
align-items: center;
.btn-icon {
margin-right: 4px;
}
}
}
}
/* 响应式设计 */
@media (max-width: 1600px) {
.main-content {
gap: $spacing-lg;
padding: $spacing-lg;
}
.device-section {
padding: $spacing-lg;
}
.info-item {
.label {
min-width: 70px;
font-size: 13px;
}
.value {
font-size: 13px;
}
}
}
@media (max-width: 1366px) {
.center-status {
gap: $spacing-xl;
}
.status-label,
.status-value {
font-size: 13px;
}
.main-content {
gap: 10px;
padding: 10px;
}
.device-section {
padding: $spacing-md;
}
}
@media (max-width: 1024px) {
.main-content {
flex-direction: column;
gap: 10px;
}
.device-section {
flex: 1;
height: calc(50vh - 100px);
}
}
/* Dialog样式已迁移到各个子组件中 */
:deep(.ant-input-group.ant-input-group-compact) {
display: flex;
.ant-btn[disabled] {
border-color: #8396B7;
color: #b4b4b4;
}
}
</style>