This commit is contained in:
MR-ZC 2025-03-04 16:18:46 +08:00
commit 45e39de2a6
46 changed files with 4657 additions and 0 deletions

1
.env.development Normal file
View File

@ -0,0 +1 @@
VITE_BASE_URL = "192.168.100.1"

1
.env.production Normal file
View File

@ -0,0 +1 @@
VITE_BASE_URL = "192.168.100.1"

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

3
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

33
README.md Normal file
View File

@ -0,0 +1,33 @@
# zx_web
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
## Customize configuration
See [Vite Configuration Reference](https://vite.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```

7
env.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

13
index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

3628
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

34
package.json Normal file
View File

@ -0,0 +1,34 @@
{
"name": "zx_web",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build"
},
"dependencies": {
"await-to-js": "^3.0.0",
"axios": "^1.8.1",
"element-plus": "^2.9.5",
"less": "^4.2.2",
"pinia": "^3.0.1",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},
"devDependencies": {
"@tsconfig/node22": "^22.0.0",
"@types/node": "^22.13.5",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"@vue/tsconfig": "^0.7.0",
"npm-run-all2": "^7.0.2",
"typescript": "~5.7.3",
"vite": "^6.1.0",
"vite-plugin-vue-devtools": "^7.7.2",
"vue-tsc": "^2.2.2"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

10
src/App.vue Normal file
View File

@ -0,0 +1,10 @@
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
</script>
<template>
<RouterView />
</template>
<style scoped>
</style>

10
src/api/user.ts Normal file
View File

@ -0,0 +1,10 @@
import request from "@/http";
import to from "await-to-js"
/**登录 */
export const login = (data: any) => to(
request.post("/login", {
}
))

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/assets/img/login_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_61_05011"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_61_05011)"><g><path d="M1,6L1,15Q1,16.6569,2.17157,17.828400000000002Q3.34315,19,5,19L19,19Q20.6569,19,21.8284,17.828400000000002Q23,16.6569,23,15L23,6Q23,4.34315,21.8284,3.17157Q20.6569,1.999999880791,19,2L5,2Q3.34315,2,2.17157,3.17157Q1,4.34315,1,6ZM3.58579,16.4142Q3,15.8284,3,15L3,6Q3,5.17157,3.58579,4.585789999999999Q4.17157,4,5,4L19,4Q19.8284,4,20.4142,4.585789999999999Q21,5.17157,21,6L21,15Q21,15.8284,20.4142,16.4142Q19.8284,17,19,17L5,17Q4.17157,17,3.58579,16.4142Z" fill-rule="evenodd" fill="#C0D5FF" fill-opacity="1"/></g><g><path d="M11,18Q11,17.9015086,11.019214999999999,17.80491Q11.03843,17.708311,11.076121,17.617317Q11.113812,17.526322,11.16853,17.44443Q11.223249,17.362537,11.292893,17.292893Q11.362537,17.223249,11.44443,17.16853Q11.526322,17.113812,11.617317,17.076121Q11.708311,17.038429999999998,11.80491,17.019215Q11.9015086,17,12,17Q12.0984914,17,12.19509,17.019215Q12.291689,17.038429999999998,12.382683,17.076121Q12.473678,17.113812,12.55557,17.16853Q12.637463,17.223249,12.707107,17.292893Q12.776751,17.362537,12.83147,17.44443Q12.886188,17.526322,12.923879,17.617317Q12.96157,17.708311,12.980785000000001,17.80491Q13,17.9015086,13,18L13,21.5Q13,21.598489999999998,12.980785000000001,21.69509Q12.96157,21.79169,12.923879,21.88268Q12.886188,21.97368,12.83147,22.05557Q12.776751,22.13746,12.707107,22.20711Q12.637463,22.27675,12.55557,22.33147Q12.473678,22.38619,12.382683,22.42388Q12.291689,22.461570000000002,12.19509,22.48078Q12.0984914,22.5,12,22.5Q11.9015086,22.5,11.80491,22.48078Q11.708311,22.461570000000002,11.617317,22.42388Q11.526322,22.38619,11.44443,22.33147Q11.362537,22.27675,11.292893,22.20711Q11.223249,22.13746,11.16853,22.05557Q11.113812,21.97368,11.076121,21.88268Q11.03843,21.79169,11.019214999999999,21.69509Q11,21.598489999999998,11,21.5L11,18Z" fill-rule="evenodd" fill="#C0D5FF" fill-opacity="1"/></g><g><path d="M5,20.5L19,20.5Q19.0985,20.5,19.1951,20.519215Q19.2917,20.538429999999998,19.3827,20.576121Q19.4737,20.613812,19.5556,20.66853Q19.6375,20.723249,19.7071,20.792893Q19.776699999999998,20.862537,19.8315,20.94443Q19.886200000000002,21.026322,19.9239,21.117317Q19.9616,21.208311,19.980800000000002,21.30491Q20,21.4015086,20,21.5Q20,21.5984914,19.980800000000002,21.69509Q19.9616,21.791689,19.9239,21.882683Q19.886200000000002,21.973678,19.8315,22.05557Q19.776699999999998,22.137463,19.7071,22.207107Q19.6375,22.276751,19.5556,22.33147Q19.4737,22.386188,19.3827,22.423879Q19.2917,22.461570000000002,19.1951,22.480785Q19.0985,22.5,19,22.5L5,22.5Q4.9015086,22.5,4.80491,22.480785Q4.708311,22.461570000000002,4.617317,22.423879Q4.526322,22.386188,4.44443,22.33147Q4.362537,22.276751,4.292893,22.207107Q4.223249,22.137463,4.16853,22.05557Q4.113812,21.973678,4.076121,21.882683Q4.03843,21.791689,4.019215,21.69509Q4,21.5984914,4,21.5Q4,21.4015086,4.019215,21.30491Q4.03843,21.208311,4.076121,21.117317Q4.113812,21.026322,4.16853,20.94443Q4.223249,20.862537,4.292893,20.792893Q4.362537,20.723249,4.44443,20.66853Q4.526322,20.613812,4.617317,20.576121Q4.708311,20.538429999999998,4.80491,20.519215Q4.9015086,20.5,5,20.5Z" fill-rule="evenodd" fill="#C0D5FF" fill-opacity="1"/></g><g><path d="M2,6L2,15C2,16.6569,3.34315,18,5,18L19,18C20.6569,18,22,16.6569,22,15L22,6C22,4.34315,20.6569,3,19,3L5,3C3.34315,3,2,4.34315,2,6ZM7.5,11C8.88071,11,10,9.88071,10,8.5C10,7.11929,8.88071,6,7.5,6C6.11929,6,5,7.11929,5,8.5C5,9.88071,6.11929,11,7.5,11ZM17,7C17,7.28836,16.875500000000002,7.56269,16.6585,7.75258L8.65937,14.7518C8.47621,14.9121,8.24222,15,8,15C7.44772,15,7,14.5523,7,14C7,13.7116,7.12448,13.4373,7.3415,13.2474L15.3415,6.24742C15.5238,6.08792,15.7578,6,16,6C16.552300000000002,6,17,6.44772,17,7ZM19,12.5C19,13.8807,17.880699999999997,15,16.5,15C15.1193,15,14,13.8807,14,12.5C14,11.11929,15.1193,10,16.5,10C17.880699999999997,10,19,11.11929,19,12.5Z" fill-rule="evenodd" fill="#C0D5FF" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_61_05055"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_61_05055)"><g><path d="M2,2L2,7C2,7.55228,2.447715,8,3,8L21,8C21.5523,8,22,7.55228,22,7L22,2C22,1.447715,21.5523,1,21,1L3,1C2.447715,1,2,1.447715,2,2ZM13.5,3.5L10.5,3.5C9.94772,3.5,9.5,3.94771,9.5,4.5C9.5,5.05228,9.94772,5.5,10.5,5.5L13.5,5.5C14.0523,5.5,14.5,5.05228,14.5,4.5C14.5,3.94771,14.0523,3.5,13.5,3.5ZM2,9.5L2,14.5C2,15.0523,2.447715,15.5,3,15.5L21,15.5C21.5523,15.5,22,15.0523,22,14.5L22,9.5C22,8.94772,21.5523,8.5,21,8.5L3,8.5C2.447715,8.5,2,8.94772,2,9.5ZM13.5,11L10.5,11C9.94772,11,9.5,11.4477,9.5,12C9.5,12.5523,9.94772,13,10.5,13L13.5,13C14.0523,13,14.5,12.5523,14.5,12C14.5,11.4477,14.0523,11,13.5,11ZM2,17L2,22C2,22.5523,2.447715,23,3,23L21,23C21.5523,23,22,22.5523,22,22L22,17C22,16.447699999999998,21.5523,16,21,16L3,16C2.447715,16,2,16.447699999999998,2,17ZM13.5,18.5L10.5,18.5C9.94772,18.5,9.5,18.9477,9.5,19.5C9.5,20.0523,9.94772,20.5,10.5,20.5L13.5,20.5C14.0523,20.5,14.5,20.0523,14.5,19.5C14.5,18.9477,14.0523,18.5,13.5,18.5Z" fill-rule="evenodd" fill="#C0D5FF" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="34" height="34" viewBox="0 0 34 34"><defs><clipPath id="master_svg0_61_02808"><rect x="0" y="0" width="34" height="34" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_61_02808)"><g><path d="M5.666015625,21.2507L5.666015625,12.04236C5.666015625,8.52154,8.520195625,5.66736,12.041015625,5.66736C15.561815625,5.66736,18.416015625,8.52154,18.416015625,12.04236L18.416015625,21.959C18.416015625,23.915,20.001715625,25.5007,21.957715625,25.5007C23.913715625,25.5007,25.499315625,23.915,25.499315625,21.959L25.499315625,12.50986C22.804715625,11.55753,21.798515625,8.270990000000001,23.497915625,5.97328C25.197415625,3.675572,28.634615625,3.675572,30.334115625,5.97328C32.033515625,8.271,31.027315625,11.55753,28.332715625,12.50986L28.332715625,21.959C28.332715625,25.4798,25.478515625,28.334,21.957715625,28.334C18.436915625,28.334,15.582715625,25.4798,15.582715625,21.959L15.582715625,12.04236C15.582715625,10.08635,13.997015625,8.500689999999999,12.041015625,8.500689999999999C10.085005625,8.500689999999999,8.499345625,10.08635,8.499345625,12.04236L8.499345625,21.2507L12.749315625,21.2507L7.082685625,28.334L1.416015625,21.2507L5.666015625,21.2507ZM26.916015625,9.91736C27.698415625,9.91736,28.332715625,9.28309,28.332715625,8.500689999999999C28.332715625,7.71829,27.698415625,7.084020000000001,26.916015625,7.084020000000001C26.133615625,7.084020000000001,25.499315625,7.71829,25.499315625,8.500689999999999C25.499315625,9.28309,26.133615625,9.91736,26.916015625,9.91736Z" fill="#09C5E7" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="34" height="34" viewBox="0 0 34 34"><defs><clipPath id="master_svg0_61_02785"><rect x="0" y="0" width="34" height="34" rx="0"/></clipPath></defs><g style="opacity:0.5;" clip-path="url(#master_svg0_61_02785)"><g><path d="M5.666015625,21.2507L5.666015625,12.04236C5.666015625,8.52154,8.520195625,5.66736,12.041015625,5.66736C15.561815625,5.66736,18.416015625,8.52154,18.416015625,12.04236L18.416015625,21.959C18.416015625,23.915,20.001715625,25.5007,21.957715625,25.5007C23.913715625,25.5007,25.499315625,23.915,25.499315625,21.959L25.499315625,12.50986C22.804715625,11.55753,21.798515625,8.270990000000001,23.497915625,5.97328C25.197415625,3.675572,28.634615625,3.675572,30.334115625,5.97328C32.033515625,8.271,31.027315625,11.55753,28.332715625,12.50986L28.332715625,21.959C28.332715625,25.4798,25.478515625,28.334,21.957715625,28.334C18.436915625,28.334,15.582715625,25.4798,15.582715625,21.959L15.582715625,12.04236C15.582715625,10.08635,13.997015625,8.500689999999999,12.041015625,8.500689999999999C10.085005625,8.500689999999999,8.499345625,10.08635,8.499345625,12.04236L8.499345625,21.2507L12.749315625,21.2507L7.082685625,28.334L1.416015625,21.2507L5.666015625,21.2507ZM26.916015625,9.91736C27.698415625,9.91736,28.332715625,9.28309,28.332715625,8.500689999999999C28.332715625,7.71829,27.698415625,7.084020000000001,26.916015625,7.084020000000001C26.133615625,7.084020000000001,25.499315625,7.71829,25.499315625,8.500689999999999C25.499315625,9.28309,26.133615625,9.91736,26.916015625,9.91736Z" fill="#09C5E7" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><defs><clipPath id="master_svg0_61_01998"><rect x="0" y="0" width="20" height="20" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_61_01998)"><g><path d="M1.666656494140625,2.5003251875C1.666656494140625,2.0400881875,2.039752494140625,1.6669921875,2.499989494140625,1.6669921875L7.499986494140625,1.6669921875C7.835746494140625,1.6669921875,8.138696494140625,1.8684841875,8.268516494140625,2.1781251875Q8.881846494140625,3.6410721875,9.999996494140625,3.6410721875Q11.118136494140625,3.6410721875,11.731456494140625,2.1781261875C11.861256494140624,1.8684851875,12.164256494140625,1.6669921875,12.499956494140624,1.6669921875L17.499956494140626,1.6669921875C17.960256494140626,1.6669921875,18.333356494140624,2.0400881875,18.333356494140624,2.5003251875L18.333356494140624,17.5002921875C18.333356494140624,17.9605921875,17.960256494140626,18.3336921875,17.499956494140626,18.3336921875L2.499989494140625,18.3336921875C2.039752494140625,18.3336921875,1.666656494140625,17.9605921875,1.666656494140625,17.5002921875L1.666656494140625,2.5003251875ZM14.339256494140624,8.0895821875C14.495556494140626,7.9333021875,14.583356494140626,7.7213421875,14.583356494140626,7.5003221875C14.583356494140626,7.0400921875,14.210256494140625,6.6669921875,13.749956494140624,6.6669921875C13.528956494140624,6.6669921875,13.317056494140624,6.7547921875,13.160456494140625,6.9113821875L8.749986494140625,11.3218121875L6.839246494140625,9.4110721875C6.682966494140625,9.2547921875,6.471006494140625,9.1669921875,6.249986494140625,9.1669921875C5.789756494140625,9.1669921875,5.416656494140625,9.5400921875,5.416656494140625,10.0003221875C5.416656494140625,10.2213421875,5.504456494140625,10.4333021875,5.660736494140625,10.5895821875L8.160736494140625,13.0895921875C8.317016494140624,13.2458921875,8.528976494140625,13.3336921875,8.749986494140625,13.3336921875C8.971006494140624,13.3336921875,9.182966494140626,13.2458921875,9.339246494140625,13.0895921875L14.339256494140624,8.0895821875Z" fill-rule="evenodd" fill="#09C5E7" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,9 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,body,#app{
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,118 @@
<template>
<header class="header_container">
<div class="bg">
<img class="left" src="@/assets/img/header_left_bg.png" alt="">
<img class="center" src="@/assets/img/hrader_center_bg.png" alt="">
<img class="right" src="@/assets/img/header_right_bg.png" alt="">
</div>
<div class="header_main">
<div class="tabs">
<div v-for="tab in props.tabs" @click="changeType(tab.type)" class="tab" :class="{ checked: tab.type == props.type }">
<span>{{ tab.label }}</span>
</div>
</div>
<div class=""></div>
</div>
</header>
</template>
<script setup lang="ts">
import { ref } from "vue"
const props = defineProps(['tabs','type'])
const emit = defineEmits(["update:type"])
function changeType(type:number){
emit("update:type",type)
}
</script>
<style lang="less" scoped>
.header_container {
position: relative;
z-index: 0;
flex-shrink: 0;
height: 57px;
.bg {
position: absolute;
z-index: -1;
display: flex;
height: 57px;
background-color: antiquewhite;
width: 100%;
img {
height: 100%;
min-width: 0;
}
.center {
flex: 1;
}
}
.header_main {
position: absolute;
margin-left: 400px;
bottom: 0;
height: 36px;
// background-color: antiquewhite;
display: flex;
.tabs {
display: flex;
justify-content: center;
align-items: center;
padding-left: 3px;
.tab {
display: flex;
position: relative;
z-index: 0;
justify-content: center;
align-items: center;
height: 100%;
padding: 0 25px;
margin-right: 10px;
color: #fff;
cursor: pointer;
&:last-child{
margin-right: 0;
}
&::before {
position: absolute;
content: "";
z-index: 1;
width: 100%;
height: 100%;
transform: skewX(-25deg);
}
&::after {
position: absolute;
content: "";
z-index: -1;
width: 100%;
height: 100%;
transform: skewX(-25deg);
box-shadow: 0 0 0 1px #277EFF inset;
}
&.checked::after {
box-sizing: border-box;
background: linear-gradient(0deg, #009BFC, #004DE7);
box-shadow: none;
}
span {
font-size: 18px;
}
}
}
}
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<div class="side_bar">
<div class="nav_item" v-for="item in navList">
<img class="icon" :src="item.icon" :alt="item.label">
<span class="label">{{ item.label }}</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue"
import dataIcon from "@/assets/img/main_nav_data_icon.svg"
import fileIcon from "@/assets/img/main_nav_file_icon.svg"
import groupIcon from "@/assets/img/main_nav_group_icon.svg"
import uavIcon from "@/assets/img/main_nav_uav_icon.svg"
import userIcon from "@/assets/img/main_nav_user_icon.svg"
const navList = [
{
icon: dataIcon,
label: "数据"
},
{
icon: userIcon,
label: "人员"
},
{
icon: groupIcon,
label: "组织"
},
{
icon: uavIcon,
label: "设备"
},
{
icon: fileIcon,
label: "文件"
},
]
</script>
<style lang="less" scoped>
.side_bar {
width: 60px;
height: 100%;
position: relative;
background-color: antiquewhite;
background: linear-gradient(180deg, #114F99 23%, rgba(18, 25, 76, 0) 100%);
display: flex;
flex-direction: column;
align-items: center;
&::after {
content: "";
position: absolute;
right: 0;
top: 0;
height: 100%;
background-color: aquamarine;
background: linear-gradient(180deg, #45adf3, rgba(69, 173, 243, 0.1) 100%);
width: 2px;
}
.nav_item{
display: flex;
flex-direction: column;
cursor: pointer;
margin-top: 16px;
.icon{
width: 24px;
height: 24px;
}
.label{
font-size: 14px;
margin-top: 3px;
color: rgba(255, 255, 255, 0.64);
}
}
}
</style>

View File

@ -0,0 +1,68 @@
<template>
<div class="ZfControlPlatform">
<div class="container_left">
<div class="task">
<taskList></taskList>
</div>
<div class="preview">
12312
</div>
</div>
<div class="container_center"></div>
<div class="container_right"></div>
</div>
</template>
<script setup lang="ts">
import taskList from "@/components/zfControlPlatform/taskList/index.vue"
</script>
<style lang="less" scoped>
.ZfControlPlatform {
display: flex;
padding: 12px;
background-color: rgb(0, 255, 162);
height: 100%;
.container_left {
width: 363px;
margin-right: 12px;
display: flex;
flex-direction: column;
flex-shrink: 0;
height: 100%;
background-color: chocolate;
.task {
background-color: brown;
flex: 1;
margin-bottom: 12px;
height: 0;
}
.preview {
height: 363px;
flex-shrink: 0;
background-color: rgb(24, 24, 24);
}
}
.container_center {
flex: 1;
background-color: pink;
margin-right: 12px;
}
.container_right {
width: 371px;
background-color: black;
flex-shrink: 0;
}
}
</style>

View File

@ -0,0 +1,55 @@
<template>
<div class="task_list">
<div class="title">
<img class="icon" src="@/assets/img/zf_task_title_icon.svg" alt="">
<span>任务进度</span>
</div>
<div class="list">
<el-scrollbar>
<taskItem v-for="i in 10"></taskItem>
</el-scrollbar>
</div>
</div>
</template>
<script setup lang="ts">
import taskItem from './taskItem.vue';
</script>
<style lang="less" scoped>
.task_list {
background-color: #053b7b;
height: 100%;
display: flex;
flex-direction: column;
.title {
display: flex;
align-items: center;
height: 40px;
background: linear-gradient(90deg, #0A5CC8 3%, #053B7B 95%);
padding-left: 20px;
font-size: 18px;
color: #fff;
border-bottom: 1px solid #4784FF;
;
.icon {
width: 20px;
height: 20px;
margin-right: 8px;
}
}
.list {
flex: 1;
height: 0;
padding: 16px 20px;
overflow-y: auto;
height: 0;
}
}
</style>

View File

@ -0,0 +1,58 @@
<template>
<div class="task_item">
<div class="icon">
<img src="@/assets/img/zf_task_path_icon.svg" alt="">
<!-- <img src="@/assets/img/zf_task_path_activate_icon.svg" alt=""> -->
</div>
<div class="item_content">
<div>
<span class="label">航线</span>
<span>G244平罗段</span>
</div>
<div>
<span class="label">桩号</span>
<span>k21+800-K79+448</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
</script>
<style lang="less" scoped>
.task_item {
height: 60px;
display: flex;
align-items: center;
cursor: pointer;
border-bottom: #265fbd 1px solid;
&:hover{
background-color: #034da5;
}
.icon {
width: 34px;
height: 34px;
margin-right: 12px;
img {
display: block;
width: 100%;
height: 100%;
}
}
.item_content {
display: flex;
flex-direction: column;
// background-color: antiquewhite;
font-size: 14px;
color: #fff;
.label {
color: rgba(255, 255, 255, 0.65);
}
}
}
</style>

17
src/http/index.ts Normal file
View File

@ -0,0 +1,17 @@
import axios from "axios";
const request = axios.create({
baseURL: import.meta.env.VITE_BASE_URL
})
request.interceptors.request.use((config) => {
return config
})
request.interceptors.response.use((res) => {
return res
})
export default request

17
src/main.ts Normal file
View File

@ -0,0 +1,17 @@
import './assets/style/base.less'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')

26
src/router/index.ts Normal file
View File

@ -0,0 +1,26 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/index/index.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path:"/login",
name:"login",
component:()=>import("../views/login/index.vue")
},
{
path:"/:pathMatch(.*)*",
name:"NotFound",
component:()=>import("../views/404/index.vue")
}
],
})
export default router

15
src/stores/user.ts Normal file
View File

@ -0,0 +1,15 @@
import { defineStore } from 'pinia'
const useUserInfoStore = defineStore('userInfo', {
state: () => ({
token: ""
}),
getters: {
},
actions: {
}
})
export default useUserInfoStore

11
src/views/404/index.vue Normal file
View File

@ -0,0 +1,11 @@
<template>
<div>404</div>
</template>
<script setup lang="ts">
</script>
<style lang="less" scoped>
</style>

66
src/views/index/index.vue Normal file
View File

@ -0,0 +1,66 @@
<template>
<div class="main_container">
<headerBar v-model:type="currentTabType" :tabs="tabs"></headerBar>
<div class="main_layout">
<sideBar></sideBar>
<main class="main">
<ZfControlPlatform v-show="currentTabType == 0"></ZfControlPlatform>
<iframe v-show="currentTabType == 1" src="https://117.78.20.62/#/login"></iframe>
<iframe v-show="currentTabType == 2" src="https://smartcity.zhifei.tech:9090/#/"></iframe>
</main>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import headerBar from '@/components/main/headerBar.vue';
import sideBar from '@/components/main/sideBar.vue';
import ZfControlPlatform from "@/components/zfControlPlatform/index.vue"
const tabs = [
{
type: 0,
label: "智飞云飞控平台"
},
{
type: 1,
label: "调度处置"
},
{
type: 2,
label: "飞行控制"
},
]
const currentTabType = ref(0)
function changeType(type: number) {
currentTabType.value = type
}
</script>
<style lang="less" scoped>
.main_container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background-color: #020e26;
.main_layout {
display: flex;
flex: 1;
height: 0;
.main {
width: 100%;
height: 100%;
iframe {
width: 100%;
height: 100%;
border: none;
}
}
}
}
</style>

274
src/views/login/index.vue Normal file
View File

@ -0,0 +1,274 @@
<template>
<div class="login_wrap">
<div class="main">
<div class="logo">
<img class="logo_border" src="@/assets/img/login_logo_border.png" alt="">
<img class="logo_img" src="@/assets/img/login_logo.png" alt="">
</div>
<h2 class="title">交通综合执法检查系统</h2>
<form class="form_wrap" @submit="submit">
<div class="form_item" :class="{ error: errors.userName }">
<div class="icon">
<img src="@/assets/img/login_user_icon.png" alt="">
</div>
<input class="input" v-model="loginFormData.userName" type="text" placeholder="请输入账号" @input="clearError('userName')">
</div>
<div class="form_item" :class="{ error: errors.password }">
<div class="icon">
<img src="@/assets/img/login_password_icon.png" alt="">
</div>
<input class="input" v-model="loginFormData.password" type="password" placeholder="请输入密码" @input="clearError('password')">
</div>
<div class="options">
<label class="save_password">
<span class="check_box" :class="{ checked: savePasswordFlag }">
<img src="@/assets/img/login_checked_icon.png" alt="">
</span>
<input v-model="savePasswordFlag" @change="changSavePassword" type="checkbox" name="" id="">
<span>记住密码</span>
</label>
<a>忘记密码</a>
</div>
<button class="submit">登录</button>
</form>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue"
import { login } from "@/api/user.ts"
import { ElMessage } from "element-plus"
import {useRouter} from "vue-router"
const router = useRouter()
const savePasswordFlag = ref(!!(localStorage.getItem('user')))
const loginFormData = ref(JSON.parse(localStorage.getItem('user') || '{"userName":"","password":""}'))
//
const errors = ref({
userName: false,
password: false
})
//
function clearError(field: 'userName' | 'password') {
errors.value[field] = false
}
function changSavePassword() {
if (savePasswordFlag.value) {
localStorage.setItem("user", JSON.stringify(loginFormData.value))
} else {
localStorage.removeItem("user")
}
}
//
function submit(event: Event) {
event.preventDefault()
changSavePassword()
if (!validate()) return;
router.push("/")
}
/**表单校验 */
function validate() {
errors.value.userName = !loginFormData.value.userName
errors.value.password = !loginFormData.value.password
if (errors.value.userName) {
ElMessage({
type: "error",
message: "请输入用户名"
})
return false
}
if (errors.value.password) {
ElMessage({
type: "error",
message: "请输入密码"
})
return false
}
return true
}
async function toLogin() {
const [err, res] = await login({})
}
</script>
<style lang="less" scoped>
.login_wrap {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-image: url("@/assets/img/login_bg.png");
background-size: cover;
background-color: antiquewhite;
.main {
display: flex;
flex-direction: column;
align-items: center;
// background-color: antiquewhite;
.logo {
width: 254px;
height: 254px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
.logo_border {
position: absolute;
transform: translateX(-3px);
width: 100%;
height: 100%;
}
.logo_img {
width: 160px;
}
}
.title {
height: 60px;
opacity: 0.93;
font-size: 42px;
font-weight: 800;
line-height: 60px;
text-align: center;
color: #0055E9;
}
.form_wrap {
width: 658px;
height: 529px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin-top: 40px;
border-radius: 4px;
background: #FFFFFF;
box-shadow: 0px 4px 30px 0px rgba(220, 220, 220, 0.1);
.form_item {
width: 522px;
height: 72px;
border-radius: 2px;
display: flex;
flex-direction: row;
align-items: center;
padding: 10px 16px 10px 22px;
background: #F5F7FA;
border: 1px solid #FFFFFF;
.icon img {
width: 24px;
height: 24px;
}
&+.form_item {
display: flex;
margin-top: 32px;
}
.input {
height: 100%;
flex: 1;
border: none;
background-color: transparent;
padding: 0 18px;
color: #1A1A1A;
font-size: 21px;
&:-webkit-autofill,
&:-webkit-autofill:hover,
&:-webkit-autofill:focus,
&:-webkit-autofill:active {
transition: background-color 5000s !important;
-webkit-text-fill-color: rgba(0, 0, 0, 0.65) !important;
}
&:focus {
outline: none;
}
}
&.error {
border: 1px solid #ff4d4f;
background: #fff2f0;
}
}
.options {
display: flex;
justify-content: space-between;
margin: 24px 0 56px;
width: 522px;
font-size: 22px;
color: #767676;
.save_password {
display: flex;
align-items: center;
cursor: pointer;
input {
display: none;
}
.check_box {
width: 22px;
height: 22px;
margin-right: 12px;
border-radius: 50%;
border: 1px #767676 solid;
display: flex;
justify-content: center;
align-items: center;
img {
width: 14px;
}
}
.check_box.checked {
background-color: #0055E9;
border: none;
}
}
}
.submit {
width: 522px;
height: 80px;
border: none;
cursor: pointer;
border-radius: 2px;
font-size: 28px;
color: #fff;
background: linear-gradient(180deg, #004DE7 0%, #009BFC 100%);
}
}
}
}
</style>

12
tsconfig.app.json Normal file
View File

@ -0,0 +1,12 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"@/*": ["./src/*"]
}
}
}

11
tsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}

19
tsconfig.node.json Normal file
View File

@ -0,0 +1,19 @@
{
"extends": "@tsconfig/node22/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"eslint.config.*"
],
"compilerOptions": {
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

20
vite.config.ts Normal file
View File

@ -0,0 +1,20 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
})