Zimo 5 روز پیش
والد
کامیت
9dba20a2b3
2فایلهای تغییر یافته به همراه651 افزوده شده و 0 حذف شده
  1. 477 0
      src/views/oli-connection/monitoring-board/1.vue
  2. 174 0
      src/views/oli-connection/monitoring-board/index.vue

+ 477 - 0
src/views/oli-connection/monitoring-board/1.vue

@@ -0,0 +1,477 @@
+<script setup lang="ts">
+import { reactive, ref } from 'vue'
+import { Search, RefreshLeft, Cpu, Aim } from '@element-plus/icons-vue'
+
+// --- 表单数据模型 ---
+const queryForm = reactive({
+  orgNode: [], // 级联选择结果
+  deviceCode: '',
+  deviceName: '',
+  deviceStatus: '',
+  selectedDevices: [], // 设备多选结果
+  timeRange: []
+})
+
+// --- 模拟数据 (与之前相同) ---
+const orgOptions = [
+  { value: 'factory-1', label: '第一工厂', children: [{ value: 'workshop-a', label: '总装车间' }] },
+  { value: 'factory-2', label: '第二工厂' }
+]
+
+const statusOptions = [
+  { label: '运行中 (RUNNING)', value: 'running', color: '#00f2ea' }, // 青色
+  { label: '故障 (ERROR)', value: 'error', color: '#ff0055' }, // 玫红
+  { label: '待机 (IDLE)', value: 'stopped', color: '#f59e0b' } // 橙色
+]
+
+const deviceOptions = ref([
+  { label: '[CNC-001] 数控机床核心单元', value: 'cnc-001' },
+  { label: '[ROBOT-A] 焊接机械臂一号', value: 'robot-a' },
+  { label: '[AGV-102] 智能物流载具', value: 'agv-102' }
+])
+
+// --- 级联配置 ---
+const cascaderProps = { checkStrictly: true, expandTrigger: 'hover' as const }
+
+// --- 事件处理 ---
+const handleQueryConditionChange = () => {
+  console.log('>> 系统提示: 前置条件变更,正在重新计算目标设备列表...')
+  // 模拟 API 调用延迟和数据更新动画效果
+  const originalOptions = [...deviceOptions.value]
+  deviceOptions.value = []
+  setTimeout(() => {
+    deviceOptions.value = originalOptions
+    console.log('>> 系统提示: 设备列表更新完毕。')
+  }, 500)
+}
+
+const handleSearch = () => {
+  console.log('执行指令: 检索数据', queryForm)
+}
+const handleReset = () => {
+  queryForm.orgNode = []
+  queryForm.deviceCode = ''
+  queryForm.deviceName = ''
+  queryForm.deviceStatus = ''
+  queryForm.selectedDevices = []
+  queryForm.timeRange = []
+}
+</script>
+
+<template>
+  <div class="cyber-bg min-h-[400px] w-full p-6 flex flex-col gap-6 relative overflow-hidden">
+    <div
+      class="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDQwIDQwIiBvcGFjaXR5PSIwLjEiPjxwYXRoIGQ9Ik0wIDBoNDB2NDBIMHoiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwZjJlYSIgc3Ryb2tlLXdpZHRoPSIwLjUiLz48L3N2Zz4=')] opacity-20 pointer-events-none"
+    ></div>
+
+    <div class="cyber-panel relative p-5 rounded-sm backdrop-blur-xl border border-[#00f2ea]/30">
+      <div class="tech-corner top-left"></div>
+      <div class="tech-corner top-right"></div>
+      <div class="tech-corner bottom-left"></div>
+      <div class="tech-corner bottom-right"></div>
+
+      <div class="flex items-center justify-between mb-6 border-b border-[#00f2ea]/20 pb-3">
+        <div class="flex items-center gap-3">
+          <div class="p-2 bg-[#00f2ea]/10 rounded-sm border border-[#00f2ea]/50">
+            <el-icon class="text-[#00f2ea] text-xl animate-pulse"><Cpu /></el-icon>
+          </div>
+          <h2
+            class="text-xl font-oxanium text-transparent bg-clip-text bg-gradient-to-r from-[#00f2ea] to-[#bd00ff] tracking-wider font-bold uppercase u-text-glow"
+          >
+            设备数据检索终端 // DATA RETRIEVAL TERMINAL
+          </h2>
+        </div>
+        <div class="flex items-center gap-2 text-xs text-[#00f2ea]/70 font-mono">
+          <span class="relative flex h-3 w-3">
+            <span
+              class="animate-ping absolute inline-flex h-full w-full rounded-full bg-[#00f2ea] opacity-75"
+            ></span>
+            <span class="relative inline-flex rounded-full h-3 w-3 bg-[#00f2ea]"></span>
+          </span>
+          SYSTEM STATUS: ONLINE
+        </div>
+      </div>
+
+      <el-form :inline="true" :model="queryForm" class="cyber-form flex flex-wrap gap-x-6 gap-y-4">
+        <div
+          class="w-full flex flex-wrap gap-4 items-end border-l-2 border-[#00f2ea]/30 pl-4 bg-gradient-to-r from-[#00f2ea]/5 to-transparent py-2"
+        >
+          <el-form-item label="节点层级 / NODE LEVEL">
+            <el-cascader
+              v-model="queryForm.orgNode"
+              :options="orgOptions"
+              :props="cascaderProps"
+              placeholder="SELECT LEVEL >"
+              clearable
+              class="cyber-input w-48"
+              :show-all-levels="false"
+              popper-class="cyber-popper"
+            />
+          </el-form-item>
+
+          <el-form-item label="设备编码 / CODE">
+            <el-input
+              v-model="queryForm.deviceCode"
+              placeholder="INPUT CODE >"
+              @change="handleQueryConditionChange"
+              class="cyber-input w-40"
+            >
+              <template #prefix
+                ><el-icon><Aim /></el-icon
+              ></template>
+            </el-input>
+          </el-form-item>
+
+          <el-form-item label="设备名称 / NAME">
+            <el-input
+              v-model="queryForm.deviceName"
+              placeholder="INPUT NAME >"
+              @change="handleQueryConditionChange"
+              class="cyber-input w-40"
+            />
+          </el-form-item>
+
+          <el-form-item label="运行状态 / STATUS">
+            <el-select
+              v-model="queryForm.deviceStatus"
+              placeholder="SELECT STATUS >"
+              clearable
+              @change="handleQueryConditionChange"
+              class="cyber-input w-44"
+              popper-class="cyber-popper"
+            >
+              <el-option
+                v-for="item in statusOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              >
+                <span class="flex items-center gap-2 font-mono text-sm">
+                  <span
+                    :style="{ backgroundColor: item.color, boxShadow: `0 0 8px ${item.color}` }"
+                    class="h-1.5 w-1.5 rounded-full inline-block"
+                  ></span>
+                  {{ item.label }}
+                </span>
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </div>
+
+        <div class="w-full flex flex-wrap gap-4 items-end mt-2 pl-4">
+          <el-form-item label="目标设备锁定 / TARGET DEVICES" class="flex-grow">
+            <el-select
+              v-model="queryForm.selectedDevices"
+              multiple
+              collapse-tags
+              collapse-tags-tooltip
+              placeholder="MULTI-SELECT DEVICES >"
+              class="cyber-input w-full md:w-[400px]"
+              popper-class="cyber-popper"
+            >
+              <el-option
+                v-for="item in deviceOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              >
+                <span class="font-mono">{{ item.label }}</span>
+              </el-option>
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="时间跨度 / TIME SPAN">
+            <el-date-picker
+              v-model="queryForm.timeRange"
+              type="datetimerange"
+              range-separator="TO"
+              start-placeholder="START TIME"
+              end-placeholder="END TIME"
+              class="cyber-date-picker !w-[380px]"
+              popper-class="cyber-popper"
+            />
+          </el-form-item>
+
+          <div class="ml-auto flex gap-3">
+            <el-button class="cyber-btn-primary" @click="handleSearch">
+              <el-icon class="mr-2"><Search /></el-icon> 初始化查询
+            </el-button>
+            <el-button class="cyber-btn-secondary" @click="handleReset">
+              <el-icon class="mr-2"><RefreshLeft /></el-icon> 重置条件
+            </el-button>
+          </div>
+        </div>
+      </el-form>
+    </div>
+
+    <div
+      class="flex-grow cyber-panel relative p-6 rounded-sm backdrop-blur-md border border-[#00f2ea]/20 min-h-[300px] flex items-center justify-center flex-col gap-4"
+    >
+      <div class="scan-line absolute inset-0 pointer-events-none z-0"></div>
+      <el-icon class="text-6xl text-[#00f2ea]/30"><Cpu /></el-icon>
+      <p class="text-[#00f2ea]/70 font-mono tracking-[0.2em] z-10"
+        >等待数据接入 // AWAITING DATA STREAM...</p
+      >
+    </div>
+  </div>
+</template>
+
+<style scoped>
+/* --- 引入科幻感字体 (可选,如果你的环境支持联网) --- */
+@import url('https://fonts.googleapis.com/css2?family=Oxanium:wght@400;700&family=Roboto+Mono:wght@400;500&display=swap');
+
+/* --- 自定义工具类 --- */
+.font-oxanium {
+  font-family: Oxanium, cursive, sans-serif;
+}
+
+.font-mono {
+  font-family: 'Roboto Mono', monospace;
+}
+
+.u-text-glow {
+  text-shadow: 0 0 10px rgb(0 242 234 / 50%);
+}
+
+/* --- 核心背景 --- */
+.cyber-bg {
+  color: #e0f2fe;
+  background: radial-gradient(circle at center top, #1a1a2e 0%, #050505 100%);
+}
+
+/* --- 面板样式 (HUD Container) --- */
+.cyber-panel {
+  background: rgb(10 10 20 / 70%);
+  box-shadow:
+    inset 0 0 30px rgb(0 242 234 / 5%),
+    0 0 10px rgb(0 0 0 / 50%);
+}
+
+/* --- 装饰性角落 (Tech Corners) --- */
+.tech-corner {
+  position: absolute;
+  z-index: 1;
+  width: 15px;
+  height: 15px;
+  border-color: rgb(0 242 234 / 60%);
+}
+
+.tech-corner.top-left {
+  top: -1px;
+  left: -1px;
+  border-top-width: 2px;
+  border-left-width: 2px;
+}
+
+.tech-corner.top-right {
+  top: -1px;
+  right: -1px;
+  border-top-width: 2px;
+  border-right-width: 2px;
+}
+
+.tech-corner.bottom-left {
+  bottom: -1px;
+  left: -1px;
+  border-bottom-width: 2px;
+  border-left-width: 2px;
+}
+
+.tech-corner.bottom-right {
+  right: -1px;
+  bottom: -1px;
+  border-right-width: 2px;
+  border-bottom-width: 2px;
+}
+
+/* =========================================
+   Element Plus 深度定制 (The Magic Happens Here)
+   ========================================= */
+
+/* 1. Form Label 定制 */
+:deep(.el-form-item__label) {
+  padding-bottom: 4px;
+  font-family: 'Roboto Mono', monospace;
+  font-size: 0.75rem; /* text-xs */
+  font-weight: bold;
+  letter-spacing: 0.05em;
+  color: rgb(0 242 234 / 70%) !important; /* 青色文字 */
+}
+
+/* 2. 输入框与选择器容器 (Wrapper) 定制 */
+:deep(.cyber-input .el-input__wrapper),
+:deep(.cyber-input .el-select__wrapper),
+:deep(.cyber-date-picker.el-input__wrapper) {
+  padding-top: 4px;
+  padding-bottom: 4px;
+  background-color: rgb(0 242 234 / 5%) !important; /* 极淡的青色背景 */
+  border: 1px solid rgb(0 242 234 / 20%); /* 基础边框 */
+  border-radius: 2px; /* 硬朗的圆角 */
+  box-shadow: none !important; /* 移除默认阴影 */
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+/* 悬停与聚焦状态:发光增强 */
+:deep(.cyber-input .el-input__wrapper:hover),
+:deep(.cyber-input .el-select__wrapper:hover),
+:deep(.cyber-input .el-input__wrapper.is-focus),
+:deep(.cyber-input .el-select__wrapper.is-focused) {
+  border-color: rgb(0 242 234 / 80%);
+  box-shadow:
+    0 0 15px rgb(0 242 234 / 30%),
+    inset 0 0 10px rgb(0 242 234 / 10%) !important;
+}
+
+/* 输入框内部文字 */
+:deep(.el-input__inner) {
+  font-family: 'Roboto Mono', monospace;
+  font-size: 0.9rem;
+  color: #fff !important;
+}
+
+:deep(.el-input__inner::placeholder) {
+  color: rgb(0 242 234 / 30%);
+}
+
+/* 图标颜色 */
+:deep(.el-input__prefix-inner .el-icon),
+:deep(.el-select__caret),
+:deep(.el-date-editor .el-range-separator) {
+  color: rgb(0 242 234 / 60%) !important;
+}
+
+/* 日期选择器文字 */
+:deep(.el-date-editor .el-range-input) {
+  font-family: 'Roboto Mono', monospace;
+  color: #fff !important;
+}
+
+/* Tag 标签定制 (用于多选和级联) */
+:deep(.el-tag.el-tag--info) {
+  color: #e0c0ff;
+  background-color: rgb(189 0 255 / 20%); /* 紫色背景 */
+  border-color: rgb(189 0 255 / 50%);
+  border-radius: 2px;
+}
+
+:deep(.el-tag .el-tag__close) {
+  color: #e0c0ff;
+}
+
+/* =========================================
+   按钮定制 (Cyber Buttons)
+   ========================================= */
+.cyber-btn-primary {
+  font-family: Oxanium, sans-serif;
+  font-weight: bold;
+  letter-spacing: 1px;
+  color: #000 !important;
+  background: linear-gradient(135deg, #00f2ea 0%, #00a8c6 100%) !important;
+  border: none !important;
+  transition: all 0.3s;
+  clip-path: polygon(10% 0, 100% 0, 100% 70%, 90% 100%, 0 100%, 0 30%); /* 斜切角造型 */
+}
+
+.cyber-btn-primary:hover {
+  filter: brightness(1.2);
+  transform: translateY(-1px);
+  box-shadow: 0 0 20px rgb(0 242 234 / 60%);
+}
+
+.cyber-btn-secondary {
+  font-family: Oxanium, sans-serif;
+  color: rgb(0 242 234 / 80%) !important;
+  background: transparent !important;
+  border: 1px solid rgb(0 242 234 / 50%) !important;
+  clip-path: polygon(0 0, 90% 0, 100% 30%, 100% 100%, 10% 100%, 0 70%);
+}
+
+.cyber-btn-secondary:hover {
+  color: #fff !important;
+  background: rgb(0 242 234 / 10%) !important;
+  border-color: #00f2ea !important;
+  box-shadow: inset 0 0 10px rgb(0 242 234 / 30%);
+}
+
+/* =========================================
+   下拉弹出层定制 (Global Styles needed for Poppers)
+   ========================================= */
+
+/* 注意:这部分通常需要放在全局样式文件中,或者去掉 scoped,
+   为了方便演示,我这里使用了特殊的处理方式。
+   在实际项目中,请确保这些样式能作用于 body 下的弹出层。
+*/
+</style>
+
+<style>
+@keyframes scan {
+  0% {
+    transform: translateY(-100%);
+  }
+
+  100% {
+    transform: translateY(100%);
+  }
+}
+
+.cyber-popper.el-popper {
+  background: rgb(10 10 25 / 95%) !important;
+  border: 1px solid rgb(0 242 234 / 30%) !important;
+  backdrop-filter: blur(10px);
+}
+
+.cyber-popper .el-popper__arrow::before {
+  background: rgb(10 10 25 / 95%) !important;
+  border: 1px solid rgb(0 242 234 / 30%) !important;
+}
+
+/* 下拉选项 Item */
+.cyber-popper .el-select-dropdown__item,
+.cyber-popper .el-cascader-node {
+  font-family: 'Roboto Mono', monospace;
+  color: #a0aec0 !important;
+}
+
+/* 选项悬停/选中状态 */
+.cyber-popper .el-select-dropdown__item.hover,
+.cyber-popper .el-select-dropdown__item.selected,
+.cyber-popper .el-cascader-node.is-active,
+.cyber-popper .el-cascader-node:hover {
+  font-weight: bold;
+  color: #00f2ea !important;
+  background: rgb(0 242 234 / 15%) !important;
+}
+
+/* 日期选择器面板特殊处理 */
+.cyber-popper .el-picker-panel {
+  color: #e0f2fe;
+  background: transparent !important;
+}
+
+.cyber-popper .el-date-table td.available:hover {
+  color: #00f2ea;
+}
+
+.cyber-popper .el-date-table td.today span {
+  font-weight: bold;
+  color: #00f2ea;
+}
+
+.cyber-popper .el-date-table td.current:not(.disabled) span {
+  color: #000;
+  background-color: #00f2ea;
+}
+
+.cyber-popper .el-date-range-picker__content.is-left {
+  border-right: 1px solid rgb(0 242 234 / 20%);
+}
+
+/* 扫描线动画 */
+.scan-line {
+  width: 100%;
+  height: 100%;
+  background: linear-gradient(to bottom, transparent, rgb(0 242 234 / 20%), transparent);
+  opacity: 0.3;
+  animation: scan 3s linear infinite;
+}
+</style>

+ 174 - 0
src/views/oli-connection/monitoring-board/index.vue

@@ -0,0 +1,174 @@
+<script setup lang="ts">
+const searchForm = reactive({
+  deviceName: '',
+  status: '',
+  dateRange: []
+})
+</script>
+
+<template>
+  <div
+    class="relative w-full rounded-lg bg-[#020408] overflow-hidden min-h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
+  >
+    <header
+      class="relative w-full h-14 flex items-center justify-center select-none bg-[#0b1121] border-b border-white/5 shadow-lg"
+    >
+      <div
+        class="absolute inset-0 opacity-20"
+        style="background-image: radial-gradient(circle at 50% 50%, #083344 0%, transparent 50%)"
+      >
+      </div>
+
+      <div class="absolute bottom-0 left-0 w-full h-[2px] bg-slate-800/50 overflow-hidden z-20">
+        <div
+          class="absolute top-0 bottom-0 w-[40%] bg-gradient-to-r from-transparent via-[#22d3ee] to-transparent shadow-[0_0_20px_#22d3ee] animate-scan-line"
+        ></div>
+      </div>
+
+      <div class="absolute left-6 top-1/2 -translate-y-1/2 flex items-center gap-1 opacity-80">
+        <div
+          class="w-1 h-4 bg-cyan-400 skew-x-[-12deg] shadow-[0_0_5px_rgba(34,211,238,0.8)]"
+        ></div>
+        <div class="w-1 h-3 bg-cyan-700 skew-x-[-12deg]"></div>
+        <div class="w-1 h-2 bg-cyan-900 skew-x-[-12deg]"></div>
+      </div>
+
+      <div
+        class="absolute right-6 top-1/2 -translate-y-1/2 flex items-center gap-1 opacity-80 flex-row-reverse"
+      >
+        <div class="w-1 h-4 bg-cyan-400 skew-x-[12deg] shadow-[0_0_5px_rgba(34,211,238,0.8)]"></div>
+        <div class="w-1 h-3 bg-cyan-700 skew-x-[12deg]"></div>
+        <div class="w-1 h-2 bg-cyan-900 skew-x-[12deg]"></div>
+      </div>
+
+      <h1 class="z-10 text-2xl font-bold tracking-[0.5em] uppercase">
+        <span
+          class="text-transparent bg-clip-text bg-gradient-to-b from-white via-cyan-100 to-cyan-500 drop-shadow-[0_0_10px_rgba(34,211,238,0.8)]"
+        >
+          监控看板
+        </span>
+      </h1>
+    </header>
+
+    <div class="p-4">
+      <el-form />
+    </div>
+
+    <!-- <div class="px-6 py-6">
+      <el-form :inline="true" :model="searchForm" class="search-container">
+        <div
+          class="absolute left-0 top-0 w-[2px] h-full bg-gradient-to-b from-transparent via-cyan-500 to-transparent"
+        ></div>
+
+        <div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-x-8 gap-y-4">
+          <el-form-item label="设备节点" class="custom-item">
+            <el-input v-model="searchForm.deviceName" placeholder="请输入设备编号" />
+          </el-form-item>
+
+          <el-form-item label="监控级别" class="custom-item">
+            <el-select v-model="searchForm.level" placeholder="请选择">
+              <el-option label="核心节点" value="1" />
+              <el-option label="普通节点" value="2" />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="记录时间" class="custom-item lg:col-span-2">
+            <el-date-picker
+              v-model="searchForm.date"
+              type="daterange"
+              range-separator="-"
+              start-placeholder="开始"
+              end-placeholder="结束"
+            />
+          </el-form-item>
+
+          <div class="lg:col-start-4 flex justify-end items-end gap-3 pb-[2px]">
+            <el-button type="primary" class="glow-button">执行查询</el-button>
+            <el-button class="reset-button">重置</el-button>
+          </div>
+        </div>
+      </el-form>
+    </div> -->
+  </div>
+</template>
+
+<style scoped>
+@keyframes scan-line {
+  0% {
+    left: -40%;
+    opacity: 0;
+  }
+
+  10% {
+    opacity: 1;
+  }
+
+  90% {
+    opacity: 1;
+  }
+
+  100% {
+    left: 100%;
+    opacity: 0;
+  }
+}
+
+.animate-scan-line {
+  animation: scan-line 3s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate;
+}
+
+.search-container {
+  position: relative;
+  padding: 24px;
+  background: rgb(16 24 45 / 80%); /* 稍微调亮的深蓝色 */
+  border: 1px solid rgb(34 211 238 / 15%); /* 明显的青色半透明边框 */
+  border-radius: 8px;
+  box-shadow:
+    0 8px 32px 0 rgb(0 0 0 / 80%),
+    inset 0 0 15px rgb(34 211 238 / 5%); /* 内部微光 */
+}
+
+/* 2. 标签颜色:提高白度 */
+:deep(.el-form-item__label) {
+  font-size: 13px;
+  letter-spacing: 0.5px;
+  color: #e2e8f0 !important;
+}
+
+/* 3. 输入框:让背景更深以产生“凹陷感”,边框在聚焦时发光 */
+:deep(.el-input__wrapper) {
+  background-color: #05080f !important;
+  box-shadow: 0 0 0 1px rgb(255 255 255 / 10%) inset !important;
+}
+
+:deep(.el-input__wrapper.is-focus) {
+  box-shadow:
+    0 0 0 1px #22d3ee inset,
+    0 0 8px rgb(34 211 238 / 40%) !important;
+}
+
+/* 4. 按钮样式:保持高对比度 */
+.glow-button {
+  font-weight: bold;
+  color: #020408 !important;
+  background: #22d3ee !important;
+  border: none !important;
+  box-shadow: 0 0 15px rgb(34 211 238 / 40%);
+}
+
+.glow-button:hover {
+  transform: translateY(-1px);
+  box-shadow: 0 0 25px rgb(34 211 238 / 60%);
+}
+
+.reset-button {
+  color: #94a3b8 !important;
+  background: transparent !important;
+  border: 1px solid rgb(255 255 255 / 20%) !important;
+}
+
+.reset-button:hover {
+  color: #22d3ee !important;
+  border-color: #22d3ee !important;
+}
+</style>