| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- <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>
|