init
							
								
								
									
										2
									
								
								.env
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,2 @@
 | 
			
		||||
# Place your StackBlitz environment variables here,
 | 
			
		||||
# and they will be securely synced to your account.
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
			
		||||
node_modules
 | 
			
		||||
							
								
								
									
										3
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
  "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
# Vue 3 + Vite
 | 
			
		||||
 | 
			
		||||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
 | 
			
		||||
 | 
			
		||||
## Recommended IDE Setup
 | 
			
		||||
 | 
			
		||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
 | 
			
		||||
							
								
								
									
										24
									
								
								_gitignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,24 @@
 | 
			
		||||
# Logs
 | 
			
		||||
logs
 | 
			
		||||
*.log
 | 
			
		||||
npm-debug.log*
 | 
			
		||||
yarn-debug.log*
 | 
			
		||||
yarn-error.log*
 | 
			
		||||
pnpm-debug.log*
 | 
			
		||||
lerna-debug.log*
 | 
			
		||||
 | 
			
		||||
node_modules
 | 
			
		||||
dist
 | 
			
		||||
dist-ssr
 | 
			
		||||
*.local
 | 
			
		||||
 | 
			
		||||
# Editor directories and files
 | 
			
		||||
.vscode/*
 | 
			
		||||
!.vscode/extensions.json
 | 
			
		||||
.idea
 | 
			
		||||
.DS_Store
 | 
			
		||||
*.suo
 | 
			
		||||
*.ntvs*
 | 
			
		||||
*.njsproj
 | 
			
		||||
*.sln
 | 
			
		||||
*.sw?
 | 
			
		||||
							
								
								
									
										13
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="UTF-8" />
 | 
			
		||||
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
			
		||||
    <title>Vite + Vue</title>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <div id="app"></div>
 | 
			
		||||
    <script type="module" src="/src/main.js"></script>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										1940
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										22
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "vite-vue-starter",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "type": "module",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "dev": "vite",
 | 
			
		||||
    "build": "vite build",
 | 
			
		||||
    "preview": "vite preview"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "echarts": "^5.4.3",
 | 
			
		||||
    "element-plus": "^2.4.4",
 | 
			
		||||
    "pinia": "^2.1.7",
 | 
			
		||||
    "vue": "^3.3.11",
 | 
			
		||||
    "vue3-marquee": "^4.1.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@vitejs/plugin-vue": "^5.0.2",
 | 
			
		||||
    "vite": "^5.0.8"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								public/vite.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
							
								
								
									
										71
									
								
								src/App.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,71 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, provide } from "vue";
 | 
			
		||||
import MainPage from "./MainPage.vue";
 | 
			
		||||
import Slider from "./components/Slider.vue";
 | 
			
		||||
import Client from "./utils/ws";
 | 
			
		||||
import { useWsStore } from "./store";
 | 
			
		||||
 | 
			
		||||
const store = useWsStore();
 | 
			
		||||
 | 
			
		||||
const url = "ws://192.168.1.101:8082/QbMonitoring/websocket";
 | 
			
		||||
let urlPath = document.location.pathname;
 | 
			
		||||
if (urlPath === "/") {
 | 
			
		||||
  urlPath = "/1-1";
 | 
			
		||||
}
 | 
			
		||||
new Client(
 | 
			
		||||
  {
 | 
			
		||||
    url: url + urlPath,
 | 
			
		||||
    name: urlPath,
 | 
			
		||||
  },
 | 
			
		||||
  (message) => {
 | 
			
		||||
    try {
 | 
			
		||||
 | 
			
		||||
      const data = JSON.parse(message.data);
 | 
			
		||||
      console.log("message", JSON.parse(message.data));
 | 
			
		||||
      
 | 
			
		||||
      if ("specificationChanges" in data) {
 | 
			
		||||
        console.log('[*] setting data1')
 | 
			
		||||
        // 分屏推送1数据
 | 
			
		||||
        store.updateData('1', data);
 | 
			
		||||
      } else if ("deliveryNotification" in data) {
 | 
			
		||||
        // 分屏推送3数据
 | 
			
		||||
        console.log('[*] setting data3')
 | 
			
		||||
        store.updateData('3', data);
 | 
			
		||||
      } else {
 | 
			
		||||
        // 分屏推送2数据
 | 
			
		||||
        console.log('[*] setting data2')
 | 
			
		||||
        store.updateData('2', data);
 | 
			
		||||
      }
 | 
			
		||||
    } catch(err) {
 | 
			
		||||
      console.log('[x] 未解析的ws数据: ', err);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const styles = ref({});
 | 
			
		||||
function setSize(value) {
 | 
			
		||||
  const v = (value / 100).toFixed(2);
 | 
			
		||||
  console.log("size change", value);
 | 
			
		||||
  styles.value = {
 | 
			
		||||
    transform: `scale(${v})`,
 | 
			
		||||
    // transform: `scale(${v * 24 / 33}, ${v})`,
 | 
			
		||||
    transformOrigin: "top left",
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div id="app-container">
 | 
			
		||||
    <MainPage :style="styles" />
 | 
			
		||||
    <Slider @size-change="setSize" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
#app-container {
 | 
			
		||||
  width: 100vw;
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										57
									
								
								src/MainPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,57 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
import Tools from './components/Tools.vue';
 | 
			
		||||
import NavMenu from './components/NavMenu.vue';
 | 
			
		||||
import AnnoucementPage from './pages/AnnouncementPage.vue';
 | 
			
		||||
import RealtimePage from './pages/RealtimePage.vue';
 | 
			
		||||
import AppHeader from './components/Base/Header.vue';
 | 
			
		||||
import AlertListPage from './pages/AlertListPage.vue'
 | 
			
		||||
import DataPage from './pages/DataPage.vue';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const currentPage = ref('3d');
 | 
			
		||||
const handlePageChange = (page) => {
 | 
			
		||||
  currentPage.value = page;
 | 
			
		||||
  console.log(currentPage.value);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="main-container">
 | 
			
		||||
    <Tools v-if="currentPage !== 'announcement'" />
 | 
			
		||||
    <AppHeader v-if="currentPage !== 'announcement'" />
 | 
			
		||||
    <AnnoucementPage
 | 
			
		||||
      v-if="currentPage === 'announcement'"
 | 
			
		||||
      class="annoucement-page"
 | 
			
		||||
      @home="() => handlePageChange('3d')"
 | 
			
		||||
    />
 | 
			
		||||
    <div v-else class="pages-wrapper">
 | 
			
		||||
      <NavMenu @change="handlePageChange" />
 | 
			
		||||
      <div v-if="currentPage === '3d'" class="3d-page">3d</div>
 | 
			
		||||
      <DataPage v-if="currentPage === 'data'" />
 | 
			
		||||
      <AlertListPage v-if="currentPage === 'alert'" />
 | 
			
		||||
      <RealtimePage v-if="currentPage === 'realtime'" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.main-container {
 | 
			
		||||
  width: 1920px;
 | 
			
		||||
  height: 1080px;
 | 
			
		||||
  background: #000;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  /** 
 | 
			
		||||
  background: url('https://img1.baidu.com/it/u=2052683582,2603151390&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800')
 | 
			
		||||
  100% / 100% no-repeat;
 | 
			
		||||
  */
 | 
			
		||||
  background: url(./assets/bg.png) 100% / cover no-repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pages-wrapper {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/bg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 761 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/header-bg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 25 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/header-bg@2x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 90 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/leftcorner@2x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/logo@2x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 12 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/rightcorner@2x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.2 KiB  | 
							
								
								
									
										24
									
								
								src/assets/svg/check.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,24 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="26px" height="26px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
			
		||||
    <title>任务</title>
 | 
			
		||||
    <defs>
 | 
			
		||||
        <linearGradient x1="91.384997%" y1="100%" x2="25.4330364%" y2="7.84095011e-14%" id="linearGradient-1">
 | 
			
		||||
            <stop stop-color="#4BFFC8" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#45F2EC" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
        <linearGradient x1="91.384997%" y1="100%" x2="25.4330364%" y2="7.84095011e-14%" id="linearGradient-2">
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
    </defs>
 | 
			
		||||
    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
 | 
			
		||||
        <g id="环动科技热处理车间立库看板" transform="translate(-989.000000, -621.000000)" fill-rule="nonzero">
 | 
			
		||||
            <g id="编组-36" transform="translate(982.000000, 621.000000)">
 | 
			
		||||
                <g id="任务" transform="translate(7.000000, 0.000000)">
 | 
			
		||||
                    <rect id="矩形" fill="#FFFFFF" opacity="0" x="0" y="0" width="32" height="32"></rect>
 | 
			
		||||
                    <path d="M24.8336138,7.21888656 C25.307557,7.21888656 25.7025096,7.62700427 25.6893445,8.08778234 L25.6893445,25.768495 C25.6893445,26.5452352 25.2417316,26.6505559 24.859944,26.6505559 L7.17923134,26.6505559 C6.6921231,26.6505559 6.31033556,26.2556033 6.31033556,25.7816601 L6.31033556,8.10094743 C6.31033556,7.61383919 6.70528819,7.23205165 7.17923134,7.23205165 L10.3915127,7.23205165 L10.3915127,9.00933847 C10.3915127,9.41745619 10.733805,9.75974847 11.1419227,9.75974847 L20.8709225,9.75974847 C21.2790402,9.75974847 21.6213325,9.43062128 21.6213325,9.00933847 L21.6213325,7.21888656 Z M21.3580307,13.7224398 C21.0289035,13.3933127 20.5154651,13.3933127 20.1863379,13.7224398 L14.5385153,19.3702624 L11.7738469,16.6319242 C11.4447197,16.302797 10.9312813,16.302797 10.6021541,16.6319242 C10.2730269,16.9610514 10.2730269,17.4744898 10.6021541,17.803617 L13.9460864,21.1475493 C14.2752136,21.4766764 14.788652,21.4766764 15.1177792,21.1475493 L21.3711958,14.9072977 C21.5423419,14.7361516 21.6213325,14.5386753 21.6213325,14.3148688 C21.6213325,14.0910623 21.5291768,13.893586 21.3580307,13.7224398 Z M19.896706,5.34944412 C20.1863379,5.34944412 20.4364746,5.59958078 20.4364746,5.88921271 L20.4364746,8.10094743 C20.4364746,8.39057936 20.1863379,8.64071602 19.896706,8.64071602 L12.1161392,8.64071602 L12.1161392,8.6670462 C11.8265073,8.6670462 11.5763706,8.41690953 11.5763706,8.1272776 L11.5763706,5.88921271 C11.5763706,5.59958078 11.8265073,5.34944412 12.1161392,5.34944412 L19.896706,5.34944412 Z" id="形状结合" fill="url(#linearGradient-2)"></path>
 | 
			
		||||
                </g>
 | 
			
		||||
            </g>
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										22
									
								
								src/assets/svg/cube-twice.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="26px" height="26px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
			
		||||
    <title>更多 2</title>
 | 
			
		||||
    <defs>
 | 
			
		||||
        <linearGradient x1="100%" y1="100%" x2="20.318998%" y2="7.84095011e-14%" id="linearGradient-1">
 | 
			
		||||
            <stop stop-color="#4BFFC8" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#45F2EC" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
        <linearGradient x1="100%" y1="100%" x2="20.318998%" y2="7.84095011e-14%" id="linearGradient-2">
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
    </defs>
 | 
			
		||||
    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
 | 
			
		||||
        <g id="环动科技热处理车间立库看板" transform="translate(-670.000000, -119.000000)" fill-rule="nonzero">
 | 
			
		||||
            <g id="更多-2" transform="translate(670.000000, 119.000000)">
 | 
			
		||||
                <rect id="矩形" fill="#FFFFFF" opacity="0" x="0" y="0" width="32" height="32"></rect>
 | 
			
		||||
                <path d="M18.6666667,12 L18.6666667,5.33333333 L7.33333333,5.33333333 C6.22876383,5.33333333 5.33333333,6.22876383 5.33333333,7.33333333 L5.33333333,18.6666667 L5.33333333,18.6666667 L12,18.6666667 L12,12 L18.6666667,12 Z M20,13.3333333 L20,20 L13.3333333,20 L13.3333333,26.6666667 L24.6666667,26.6666667 C25.7712362,26.6666667 26.6666667,25.7712362 26.6666667,24.6666667 L26.6666667,13.3333333 L26.6666667,13.3333333 L20,13.3333333 Z" id="形状" fill="url(#linearGradient-2)"></path>
 | 
			
		||||
            </g>
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
							
								
								
									
										12
									
								
								src/assets/svg/cube.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,12 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="26px" height="26px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
			
		||||
    <title>多种 2</title>
 | 
			
		||||
    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
 | 
			
		||||
        <g id="环动科技热处理车间立库看板" transform="translate(-39.000000, -620.000000)" fill="#FFFFFF" fill-rule="nonzero">
 | 
			
		||||
            <g id="多种-2" transform="translate(39.000000, 620.000000)">
 | 
			
		||||
                <rect id="矩形" opacity="0" x="0" y="0" width="32" height="32"></rect>
 | 
			
		||||
                <path d="M26,23 L18.2,27.8 C17.6,28.2 17,27.8 17,27 L17,15.8 C17,15.6 17.2,15.2 17.4,15 L25.2,10.2 C25.8,9.8 26.4,10.2 26.4,11 L26.4,22.4 C26.4,22.6 26.2,23 26,23 Z M6,23 L13.8,27.8 C14.4,28.2 15,27.8 15,27 L15,15.8 C15,15.6 14.8,15.2 14.6,15 L6.8,10.2 C6.4,10 5.6,10.4 5.6,11 L5.6,22.4 C5.6,22.6 5.8,23 6,23 Z M15.8,4 L6.8,7.4 C6.4,7.6 6.4,8.2 6.8,8.4 L15.8,14 C16,14 16.2,14 16.2,14 L25.4,8.4 C25.8,8.2 25.8,7.6 25.4,7.4 L16.2,4 C16,4 16,4 15.8,4 Z" id="形状"></path>
 | 
			
		||||
            </g>
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
							
								
								
									
										40
									
								
								src/assets/svg/stack.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,40 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="26px" height="26px" viewBox="0 0 24.4721163 23.7661066" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
			
		||||
    <title>多种</title>
 | 
			
		||||
    <defs>
 | 
			
		||||
        <linearGradient x1="100%" y1="89.6187762%" x2="20.318998%" y2="10.3812238%" id="linearGradient-1">
 | 
			
		||||
            <stop stop-color="#4BFFC8" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#45F2EC" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
        <linearGradient x1="100%" y1="89.6187762%" x2="20.318998%" y2="10.3812238%" id="linearGradient-2">
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
        <linearGradient x1="100%" y1="54.7269958%" x2="20.318998%" y2="45.2730042%" id="linearGradient-3">
 | 
			
		||||
            <stop stop-color="#4BFFC8" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#45F2EC" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
        <linearGradient x1="100%" y1="54.7269958%" x2="20.318998%" y2="45.2730042%" id="linearGradient-4">
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#FFFFFF" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
    </defs>
 | 
			
		||||
    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
 | 
			
		||||
        <g id="环动科技热处理车间立库看板" transform="translate(-43.763942, -124.000000)">
 | 
			
		||||
            <g id="多种" transform="translate(40.000000, 120.000000)">
 | 
			
		||||
                <rect id="矩形" x="0" y="0" width="32" height="32"></rect>
 | 
			
		||||
                <g id="异常" transform="translate(3.763942, 4.000000)" fill-rule="nonzero">
 | 
			
		||||
                    <rect id="矩形" fill="#FFFFFF" opacity="0" x="0.236058137" y="0" width="22.6666667" height="22.6666667"></rect>
 | 
			
		||||
                    <g transform="translate(0.000000, 1.333333)">
 | 
			
		||||
                        <rect id="矩形" fill="#FFFFFF" opacity="0" x="3.05901453" y="5.09835756" width="17.3344157" height="17.3344157"></rect>
 | 
			
		||||
                        <g id="数量_面性">
 | 
			
		||||
                            <rect id="矩形" fill="#FFFFFF" opacity="0" x="0" y="0" width="21.7851425" height="21.7851425"></rect>
 | 
			
		||||
                            <path d="M12.237403,12.1431998 C12.1208704,12.1431998 12.0057183,12.1179773 11.8998678,12.0692379 L0.469391828,6.80449511 C0.183288453,6.67275726 2.8725996e-07,6.38657609 2.8725996e-07,6.07159989 C2.8725996e-07,5.7566237 0.183288453,5.47044252 0.469391828,5.33870467 L11.8998678,0.073961899 C12.1133182,-0.0238729288 12.3587984,-0.0238729288 12.5722488,0.073961899 L24.0027247,5.33870467 C24.2888281,5.47044252 24.4721163,5.7566237 24.4721163,6.07159989 C24.4721163,6.38657609 24.2888281,6.67275726 24.0027247,6.80449511 L12.5722488,12.0692379 C12.4672224,12.1175995 12.3530285,12.142823 12.237403,12.1431998 L12.237403,12.1431998 Z M23.2644505,15.0102321 L12.237403,20.0893977 L1.21035562,15.0102321 L1.21035562,16.7866626 L11.8998678,21.7111806 C12.1133182,21.8090154 12.3587984,21.8090154 12.5722488,21.7111806 L23.2644505,16.7866626 L23.2644505,15.0102321 Z" id="形状" fill="url(#linearGradient-2)"></path>
 | 
			
		||||
                            <path d="M23.2644505,10.1838817 L12.237403,15.2643921 L1.21035562,10.1838817 L1.21035562,11.9683807 L11.8998678,16.891554 C12.1133182,16.9893888 12.3587984,16.9893888 12.5722488,16.891554 L23.2644505,11.9683807 L23.2644505,10.1838817 Z" id="路径" fill="url(#linearGradient-4)"></path>
 | 
			
		||||
                        </g>
 | 
			
		||||
                    </g>
 | 
			
		||||
                </g>
 | 
			
		||||
            </g>
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 3.5 KiB  | 
							
								
								
									
										114
									
								
								src/components/Base/Container.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,114 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import Icon from './Icon.vue';
 | 
			
		||||
import Corner from './Corner.vue';
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  title: {
 | 
			
		||||
    type: String,
 | 
			
		||||
    default: 'Default title',
 | 
			
		||||
  },
 | 
			
		||||
  icon: {
 | 
			
		||||
    type: String,
 | 
			
		||||
    default: 'icon',
 | 
			
		||||
  },
 | 
			
		||||
  corner: {
 | 
			
		||||
    type: Array,
 | 
			
		||||
    default: ['tl', 'tr', 'bl', 'br'], //'trbl', // top right bottom left
 | 
			
		||||
  },
 | 
			
		||||
  cubeCorner: {
 | 
			
		||||
    type: String,
 | 
			
		||||
    default: 'bl',
 | 
			
		||||
    validator: (value, props) => {
 | 
			
		||||
      return ['bl', 'br'].includes(value);
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="container-border">
 | 
			
		||||
    <Corner
 | 
			
		||||
      v-if="corner.indexOf('tl') !== -1"
 | 
			
		||||
      position="top-left"
 | 
			
		||||
      key="top-left"
 | 
			
		||||
    />
 | 
			
		||||
    <Corner
 | 
			
		||||
      v-if="corner.indexOf('tr') !== -1"
 | 
			
		||||
      position="top-right"
 | 
			
		||||
      key="top-right"
 | 
			
		||||
    />
 | 
			
		||||
    <Corner
 | 
			
		||||
      v-if="corner.indexOf('bl') !== -1"
 | 
			
		||||
      position="bottom-left"
 | 
			
		||||
      key="bottom-left"
 | 
			
		||||
    />
 | 
			
		||||
    <Corner
 | 
			
		||||
      v-if="corner.indexOf('br') !== -1"
 | 
			
		||||
      position="bottom-right"
 | 
			
		||||
      key="bottom-right"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    <div class="container">
 | 
			
		||||
      <div class="cube" :class="[`cube-${cubeCorner}`]"></div>
 | 
			
		||||
      <div class="container-header">
 | 
			
		||||
        <Icon :name="icon" />
 | 
			
		||||
        <span>{{ title }}</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="container-body">
 | 
			
		||||
        <slot />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.container-border {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cube {
 | 
			
		||||
  width: 26px;
 | 
			
		||||
  height: 26px;
 | 
			
		||||
  background: #1f8fff;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  z-index: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cube-bl {
 | 
			
		||||
  transform: rotate(45deg);
 | 
			
		||||
  bottom: -13px;
 | 
			
		||||
  left: -13px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cube-br {
 | 
			
		||||
  transform: rotate(45deg);
 | 
			
		||||
  bottom: -13px;
 | 
			
		||||
  right: -13px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.container {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.container-header {
 | 
			
		||||
  background: #006acd66;
 | 
			
		||||
  backdrop-filter: blur(2px);
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  gap: 12px;
 | 
			
		||||
  padding: 8px 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.container-body {
 | 
			
		||||
  background: #ffffff33;
 | 
			
		||||
  backdrop-filter: blur(1px);
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  padding: 20px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										62
									
								
								src/components/Base/Corner.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,62 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, computed } from 'vue';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  position: {
 | 
			
		||||
    type: String,
 | 
			
		||||
    default: 'bottom-left',
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const styles = computed(() => {
 | 
			
		||||
  switch (props.position) {
 | 
			
		||||
    case 'top-left':
 | 
			
		||||
      return {
 | 
			
		||||
        transform: 'rotate(90deg)',
 | 
			
		||||
        top: 0,
 | 
			
		||||
        left: 0,
 | 
			
		||||
        bottom: 'unset',
 | 
			
		||||
        right: 'unset',
 | 
			
		||||
      };
 | 
			
		||||
    case 'top-right':
 | 
			
		||||
      return {
 | 
			
		||||
        transform: 'rotate(180deg)',
 | 
			
		||||
        top: 0,
 | 
			
		||||
        left: 'unset',
 | 
			
		||||
        bottom: 'unset',
 | 
			
		||||
        right: 0,
 | 
			
		||||
      };
 | 
			
		||||
    case 'bottom-left':
 | 
			
		||||
      return {
 | 
			
		||||
        transform: 'rotate(0deg)',
 | 
			
		||||
        bottom: 0,
 | 
			
		||||
        left: 0,
 | 
			
		||||
        right: 'unset',
 | 
			
		||||
        top: 'unset',
 | 
			
		||||
      };
 | 
			
		||||
    case 'bottom-right':
 | 
			
		||||
      return {
 | 
			
		||||
        transform: 'rotate(-90deg)',
 | 
			
		||||
        top: 'unset',
 | 
			
		||||
        left: 'unset',
 | 
			
		||||
        bottom: 0,
 | 
			
		||||
        right: 0,
 | 
			
		||||
      };
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="corner" :style="styles"></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.corner {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 16px;
 | 
			
		||||
  height: 16px;
 | 
			
		||||
  border-left: 2px solid #0078e4;
 | 
			
		||||
  border-bottom: 2px solid #0078e4;
 | 
			
		||||
  z-index: 2;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										37
									
								
								src/components/Base/Header.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,37 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, computed } from 'vue';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <header class="header">
 | 
			
		||||
    <div>
 | 
			
		||||
      <Icon htmlRole="logo" icon="logo" />
 | 
			
		||||
      <h1 class="header__title">郴州旗滨光伏光电玻璃有限公司</h1>
 | 
			
		||||
    </div>
 | 
			
		||||
  </header>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.header {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: 90px;
 | 
			
		||||
  background: url(../../assets/header-bg@2x.png) 100% / 100% no-repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.header > div {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  margin: 0 auto;
 | 
			
		||||
  /** width: 520px; **/
 | 
			
		||||
  width: 480px;
 | 
			
		||||
  top: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.header__title {
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  letter-spacing: 2px;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  user-select: none;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										51
									
								
								src/components/Base/Icon.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,51 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
// import icons
 | 
			
		||||
import checkIcon from '../../assets/svg/check.svg';
 | 
			
		||||
import cubeIcon from '../../assets/svg/cube.svg';
 | 
			
		||||
import cube2Icon from '../../assets/svg/cube-twice.svg';
 | 
			
		||||
import stackIcon from '../../assets/svg/stack.svg';
 | 
			
		||||
 | 
			
		||||
import { ref, computed } from 'vue';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  name: {
 | 
			
		||||
    type: String,
 | 
			
		||||
    default: 'icon',
 | 
			
		||||
  },
 | 
			
		||||
  htmlRole: {
 | 
			
		||||
    type: String,
 | 
			
		||||
    default: 'icon', // 'icon' | 'logo'
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const icon = computed(() => {
 | 
			
		||||
  switch (props.name) {
 | 
			
		||||
    case 'icon':
 | 
			
		||||
    case 'cube':
 | 
			
		||||
      return cubeIcon;
 | 
			
		||||
    case 'cube-2':
 | 
			
		||||
      return cube2Icon;
 | 
			
		||||
    case 'stack':
 | 
			
		||||
      return stackIcon;
 | 
			
		||||
    case 'check':
 | 
			
		||||
      return checkIcon;
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="icon">
 | 
			
		||||
    <img :src="icon" :class="icon" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.icon {
 | 
			
		||||
  height: 16px;
 | 
			
		||||
  width: 16px;
 | 
			
		||||
  background: #fff3;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										54
									
								
								src/components/Dribbble/Dialog.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,54 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import './style.css';
 | 
			
		||||
import { Close } from '@element-plus/icons-vue';
 | 
			
		||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
 | 
			
		||||
 | 
			
		||||
const contentVisible = ref(false);
 | 
			
		||||
const emit = defineEmits(['close']);
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    contentVisible.value = true;
 | 
			
		||||
  }, 100);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onBeforeUnmount(() => {});
 | 
			
		||||
 | 
			
		||||
function close() {
 | 
			
		||||
  contentVisible.value = false;
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    emit('close');
 | 
			
		||||
  }, 150);
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="modal">
 | 
			
		||||
    <div class="dribbble-dialog pop-out" :class="{ visible: contentVisible }">
 | 
			
		||||
      <div class="logo"></div>
 | 
			
		||||
      <div class="left"></div>
 | 
			
		||||
      <div class="right"></div>
 | 
			
		||||
      <div class="content-text">
 | 
			
		||||
        <p>Advance your career with a</p>
 | 
			
		||||
        <p>Professional Diploma in UX Design</p>
 | 
			
		||||
        <button>Learn More</button>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-button
 | 
			
		||||
        :icon="Close"
 | 
			
		||||
        size="small"
 | 
			
		||||
        circle
 | 
			
		||||
        style="
 | 
			
		||||
          background: #eeeb;
 | 
			
		||||
          color: #000;
 | 
			
		||||
          border: none;
 | 
			
		||||
          position: absolute;
 | 
			
		||||
          top: -3px;
 | 
			
		||||
          right: 8px;
 | 
			
		||||
          z-index: -10;
 | 
			
		||||
        "
 | 
			
		||||
        @click="close"
 | 
			
		||||
      ></el-button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
i
 | 
			
		||||
							
								
								
									
										105
									
								
								src/components/Dribbble/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,105 @@
 | 
			
		||||
.modal {
 | 
			
		||||
  background: #0003;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  display: grid;
 | 
			
		||||
  place-items: center;
 | 
			
		||||
  color: #000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dribbble-dialog {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  margin: 12px;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  border-radius: 18px;
 | 
			
		||||
  box-shadow: 0 0 32px 2px #0001;
 | 
			
		||||
  overflow-x: hidden;
 | 
			
		||||
  height: auto;
 | 
			
		||||
  padding: 20px;
 | 
			
		||||
  transition: all 0.1s cubic-bezier(0, 0.48, 0, 1.18);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.content-text {
 | 
			
		||||
  margin: 56px 56px 32px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-weight: 700;
 | 
			
		||||
  line-height: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
p {
 | 
			
		||||
  margin: 10px 0;
 | 
			
		||||
  user-select: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button {
 | 
			
		||||
  border: none;
 | 
			
		||||
  outline: none;
 | 
			
		||||
  appearance: none;
 | 
			
		||||
  padding: 12px 24px;
 | 
			
		||||
  border-radius: 20px;
 | 
			
		||||
  background: #000;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  margin-top: 12px;
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  font-weight: 700;
 | 
			
		||||
  letter-spacing: 0.5px;
 | 
			
		||||
  text-transform: uppercase;
 | 
			
		||||
  transition: all 0.1s ease-out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:hover {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  background: #000b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.logo {
 | 
			
		||||
  width: 128px;
 | 
			
		||||
  height: 40px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 20px;
 | 
			
		||||
  left: 20px;
 | 
			
		||||
  background: url(../../assets/logo@2x.png) center / contain no-repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.left {
 | 
			
		||||
  width: 160px;
 | 
			
		||||
  height: 80px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  background: url(../../assets/leftcorner@2x.png) center / 100% 100% no-repeat;
 | 
			
		||||
  z-index: -100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.right {
 | 
			
		||||
  width: 100px;
 | 
			
		||||
  height: 118px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  z-index: -100;
 | 
			
		||||
  top: -2px;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  background: url(../../assets/rightcorner@2x.png) center / 100% 100% no-repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.fade-in {
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  transform: translateY(-56px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.fade-in.visible {
 | 
			
		||||
  transform: translateY(0);
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pop-out {
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  transform: scale(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pop-out.visible {
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
  transform: scale(1);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								src/components/HourChart.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,52 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, onMounted } from 'vue';
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
import Container from './Base/Container.vue';
 | 
			
		||||
 | 
			
		||||
const chartChart = ref(null);
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  chartChart.value.classList.add('h-full');
 | 
			
		||||
  const mc = echarts.init(chartChart.value);
 | 
			
		||||
  mc.setOption({
 | 
			
		||||
    grid: {
 | 
			
		||||
      top: 24,
 | 
			
		||||
      bottom: 24,
 | 
			
		||||
      left: 24,
 | 
			
		||||
      right: 24,
 | 
			
		||||
    },
 | 
			
		||||
    tooltip: {},
 | 
			
		||||
    xAxis: {
 | 
			
		||||
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
 | 
			
		||||
    },
 | 
			
		||||
    yAxis: {},
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
        name: '销量',
 | 
			
		||||
        type: 'bar',
 | 
			
		||||
        data: [5, 20, 36, 10, 10, 20],
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Container class="chart" title="小时数据" icon="cube">
 | 
			
		||||
    <div ref="chartChart" class="chart-chart"></div>
 | 
			
		||||
  </Container>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.chart {
 | 
			
		||||
  height: 300px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart-inner {
 | 
			
		||||
  background: #0f0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart-chart {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										55
									
								
								src/components/NavMenu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,55 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
const emit = defineEmits(['change']);
 | 
			
		||||
const handleClick = (page) => {
 | 
			
		||||
  emit('change', page);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <nav class="nav-menu">
 | 
			
		||||
    <ul>
 | 
			
		||||
      <li><button @click="(e) => handleClick('3d')">三维界面</button></li>
 | 
			
		||||
      <li><button @click="(e) => handleClick('data')">数据界面</button></li>
 | 
			
		||||
      <li><button @click="(e) => handleClick('realtime')">实时数据</button></li>
 | 
			
		||||
      <li><button @click="(e) => handleClick('alert')">报警列表</button></li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <button @click="(e) => handleClick('announcement')">公告页面</button>
 | 
			
		||||
      </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
  </nav>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.nav-menu {
 | 
			
		||||
  width: 480px;
 | 
			
		||||
  padding: 12px;
 | 
			
		||||
  background: #0006;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  /** 
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  top: 45%;
 | 
			
		||||
  left: 10px;
 | 
			
		||||
  */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button {
 | 
			
		||||
  appearance: none;
 | 
			
		||||
  border: none;
 | 
			
		||||
  outline: none;
 | 
			
		||||
  background: #7777;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:hover {
 | 
			
		||||
  background: #ccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ul,
 | 
			
		||||
li {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  list-style: none;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										56
									
								
								src/components/RealtimeChart.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,56 @@
 | 
			
		||||
<!-- 货物情况 -->
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, onMounted } from 'vue';
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
import Container from './Base/Container.vue';
 | 
			
		||||
 | 
			
		||||
const cargoChart = ref(null);
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  cargoChart.value.classList.add('h-full');
 | 
			
		||||
  const mc = echarts.init(cargoChart.value);
 | 
			
		||||
  mc.setOption({
 | 
			
		||||
    grid: {
 | 
			
		||||
      top: 24,
 | 
			
		||||
      bottom: 24,
 | 
			
		||||
      left: 24,
 | 
			
		||||
      right: 24,
 | 
			
		||||
    },
 | 
			
		||||
    tooltip: {},
 | 
			
		||||
    xAxis: {
 | 
			
		||||
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
 | 
			
		||||
    },
 | 
			
		||||
    yAxis: {},
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
        name: '销量',
 | 
			
		||||
        type: 'bar',
 | 
			
		||||
        data: [5, 20, 36, 10, 10, 20],
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Container class="cargo" title="实时数据" icon="cube">
 | 
			
		||||
    <div ref="cargoChart" class="cargo-chart"></div>
 | 
			
		||||
  </Container>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.cargo {
 | 
			
		||||
  height: 640px;
 | 
			
		||||
  width: 80%;
 | 
			
		||||
  align-self: self-end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cargo-inner {
 | 
			
		||||
  background: #0f0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cargo-chart {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										49
									
								
								src/components/RealtimeTable.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,49 @@
 | 
			
		||||
<!-- 实时数据表格 -->
 | 
			
		||||
<script setup>
 | 
			
		||||
 | 
			
		||||
const tableData = [
 | 
			
		||||
    { productLine: '00A', mbt: '---', mbb: '---', dkt: '---', dkb: '---', dmt: '---', dmb: '---', syt: '---', syb: '---', ght: '---', ghb: '---', gh1: '---', gh2: '---', bzt: '---', bzb: '---' },
 | 
			
		||||
    { productLine: '00B', mbt: '---', mbb: '---', dkt: '---', dkb: '---', dmt: '---', dmb: '---', syt: '---', syb: '---', ght: '---', ghb: '---', gh1: '---', gh2: '---', bzt: '---', bzb: '---' },
 | 
			
		||||
    { productLine: '00C', mbt: '---', mbb: '---', dkt: '---', dkb: '---', dmt: '---', dmb: '---', syt: '---', syb: '---', ght: '---', ghb: '---', gh1: '---', gh2: '---', bzt: '---', bzb: '---' },
 | 
			
		||||
    { productLine: '00D', mbt: '---', mbb: '---', dkt: '---', dkb: '---', dmt: '---', dmb: '---', syt: '---', syb: '---', ght: '---', ghb: '---', gh1: '---', gh2: '---', bzt: '---', bzb: '---' },
 | 
			
		||||
    { productLine: '00E', mbt: '---', mbb: '---', dkt: '---', dkb: '---', dmt: '---', dmb: '---', syt: '---', syb: '---', ght: '---', ghb: '---', gh1: '---', gh2: '---', bzt: '---', bzb: '---' },
 | 
			
		||||
    { productLine: '00F', mbt: '---', mbb: '---', dkt: '---', dkb: '---', dmt: '---', dmb: '---', syt: '---', syb: '---', ght: '---', ghb: '---', gh1: '---', gh2: '---', bzt: '---', bzb: '---' },
 | 
			
		||||
]
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="realtime-table">
 | 
			
		||||
        <el-table class="dark-table" :data="tableData" :show-overflow-tooltip="true" row-class-name="dark-row"
 | 
			
		||||
            header-row-class-name="dark-header">
 | 
			
		||||
            <el-table-column prop="productLine" label="产线"></el-table-column>
 | 
			
		||||
            <el-table-column prop="mbt" label="磨边上"></el-table-column>
 | 
			
		||||
            <el-table-column prop="mbb" label="磨边下"></el-table-column>
 | 
			
		||||
            <el-table-column prop="dkt" label="打孔上"></el-table-column>
 | 
			
		||||
            <el-table-column prop="dkb" label="打孔下"></el-table-column>
 | 
			
		||||
            <el-table-column prop="dmt" label="镀膜上"></el-table-column>
 | 
			
		||||
            <el-table-column prop="dmb" label="镀膜下"></el-table-column>
 | 
			
		||||
            <el-table-column prop="syt" label="丝印上"></el-table-column>
 | 
			
		||||
            <el-table-column prop="syb" label="丝印下"></el-table-column>
 | 
			
		||||
            <el-table-column prop="ght" label="固化上"></el-table-column>
 | 
			
		||||
            <el-table-column prop="ghb" label="固化下"></el-table-column>
 | 
			
		||||
            <el-table-column prop="gh1" label="钢化上"></el-table-column>
 | 
			
		||||
            <el-table-column prop="gh2" label="钢化下"></el-table-column>
 | 
			
		||||
            <el-table-column prop="bzt" label="包装上"></el-table-column>
 | 
			
		||||
            <el-table-column prop="bzb" label="包装下"></el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped> 
 | 
			
		||||
 | 
			
		||||
.realtime-table {
 | 
			
		||||
     background: #00f3;
 | 
			
		||||
     height: 240px;
 | 
			
		||||
     width: 80%;
 | 
			
		||||
     align-self: self-start;
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
 .dark-table {
 | 
			
		||||
    height: 100%;
 | 
			
		||||
 }
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										65
									
								
								src/components/Slider.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,65 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, watch, onMounted } from 'vue';
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['size-change']);
 | 
			
		||||
const size = ref(100);
 | 
			
		||||
const slider = ref(null);
 | 
			
		||||
 | 
			
		||||
// watchers
 | 
			
		||||
watch(size, (value) => {
 | 
			
		||||
  if (value == null) return;
 | 
			
		||||
  emit('size-change', value);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// handlers
 | 
			
		||||
function keydownHandler(e) {
 | 
			
		||||
  if (e.shiftKey && e.key === 'L') {
 | 
			
		||||
    if (slider.value) {
 | 
			
		||||
      slider.value.classList.toggle('show');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// hooks
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  document.addEventListener('keydown', keydownHandler);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div ref="slider" class="slider">
 | 
			
		||||
    <input type="range" min="0" max="100" v-model="size" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.slider {
 | 
			
		||||
  height: 5vh;
 | 
			
		||||
  width: 20vw;
 | 
			
		||||
  border-radius: 88px;
 | 
			
		||||
  box-shadow: 0 0 68px 8px rgba(0, 0, 0, 0.3);
 | 
			
		||||
  padding: 32px;
 | 
			
		||||
  display: grid;
 | 
			
		||||
  place-items: center;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  z-index: 1000;
 | 
			
		||||
  bottom: -5vh;
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  left: 50%;
 | 
			
		||||
  transform: translateX(-50%);
 | 
			
		||||
  transition: opacity 0.3s ease-out, bottom 0.3s ease-out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.slider input {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  transform: translateY(-7px);
 | 
			
		||||
  color: #0b58ff;
 | 
			
		||||
  background: #fcc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.slider.show {
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
  bottom: 64px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										52
									
								
								src/components/TeamChartDay.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,52 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, onMounted } from 'vue';
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
import Container from './Base/Container.vue';
 | 
			
		||||
 | 
			
		||||
const chartChart = ref(null);
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  chartChart.value.classList.add('h-full');
 | 
			
		||||
  const mc = echarts.init(chartChart.value);
 | 
			
		||||
  mc.setOption({
 | 
			
		||||
    grid: {
 | 
			
		||||
      top: 24,
 | 
			
		||||
      bottom: 24,
 | 
			
		||||
      left: 24,
 | 
			
		||||
      right: 24,
 | 
			
		||||
    },
 | 
			
		||||
    tooltip: {},
 | 
			
		||||
    xAxis: {
 | 
			
		||||
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
 | 
			
		||||
    },
 | 
			
		||||
    yAxis: {},
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
        name: '销量',
 | 
			
		||||
        type: 'bar',
 | 
			
		||||
        data: [5, 20, 36, 10, 10, 20],
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Container class="chart" title="本日班组情况" icon="cube">
 | 
			
		||||
    <div ref="chartChart" class="chart-chart"></div>
 | 
			
		||||
  </Container>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.chart {
 | 
			
		||||
  height: 300px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart-inner {
 | 
			
		||||
  background: #0f0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart-chart {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										52
									
								
								src/components/TeamChartMonth.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,52 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, onMounted } from 'vue';
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
import Container from './Base/Container.vue';
 | 
			
		||||
 | 
			
		||||
const chartChart = ref(null);
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  chartChart.value.classList.add('h-full');
 | 
			
		||||
  const mc = echarts.init(chartChart.value);
 | 
			
		||||
  mc.setOption({
 | 
			
		||||
    grid: {
 | 
			
		||||
      top: 24,
 | 
			
		||||
      bottom: 24,
 | 
			
		||||
      left: 24,
 | 
			
		||||
      right: 24,
 | 
			
		||||
    },
 | 
			
		||||
    tooltip: {},
 | 
			
		||||
    xAxis: {
 | 
			
		||||
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
 | 
			
		||||
    },
 | 
			
		||||
    yAxis: {},
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
        name: '销量',
 | 
			
		||||
        type: 'bar',
 | 
			
		||||
        data: [5, 20, 36, 10, 10, 20],
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Container class="chart" title="本月班组情况" icon="cube">
 | 
			
		||||
    <div ref="chartChart" class="chart-chart"></div>
 | 
			
		||||
  </Container>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.chart {
 | 
			
		||||
  height: 300px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart-inner {
 | 
			
		||||
  background: #0f0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart-chart {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										21
									
								
								src/components/Tools.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,21 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, watch, onMounted } from 'vue';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="tools">
 | 
			
		||||
    <button>Home</button>
 | 
			
		||||
    <button>Settings</button>
 | 
			
		||||
    <button>AutoScroll</button>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.tools {
 | 
			
		||||
  background: #00f;
 | 
			
		||||
  padding: 8px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 24px;
 | 
			
		||||
  left: 24px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										11
									
								
								src/components/data.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "code": 0,
 | 
			
		||||
  "data": [
 | 
			
		||||
    { "date": "2023-01-01", "检测项目": "光刻胶&显影", "光刻胶残留": "1" },
 | 
			
		||||
    { "date": "2023-01-01", "检测项目": "激光一", "磨面擦伤": "1" },
 | 
			
		||||
    { "date": "2023-01-01", "检测项目": "激光二", "刻线宽度不良": "1" },
 | 
			
		||||
    { "date": "2023-01-02", "检测项目": "光刻胶&显影", "光刻胶残留": "2" },
 | 
			
		||||
    { "date": "2023-01-02", "检测项目": "激光一", "刻线宽度不良": "2" },
 | 
			
		||||
    { "date": "2023-01-03", "检测项目": "激光二", "擦伤": "3" }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								src/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,16 @@
 | 
			
		||||
import { createApp } from 'vue';
 | 
			
		||||
import { createPinia } from 'pinia'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import './style.css';
 | 
			
		||||
import ElementPlus from 'element-plus';
 | 
			
		||||
import 'element-plus/dist/index.css';
 | 
			
		||||
import Vue3Marquee from 'vue3-marquee';
 | 
			
		||||
import App from './App.vue';
 | 
			
		||||
const pinia = createPinia()
 | 
			
		||||
 | 
			
		||||
const app = createApp(App);
 | 
			
		||||
app.use(pinia);
 | 
			
		||||
app.use(ElementPlus);
 | 
			
		||||
app.use(Vue3Marquee, { name: 'ScrollText' });
 | 
			
		||||
app.mount('#app');
 | 
			
		||||
							
								
								
									
										1
									
								
								src/pages/3D.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
			
		||||
<!-- 三维页面 -->
 | 
			
		||||
							
								
								
									
										140
									
								
								src/pages/AlertListPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,140 @@
 | 
			
		||||
<!-- 报警列表页面 -->
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
 | 
			
		||||
const tableData = [
 | 
			
		||||
    { id: 1, eqName: '设备00A', eqIndex: '1', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 2, eqName: '设备00B', eqIndex: '2', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 3, eqName: '设备00C', eqIndex: '3', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 4, eqName: '设备00D', eqIndex: '4', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 5, eqName: '设备00E', eqIndex: '5', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 6, eqName: '设备00F', eqIndex: '6', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 7, eqName: '设备00G', eqIndex: '7', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 1, eqName: '设备00A', eqIndex: '1', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 2, eqName: '设备00B', eqIndex: '2', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 3, eqName: '设备00C', eqIndex: '3', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 4, eqName: '设备00D', eqIndex: '4', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 5, eqName: '设备00E', eqIndex: '5', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 6, eqName: '设备00F', eqIndex: '6', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 7, eqName: '设备00G', eqIndex: '7', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 1, eqName: '设备00A', eqIndex: '1', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 2, eqName: '设备00B', eqIndex: '2', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 3, eqName: '设备00C', eqIndex: '3', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 4, eqName: '设备00D', eqIndex: '4', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 5, eqName: '设备00E', eqIndex: '5', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 6, eqName: '设备00F', eqIndex: '6', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 7, eqName: '设备00G', eqIndex: '7', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 1, eqName: '设备00A', eqIndex: '1', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 2, eqName: '设备00B', eqIndex: '2', alarmGrade: 1, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 3, eqName: '设备00C', eqIndex: '3', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 4, eqName: '设备00D', eqIndex: '4', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 5, eqName: '设备00E', eqIndex: '5', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 6, eqName: '设备00F', eqIndex: '6', alarmGrade: 3, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
    { id: 7, eqName: '设备00G', eqIndex: '7', alarmGrade: 2, alarmDetail: 'lorem sdf fkj', position: 'x,y' },
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="alert-list-page">
 | 
			
		||||
        <div class="alert-list">
 | 
			
		||||
            <div class="alert-list__table" style="">
 | 
			
		||||
                <el-table class="dark-table" :data="tableData" :show-overflow-tooltip="true" row-class-name="dark-row"
 | 
			
		||||
                    header-row-class-name="dark-header">
 | 
			
		||||
                    <el-table-column prop="eqName" label="设备名" width="90"></el-table-column>
 | 
			
		||||
                    <el-table-column prop="eqIndex" label="序号" width="60"></el-table-column>
 | 
			
		||||
                    <el-table-column prop="alarmGrade" label="报警等级" width="90"></el-table-column>
 | 
			
		||||
                    <el-table-column prop="alarmDetail" label="报警细节" width="144"></el-table-column>
 | 
			
		||||
                    <el-table-column prop="position" label="定位"></el-table-column>
 | 
			
		||||
                </el-table>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button class="alert-btn">忽略</button>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.dark-table {
 | 
			
		||||
    /* height: 72vh; */
 | 
			
		||||
    /* height: 72%; */
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    background: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark-row {
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    background: #005eff25 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark-row>td.el-table__cell {
 | 
			
		||||
    border: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark-row:hover>td.el-table__cell {
 | 
			
		||||
    background-color: #005effaa !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark-header {
 | 
			
		||||
    background-color: transparent !important;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark-header>th.el-table__cell.is-leaf {
 | 
			
		||||
    border-bottom: none;
 | 
			
		||||
    background-color: #005eff95 !important;
 | 
			
		||||
    font-weight: 400;
 | 
			
		||||
    letter-spacing: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark-header>th.el-table__cell {
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.alert-list-page {
 | 
			
		||||
    flex: 1;
 | 
			
		||||
    position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.alert-list {
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    width: 480px;
 | 
			
		||||
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.alert-list__table {
 | 
			
		||||
    height: calc(100% - 72px);
 | 
			
		||||
    background: linear-gradient(to right, transparent, #0ba6ff80);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.alert-list__table>>>.el-table__inner-wrapper::before {
 | 
			
		||||
    background: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button {
 | 
			
		||||
    appearance: none;
 | 
			
		||||
    outline: none;
 | 
			
		||||
    border: none;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.alert-btn {
 | 
			
		||||
    height: 72px;
 | 
			
		||||
    background: #0f04;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    font-size: 32px;
 | 
			
		||||
    line-height: 1;
 | 
			
		||||
    letter-spacing: 2px;
 | 
			
		||||
    transition: all .2s ease-out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.alert-btn:hover {
 | 
			
		||||
    background: #0f08;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										68
									
								
								src/pages/AnnouncementPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,68 @@
 | 
			
		||||
<!-- 公告页面 -->
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
const emit = defineEmits(['home']);
 | 
			
		||||
const content = ref('公告加载中...');
 | 
			
		||||
 | 
			
		||||
const handleClose = () => {
 | 
			
		||||
  emit('home');
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="announcement-page">
 | 
			
		||||
    <h1 class="announcement-title">公告栏</h1>
 | 
			
		||||
    <main class="announcement-content">
 | 
			
		||||
      <ScrollText :vertical="true" :duration="10" :pause-on-hover="true">
 | 
			
		||||
        {{ content }}
 | 
			
		||||
      </ScrollText>
 | 
			
		||||
    </main>
 | 
			
		||||
    <div class="announcement-footer">
 | 
			
		||||
      <button
 | 
			
		||||
        style="position: absolute; left: 0; bottom: 10px"
 | 
			
		||||
        @click="handleClose"
 | 
			
		||||
      >
 | 
			
		||||
        返回
 | 
			
		||||
      </button>
 | 
			
		||||
      <ScrollText> 数据加载异常 </ScrollText>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.announcement-page {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  background: #000;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  color: #f00;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.announcement-title {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 72px;
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
  letter-spacing: 2px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.announcement-content {
 | 
			
		||||
  /* background: #ccc3; */
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  padding: 8px 80px;
 | 
			
		||||
  font-size: 72px;
 | 
			
		||||
  font-family: serif;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.announcement-footer {
 | 
			
		||||
  height: 128px;
 | 
			
		||||
  /* background: #ccc1; */
 | 
			
		||||
  font-size: 64px;
 | 
			
		||||
  padding: 0 80px;
 | 
			
		||||
  line-height: 128px;
 | 
			
		||||
  font-family: sans-serif;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										43
									
								
								src/pages/DataPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,43 @@
 | 
			
		||||
<!-- 实时数据页面 -->
 | 
			
		||||
<script setup>
 | 
			
		||||
import HourChart from "../components/HourChart.vue";
 | 
			
		||||
import TeamChartDay from "../components/TeamChartDay.vue";
 | 
			
		||||
import TeamChartMonth from "../components/TeamChartMonth.vue";
 | 
			
		||||
 | 
			
		||||
import { useWsStore } from '../store'
 | 
			
		||||
 | 
			
		||||
const store = useWsStore();
 | 
			
		||||
 | 
			
		||||
console.log('store', store.data1.test);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="data-page">
 | 
			
		||||
    <div class="data-list">
 | 
			
		||||
      <HourChart />
 | 
			
		||||
      <TeamChartDay />
 | 
			
		||||
      <TeamChartMonth />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.data-page {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.data-list {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 480px;
 | 
			
		||||
  background: #ccc3;
 | 
			
		||||
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										21
									
								
								src/pages/RealtimePage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,21 @@
 | 
			
		||||
<!-- 实时数据页面 -->
 | 
			
		||||
<script setup>
 | 
			
		||||
import Chart from '../components/RealtimeChart.vue';
 | 
			
		||||
import RealtimeTable from '../components/RealtimeTable.vue';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="realtime-page">
 | 
			
		||||
    <Chart />
 | 
			
		||||
    <RealtimeTable />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.realtime-page {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  display: grid;
 | 
			
		||||
  place-items: center;
 | 
			
		||||
  gap: 24px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										41
									
								
								src/store/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,41 @@
 | 
			
		||||
import { defineStore } from "pinia";
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export const useWsStore = defineStore("wsData", () => {
 | 
			
		||||
  const data1 = ref({ test: 'hello world'});
 | 
			
		||||
  const data2 = ref({});
 | 
			
		||||
  const data3 = ref({});
 | 
			
		||||
 | 
			
		||||
  function updateData(category, data) {
 | 
			
		||||
    console.log('update', data)
 | 
			
		||||
    switch (category) {
 | 
			
		||||
      case "1":
 | 
			
		||||
        data1.value = data;
 | 
			
		||||
        break;
 | 
			
		||||
      case "2":
 | 
			
		||||
        data2.value = data;
 | 
			
		||||
        break;
 | 
			
		||||
      case "3":
 | 
			
		||||
        data3.value = data;
 | 
			
		||||
      default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return { data1, data2, data3, updateData };
 | 
			
		||||
});
 | 
			
		||||
// export const useWsStore = defineStore('wsData', {
 | 
			
		||||
//     state: () => ({
 | 
			
		||||
//         data1: {
 | 
			
		||||
//             test: 'hello world'
 | 
			
		||||
//         },
 | 
			
		||||
//         data2: null,
 | 
			
		||||
//         data3: null,
 | 
			
		||||
//     }),
 | 
			
		||||
//     actions: {
 | 
			
		||||
//         updateData(category, data) {
 | 
			
		||||
//             this[category] = data
 | 
			
		||||
//         }
 | 
			
		||||
//     }
 | 
			
		||||
// })
 | 
			
		||||
							
								
								
									
										4
									
								
								src/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,4 @@
 | 
			
		||||
* {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/utils/connects.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
			
		||||
import Client from './ws'
 | 
			
		||||
 | 
			
		||||
const uid_list = [
 | 
			
		||||
//       磨边    丝印   钢化    包装
 | 
			
		||||
// 一线    
 | 
			
		||||
        '1-1', '1-2', '1-3', '1-4',
 | 
			
		||||
// 二线 
 | 
			
		||||
        '2-1', '2-2', '2-3', '2-4',
 | 
			
		||||
// 三线 
 | 
			
		||||
        '3-1', '3-2', '3-3', '3-4',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
const url = 'wss://192.168.1.101:8082/QbMonitoring/websocket/'
 | 
			
		||||
 | 
			
		||||
uid_list.forEach(uid => {
 | 
			
		||||
    new Client({
 | 
			
		||||
        url: url + uid,
 | 
			
		||||
        name: '/' + uid
 | 
			
		||||
    }, message => {
 | 
			
		||||
        console.log('message', message);
 | 
			
		||||
    })
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										95
									
								
								src/utils/ws.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,95 @@
 | 
			
		||||
export default class XClient {
 | 
			
		||||
  url = "";
 | 
			
		||||
  name = "";
 | 
			
		||||
  ws = null;
 | 
			
		||||
  timeout = 1000 * 5;
 | 
			
		||||
  heartbeatDelay = 1000 * 60 * 3;
 | 
			
		||||
  reconnectCount = 0;
 | 
			
		||||
  onmessage = null;
 | 
			
		||||
  hb = 0;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    config,
 | 
			
		||||
    onmessage
 | 
			
		||||
  ) {
 | 
			
		||||
    this.url = config.url;
 | 
			
		||||
    this.name = config.name;
 | 
			
		||||
    this.ws = new WebSocket(config.url);
 | 
			
		||||
    this.timeout = config.timeout || 1000 * 5;
 | 
			
		||||
 | 
			
		||||
    this.ws.onopen = () => {
 | 
			
		||||
      console.log(`[*] ${this.name} 初始化连接成功`);
 | 
			
		||||
      this.hb = this.heartbeat();
 | 
			
		||||
    };
 | 
			
		||||
    this.onmessage = onmessage;
 | 
			
		||||
    this.ws.onmessage = onmessage;
 | 
			
		||||
    this.ws.onerror = (err) => {
 | 
			
		||||
      console.log(`[*] ${this.name} 连接错误`, err);
 | 
			
		||||
      this.tryReconnect();
 | 
			
		||||
    };
 | 
			
		||||
    this.ws.onclose = (e) => {
 | 
			
		||||
      console.log(`[*] ${this.name} 连接关闭`);
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  heartbeat() {
 | 
			
		||||
    if (this.hb) clearInterval(this.hb);
 | 
			
		||||
    return setInterval(() => {
 | 
			
		||||
      console.log(`${this.name} ping...`);
 | 
			
		||||
      if (this.ws.readyState == WebSocket.OPEN) {
 | 
			
		||||
        this.ws.send("ping");
 | 
			
		||||
      } else {
 | 
			
		||||
        clearInterval(this.hb);
 | 
			
		||||
        this.tryReconnect();
 | 
			
		||||
      }
 | 
			
		||||
    }, this.heartbeatDelay);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  tryReconnect() {
 | 
			
		||||
    console.log(`[*] ${this.name} 重连中,已尝试:`, this.reconnectCount, "次");
 | 
			
		||||
    setTimeout(
 | 
			
		||||
      () => {
 | 
			
		||||
        if (this.ws.readyState === WebSocket.OPEN) {
 | 
			
		||||
          this.reconnectCount = 0;
 | 
			
		||||
          console.log(`[*] ${this.name} 已恢复连接,取消重连`);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        this.reconnectCount++;
 | 
			
		||||
        this.ws = new WebSocket(this.url);
 | 
			
		||||
        this.ws.onopen = () => {
 | 
			
		||||
          console.log(`[*] ${this.name} 重连成功`);
 | 
			
		||||
          this.reconnectCount = 0;
 | 
			
		||||
          this.hb = this.heartbeat();
 | 
			
		||||
        };
 | 
			
		||||
        this.ws.onmessage = this.onmessage;
 | 
			
		||||
        this.ws.onerror = (err) => {
 | 
			
		||||
          console.log(`[*] ${this.name} 重连出错`);
 | 
			
		||||
          this.tryReconnect();
 | 
			
		||||
        };
 | 
			
		||||
        this.ws.onclose = (e) => {
 | 
			
		||||
          console.log(`[*] ${this.name} 重连连接关闭`);
 | 
			
		||||
        };
 | 
			
		||||
      },
 | 
			
		||||
      this.reconnectCount == 0 ? 0 : this.timeout
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  logStatus() {
 | 
			
		||||
    console.log(
 | 
			
		||||
      `[*] ${this.name} 重连状态: 连接中`,
 | 
			
		||||
      this.ws.readyState == WebSocket.CONNECTING
 | 
			
		||||
    );
 | 
			
		||||
    console.log(
 | 
			
		||||
      `[*] ${this.name} 重连状态: 已连接`,
 | 
			
		||||
      this.ws.readyState == WebSocket.OPEN
 | 
			
		||||
    );
 | 
			
		||||
    console.log(
 | 
			
		||||
      `[*] ${this.name} 重连状态: 关闭中`,
 | 
			
		||||
      this.ws.readyState == WebSocket.CLOSING
 | 
			
		||||
    );
 | 
			
		||||
    console.log(
 | 
			
		||||
      `[*] ${this.name} 重连状态: 关闭`,
 | 
			
		||||
      this.ws.readyState == WebSocket.CLOSED
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vite.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
import { defineConfig } from 'vite'
 | 
			
		||||
import vue from '@vitejs/plugin-vue'
 | 
			
		||||
 | 
			
		||||
// https://vitejs.dev/config/
 | 
			
		||||
export default defineConfig({
 | 
			
		||||
  plugins: [vue()],
 | 
			
		||||
})
 | 
			
		||||