From 60d0235013e4df2fa18a4027bff6b2b8aa10594c Mon Sep 17 00:00:00 2001 From: suixy <2277317060@qq.com> Date: Mon, 15 Jun 2026 15:06:13 +0800 Subject: [PATCH] init --- .gitignore | 30 ++ index.html | 12 + package.json | 21 + src/App.vue | 3 + src/main.js | 17 + src/router/index.js | 21 + src/style.css | 243 ++++++++++++ src/view/blocked-data/index.vue | 83 ++++ src/view/config/index.vue | 108 +++++ src/view/history-data/index.vue | 91 +++++ src/view/login/index.vue | 238 +++++++++++ src/view/map/index.vue | 682 ++++++++++++++++++++++++++++++++ src/view/serve/index.vue | 0 src/view/video/index.vue | 206 ++++++++++ vite.config.js | 10 + 15 files changed, 1765 insertions(+) create mode 100644 .gitignore create mode 100644 index.html create mode 100644 package.json create mode 100644 src/App.vue create mode 100644 src/main.js create mode 100644 src/router/index.js create mode 100644 src/style.css create mode 100644 src/view/blocked-data/index.vue create mode 100644 src/view/config/index.vue create mode 100644 src/view/history-data/index.vue create mode 100644 src/view/login/index.vue create mode 100644 src/view/map/index.vue create mode 100644 src/view/serve/index.vue create mode 100644 src/view/video/index.vue create mode 100644 vite.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d59a54 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +.DS_Store +.history +node_modules/ +dist/ +release/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +**/*.log + +tests/**/coverage/ +tests/e2e/reports +selenium-debug.log + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.local + +package-lock.json +yarn.lock +pnpm-lock.yaml + +# 编译生成的文件 +auto-imports.d.ts +components.d.ts diff --git a/index.html b/index.html new file mode 100644 index 0000000..9849ba8 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + 塔架 FOD + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..01aca3c --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "tower-fod", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --host 0.0.0.0", + "build": "vite build", + "preview": "vite preview --host 0.0.0.0" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "element-plus": "^2.11.8", + "vue": "^3.5.24", + "vue-router": "^4.6.4" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.2", + "vite": "^7.2.6" + } +} diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..98240ae --- /dev/null +++ b/src/App.vue @@ -0,0 +1,3 @@ + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..03f373a --- /dev/null +++ b/src/main.js @@ -0,0 +1,17 @@ +import { createApp } from 'vue' +import ElementPlus from 'element-plus' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' +import 'element-plus/dist/index.css' +import './style.css' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} + +app.use(ElementPlus) +app.use(router) +app.mount('#app') diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..2d7eee2 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,21 @@ +import { createRouter, createWebHistory } from 'vue-router' +import LoginView from '../view/login/index.vue' +import MapView from '../view/map/index.vue' + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { + path: '/login', + name: 'login', + component: LoginView, + }, + { + path: '/', + name: 'map', + component: MapView, + }, + ], +}) + +export default router diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..4625497 --- /dev/null +++ b/src/style.css @@ -0,0 +1,243 @@ +:root { + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + sans-serif; + color: #eef5ff; + background: #030712; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-width: 320px; + min-height: 100vh; + overflow: hidden; +} + +#app { + min-height: 100vh; +} + +.monitor-page { + position: relative; + width: 100vw; + height: 100vh; + overflow: hidden; + background: + radial-gradient(circle at 18% 12%, rgba(45, 212, 191, 0.18), transparent 32%), + linear-gradient(135deg, #020617 0%, #111827 52%, #07111f 100%); +} + +.stream-video { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + background: #020617; +} + +.video-backdrop { + position: absolute; + inset: 0; + pointer-events: none; + background: + linear-gradient(90deg, rgba(148, 163, 184, 0.08) 1px, transparent 1px), + linear-gradient(0deg, rgba(148, 163, 184, 0.08) 1px, transparent 1px); + background-size: 56px 56px; + mix-blend-mode: screen; +} + +.video-backdrop::after { + position: absolute; + inset: 0; + content: ""; + background: linear-gradient(180deg, rgba(2, 6, 23, 0.28), transparent 34%, rgba(2, 6, 23, 0.52)); +} + +.scan-line { + position: absolute; + top: -12%; + left: 0; + width: 100%; + height: 16%; + background: linear-gradient(180deg, transparent, rgba(34, 211, 238, 0.16), transparent); + animation: scan-move 5.8s linear infinite; +} + +.signal-grid { + position: absolute; + inset: 24px; + border: 1px solid rgba(125, 211, 252, 0.24); + box-shadow: inset 0 0 44px rgba(8, 145, 178, 0.12); +} + +.stream-status { + position: absolute; + left: 24px; + bottom: 24px; + z-index: 2; + display: flex; + gap: 10px; + align-items: center; + max-width: calc(100vw - 48px); + min-height: 38px; + padding: 0 14px; + border: 1px solid rgba(148, 163, 184, 0.24); + border-radius: 8px; + color: #dbeafe; + background: rgba(2, 6, 23, 0.62); + backdrop-filter: blur(14px); +} + +.stream-status strong { + overflow: hidden; + color: #93c5fd; + font-size: 12px; + font-weight: 600; + text-overflow: ellipsis; + white-space: nowrap; +} + +.status-dot { + width: 8px; + height: 8px; + flex: 0 0 auto; + border-radius: 999px; + background: #f59e0b; + box-shadow: 0 0 14px rgba(245, 158, 11, 0.85); +} + +.status-dot.online { + background: #22c55e; + box-shadow: 0 0 14px rgba(34, 197, 94, 0.9); +} + +.control-panel { + position: absolute; + top: 24px; + right: 24px; + z-index: 3; + width: 236px; + padding: 14px; + border: 1px solid rgba(186, 230, 253, 0.28); + border-radius: 8px; + background: rgba(3, 7, 18, 0.66); + box-shadow: 0 18px 60px rgba(0, 0, 0, 0.34); + backdrop-filter: blur(18px); +} + +.direction-pad { + display: grid; + grid-template-areas: + ". up ." + "left center right" + ". down ."; + grid-template-columns: repeat(3, 48px); + grid-template-rows: repeat(3, 42px); + justify-content: center; + gap: 8px; +} + +.control-btn, +.zoom-btn { + width: 100%; + height: 100%; + margin: 0 !important; + border-color: rgba(147, 197, 253, 0.34); + border-radius: 8px; + color: #eff6ff; + background: rgba(15, 23, 42, 0.74); +} + +.control-btn:hover, +.zoom-btn:hover, +.function-btn:hover { + border-color: rgba(34, 211, 238, 0.86); + color: #ffffff; + background: rgba(8, 145, 178, 0.76); +} + +.control-btn.up { + grid-area: up; +} + +.control-btn.left { + grid-area: left; +} + +.control-btn.center { + grid-area: center; +} + +.control-btn.right { + grid-area: right; +} + +.control-btn.down { + grid-area: down; +} + +.zoom-controls { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + height: 40px; + margin-top: 12px; +} + +.function-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px; + margin-top: 12px; +} + +.function-btn { + min-width: 0; + height: 36px; + margin: 0 !important; + border-color: rgba(148, 163, 184, 0.24); + border-radius: 8px; + color: #dbeafe; + background: rgba(15, 23, 42, 0.7); +} + +@keyframes scan-move { + from { + transform: translateY(0); + } + + to { + transform: translateY(760%); + } +} + +@media (max-width: 680px) { + .control-panel { + top: 12px; + right: 12px; + width: 212px; + padding: 12px; + } + + .direction-pad { + grid-template-columns: repeat(3, 42px); + grid-template-rows: repeat(3, 38px); + gap: 7px; + } + + .stream-status { + left: 12px; + right: 12px; + bottom: 12px; + max-width: none; + } +} diff --git a/src/view/blocked-data/index.vue b/src/view/blocked-data/index.vue new file mode 100644 index 0000000..2b4dbca --- /dev/null +++ b/src/view/blocked-data/index.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/view/config/index.vue b/src/view/config/index.vue new file mode 100644 index 0000000..0cd77e1 --- /dev/null +++ b/src/view/config/index.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/src/view/history-data/index.vue b/src/view/history-data/index.vue new file mode 100644 index 0000000..9007f5d --- /dev/null +++ b/src/view/history-data/index.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/view/login/index.vue b/src/view/login/index.vue new file mode 100644 index 0000000..a8e9cd5 --- /dev/null +++ b/src/view/login/index.vue @@ -0,0 +1,238 @@ + + + + + diff --git a/src/view/map/index.vue b/src/view/map/index.vue new file mode 100644 index 0000000..e5dddf9 --- /dev/null +++ b/src/view/map/index.vue @@ -0,0 +1,682 @@ + + + + + diff --git a/src/view/serve/index.vue b/src/view/serve/index.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/view/video/index.vue b/src/view/video/index.vue new file mode 100644 index 0000000..2f6ee34 --- /dev/null +++ b/src/view/video/index.vue @@ -0,0 +1,206 @@ + + + diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..6db2aa6 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + plugins: [vue()], + server: { + host: '0.0.0.0', + port: 5173, + }, +})