Browse Source

feat: init

master
guoapeng 3 days ago
commit
8d718dcbf9
  1. 7
      .env.dev
  2. 7
      .env.pre
  3. 7
      .env.prod
  4. 7
      .env.test
  5. 27
      .gitignore
  6. 0
      .npmrc
  7. 28
      .postcssrc.js
  8. 10
      .prettierrc
  9. 23
      README.md
  10. BIN
      commitlint.config.js
  11. 25
      eslint.config.js
  12. 43
      increment-version.js
  13. 27
      index.html
  14. 97
      package.json
  15. BIN
      public/favicon.ico
  16. 7
      src/apis/audit.ts
  17. 5
      src/apis/channel.ts
  18. 5
      src/apis/container.ts
  19. 9
      src/apis/crafts.ts
  20. 13
      src/apis/home.ts
  21. 8
      src/apis/log.ts
  22. 4
      src/apis/login.ts
  23. 4
      src/apis/point.ts
  24. 3
      src/apis/self.ts
  25. 9
      src/apis/solution.ts
  26. 12
      src/apis/system.ts
  27. 7
      src/apis/user.ts
  28. 110
      src/app.vue
  29. 1
      src/assets/images/auto.svg
  30. 1
      src/assets/images/background.svg
  31. 1
      src/assets/images/empty.svg
  32. 1
      src/assets/images/error.svg
  33. 1
      src/assets/images/expand.svg
  34. 1
      src/assets/images/icon_add_s.svg
  35. 1
      src/assets/images/icon_arr_s.svg
  36. 1
      src/assets/images/icon_del_s.svg
  37. 1
      src/assets/images/ing.svg
  38. 1
      src/assets/images/jaw.svg
  39. 1
      src/assets/images/liquied/liquied_bottle.svg
  40. 1
      src/assets/images/login.svg
  41. 1
      src/assets/images/logo.svg
  42. 1
      src/assets/images/logout.svg
  43. 1
      src/assets/images/manual.svg
  44. 1
      src/assets/images/menuIcon/n_debug.svg
  45. 1
      src/assets/images/menuIcon/n_expe.svg
  46. 1
      src/assets/images/menuIcon/n_home.svg
  47. 1
      src/assets/images/menuIcon/n_liquid.svg
  48. 1
      src/assets/images/menuIcon/n_liquid_config.svg
  49. 1
      src/assets/images/menuIcon/n_log.svg
  50. 1
      src/assets/images/menuIcon/n_ore.svg
  51. 1
      src/assets/images/menuIcon/n_point.svg
  52. 1
      src/assets/images/menuIcon/n_ps.svg
  53. 1
      src/assets/images/menuIcon/n_setting.svg
  54. 1
      src/assets/images/menuIcon/n_user.svg
  55. 1
      src/assets/images/menuIcon/s_debug.svg
  56. 1
      src/assets/images/menuIcon/s_expe.svg
  57. 1
      src/assets/images/menuIcon/s_home.svg
  58. 1
      src/assets/images/menuIcon/s_liquid.svg
  59. 1
      src/assets/images/menuIcon/s_liquid_config.svg
  60. 1
      src/assets/images/menuIcon/s_log.svg
  61. 1
      src/assets/images/menuIcon/s_ore.svg
  62. 1
      src/assets/images/menuIcon/s_point.svg
  63. 1
      src/assets/images/menuIcon/s_ps.svg
  64. 1
      src/assets/images/menuIcon/s_setting.svg
  65. 1
      src/assets/images/menuIcon/s_user.svg
  66. 1
      src/assets/images/password_icon.svg
  67. 1
      src/assets/images/run.svg
  68. 1
      src/assets/images/solution.svg
  69. 1
      src/assets/images/success.svg
  70. 22
      src/assets/images/user-cancel.svg
  71. 1
      src/assets/images/user.svg
  72. 1
      src/assets/images/user_icon.svg
  73. 1
      src/assets/images/wait.svg
  74. 1
      src/assets/images/wifi-active.svg
  75. 1
      src/assets/images/wifi.svg
  76. 92
      src/assets/styles/common.scss
  77. 73
      src/assets/styles/element.scss
  78. 3
      src/assets/styles/main.scss
  79. 5
      src/assets/styles/variable.scss
  80. 158
      src/components/common/FTButton/index.vue
  81. 81
      src/components/common/FTChart/index.vue
  82. 108
      src/components/common/FTDatetime/index.vue
  83. 82
      src/components/common/FTDialog/index.vue
  84. 35
      src/components/common/FTImage/index.vue
  85. 356
      src/components/common/FTInput/index.vue
  86. 182
      src/components/common/FTStream/index.vue
  87. 7
      src/components/common/FTTable/expand.ts
  88. 216
      src/components/common/FTTable/index.vue
  89. 97
      src/components/home/Receive/index.vue
  90. 53
      src/components/solution/Edit/index.vue
  91. 255
      src/components/system/Check/index.vue
  92. 64
      src/components/system/EditDate/index.vue
  93. 28
      src/components/system/Stop/index.vue
  94. 53
      src/components/systemConfig/Edit/index.vue
  95. 184
      src/components/user/Edit/index.vue
  96. 21
      src/env.d.ts
  97. 33
      src/hooks/useActivateDebug.ts
  98. 29
      src/hooks/useApiData.ts
  99. 64
      src/hooks/useServerTime.ts
  100. 413
      src/layouts/default.vue

7
.env.dev

@ -0,0 +1,7 @@
# 开发环境
FT_NODE_ENV=dev
FT_WS_URL=ws://192.168.1.199:8080/ws
FT_PROXY=http://localhost:8080
FT_API_BASE=/api

7
.env.pre

@ -0,0 +1,7 @@
# 预发环境
FT_NODE_ENV=pre
FT_WS_URL=ws://192.168.8.108:8080/ws
FT_PROXY=http://192.168.8.108
FT_API_BASE=http://192.168.8.108:8080/api

7
.env.prod

@ -0,0 +1,7 @@
# 生产环境
FT_NODE_ENV=prod
FT_WS_URL=ws://192.168.8.168:8080/ws
FT_PROXY=http://192.168.8.168:8080
FT_API_BASE=/api

7
.env.test

@ -0,0 +1,7 @@
# 测试环境
FT_NODE_ENV=test
FT_WS_URL=ws://192.168.1.199:8081/ws
FT_PROXY=http://127.0.0.1:8081
FT_API_BASE=/api

27
.gitignore

@ -0,0 +1,27 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
auto-imports.d.ts
.eslintrc-auto-import.json
pnpm-lock.yaml
node_modules
dist
dist-*
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

0
.npmrc

28
.postcssrc.js

@ -0,0 +1,28 @@
export default {
plugins: {
'postcss-import': {},
'postcss-url': {},
'postcss-aspect-ratio-mini': {},
'postcss-write-svg': {
utf8: false,
},
'postcss-px-to-viewport-8-plugin': {
viewportWidth: 1120,
viewportHeight: 736,
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
selectorBlackList: ['.ignore', '.hairlines', ':after'], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false, // 允许在媒体查询中转换`px`
},
'postcss-viewport-units': {
filterRule: rule =>
!/::?(?:before|after)/i.test(rule.selector),
},
'cssnano': {
'autoprefixer': false,
'postcss-zindex': false,
},
},
}

10
.prettierrc

@ -0,0 +1,10 @@
{
"printWidth": 120,
"tabWidth": 2,
"endOfLine": "lf",
"singleQuote": true,
"semi": true,
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "avoid"
}

23
README.md

@ -0,0 +1,23 @@
### 前端项目模板
##### 文件目录
- src
- components 组件目录
- apis 接口文件目录
- assets 静态资源目录
- hooks hooks目录
- libs 公共工具类
- router 页面路由
- stores 项目公共状态管理
- types 类型申明
- views 页面目录
##### 项目运行
项目采用pnpm 进行依赖构建,请先安装pnpm
[pnpm - 速度快、节省磁盘空间的软件包管理器](https://pnpm.io/)
```bash
npm install pnpm -g
```
```bash
pnpm install // 安装依赖
pnpm dev // 运行项目
```

BIN
commitlint.config.js

25
eslint.config.js

@ -0,0 +1,25 @@
// import eslint_js from '@eslint/js'
// import eslint_ts from 'typescript-eslint';
// import eslint_vue from 'eslint-plugin-vue';
// import vue_parser from 'vue-eslint-parser';
import lintConfig from '@antfu/eslint-config'
export default lintConfig({
vue: true,
markdown: true,
ignores: [],
rules: {
'no-console': 0,
'antfu/top-level-function': 0,
'ts/no-use-before-define': 0,
'no-alert': 0,
'unused-imports/no-unused-vars': 0,
'unused-imports/no-unused-imports': 0,
},
globals: { process: 'readonly' },
extends: [
'plugin:vue/vue3-recommended',
'plugin:vue-pug/vue3-recommended',
],
})

43
increment-version.js

@ -0,0 +1,43 @@
import { execSync } from 'node:child_process' // 引入 child_process 模块用于执行 Git 命令
import fs from 'node:fs'
import path, { dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import semver from 'semver'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const packagePath = path.resolve(__dirname, 'package.json')
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'))
// 读取命令行参数(默认使用 'patch')
// eslint-disable-next-line node/prefer-global/process
const versionType = process.argv[2] || 'patch'
// 递增版本
const newVersion = semver.inc(packageJson.version, versionType)
if (!newVersion) {
throw new Error(`Invalid version type: ${versionType}`)
}
packageJson.version = newVersion
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2))
console.log(`Version updated to: ${newVersion}`)
// 新增:自动提交 package.json 到远程仓库
try {
// 将 package.json 添加到暂存区
execSync('git add package.json')
console.log('Added package.json to staging area.')
// 提交更改
execSync(`git commit -m "fix: Update version to V${newVersion}"`)
console.log(`Committed changes with message: Update version to ${newVersion}`)
// 推送到远程仓库
execSync('git push')
console.log('Pushed changes to remote repository.')
}
catch (error) {
console.error('Failed to commit and push changes:', error.message)
}

27
index.html

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>融动泵加液</title>
<style>
html,body{
height:100%;
width:100%;
margin: 0;
padding: 0;
}
#app {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

97
package.json

@ -0,0 +1,97 @@
{
"name": "color-titration-web",
"type": "module",
"version": "0.0.0",
"description": "",
"author": "",
"license": "ISC",
"keywords": [],
"main": "index.js",
"scripts": {
"dev": "vite --mode dev",
"dev:server": "concurrently -n server,client -c green,blue \"node server/index.js\" \"vite --mode dev\"",
"test": "vite --mode test",
"prod": "vite --mode prod",
"pre": "vite --mode pre",
"build": "vite build --mode dev",
"build:test": "vite build --mode test",
"build:prod:patch": "node increment-version.js patch && vite build --mode prod",
"build:prod:minor": "node increment-version.js minor && vite build --mode prod",
"build:prod:major": "node increment-version.js major && vite build --mode prod",
"build:pre": "vite build --mode pre",
"build:dev": "vite build --mode dev",
"prepare": "husky",
"lint:lint-staged": "lint-staged",
"lint": "vue-tsc --noEmit --skipLibCheck && eslint",
"eslint": "eslint --fix --ext .ts,.vue src",
"prettier": "prettier --write ."
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"autoprefixer": "^10.4.20",
"axios": "1.8.2",
"cssnano": "^7.0.6",
"echarts": "^5.6.0",
"element-plus": "^2.9.5",
"express": "^5.1.0",
"konva": "^9.3.18",
"lodash": "^4.17.21",
"pinia": "^3.0.1",
"pinia-plugin-persistedstate": "^4.2.0",
"postcss": "^8.5.3",
"postcss-aspect-ratio-mini": "^1.1.0",
"postcss-import": "^16.1.0",
"postcss-px-to-viewport-8-plugin": "^1.2.5",
"postcss-url": "^10.1.3",
"postcss-viewport-units": "^0.1.6",
"postcss-write-svg": "^3.0.1",
"vue": "^3.5.13",
"vue-router": "^4.5.0",
"ws": "^8.18.1"
},
"devDependencies": {
"@antfu/eslint-config": "^4.3.0",
"@commitlint/cli": "^19.7.1",
"@commitlint/config-conventional": "^19.7.1",
"@types/node": "^22.13.5",
"@typescript-eslint/eslint-plugin": "^8.25.0",
"@typescript-eslint/parser": "^8.25.0",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^5.0.1",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/language-plugin-pug": "^3.0.3",
"concurrently": "^9.1.2",
"eslint": "^9.21.0",
"eslint-config-prettier": "^10.0.2",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-vue": "^9.32.0",
"eslint-plugin-vue-pug": "^0.6.2",
"husky": "^9.1.7",
"lint-staged": "^15.4.3",
"prettier": "^3.5.2",
"pug": "^3.0.3",
"sass": "^1.85.1",
"semver": "^7.7.1",
"stylus": "^0.64.0",
"typescript": "^5.7.3",
"unplugin-auto-import": "^19.1.1",
"unplugin-vue-components": "^28.4.1",
"vite": "6.2.6",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-eslint": "^1.8.1",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^2.2.4"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
"eslint --fix",
"prettier --write",
"lint-staged"
]
}
}

BIN
public/favicon.ico

7
src/apis/audit.ts

@ -0,0 +1,7 @@
import http from 'libs/http'
export const getAuditList = (params: System.Page = { pageNum: 1, pageSize: 999 }): Promise<System.PageResponse<Audit.AuditItem[]>> => http.post(`/audit-record/page`, params)
export const exportAudit = (params: string): Promise<Blob> => http.post(`/audit-record/export`, params)
export const delAudit = (ids: string): Promise<null> => http.delete(`/audit-record/${ids}`)

5
src/apis/channel.ts

@ -0,0 +1,5 @@
import http from 'libs/http'
export const getChannelList = (): Promise<Channel.ChannelItem[]> => http.get(`/channel/list`)
export const edit = (params: Channel.ChannelItem): Promise<null> => http.put(`/channel`, params)

5
src/apis/container.ts

@ -0,0 +1,5 @@
import http from 'libs/http'
export const getContainerList = (): Promise<Container.ContainerItem[]> => http.get(`/container/list`)
export const updateContainer = (params: Container.ContainerItem): Promise<null> => http.put(`/container`, params)

9
src/apis/crafts.ts

@ -0,0 +1,9 @@
import http from 'libs/http'
export const getCraftList = (params: System.Page = { pageNum: 1, pageSize: 999 }): Promise<System.PageResponse<Craft.CraftItem>> => http.post(`/formulation/page`, params)
export const createCraft = (params: Craft.CraftItem): Promise<null> => http.post('/formulation', params)
export const updateCraft = (params: Craft.CraftItem): Promise<null> => http.put(`/formulation`, params)
export const delCraft = (ids: string): Promise<null> => http.delete(`/formulation/${ids}`)

13
src/apis/home.ts

@ -0,0 +1,13 @@
import http from 'libs/http'
const baseUrl = '/tasks/'
export const setTargetTemperature = (params: Home.SetTargetTemperatureParams): Promise<null> => http.post('/heat/target-temperature', params)
export const trayTube = (params: Home.TrayTubeParams[]): Promise<null> => http.put('/tube/set-tube-exist', params)
export const addTask = (params: Task.TaskAdd): Promise<null> => http.post(baseUrl, params)
export const stopTask = (): Promise<null> => http.post(`${baseUrl}stop`)
export const getTask = (id: number): Promise<Task.Task> => http.get(`${baseUrl}${id}`)
export const taskList = (params: Task.TaskQuery): Promise<Task.Task[]> => http.get(`${baseUrl}list`, { params })
export const getTaskIng = (): Promise<null> => http.get(`${baseUrl}getIngTask`)
export const delTask = (params: string): Promise<null> => http.delete(`${baseUrl}${params}`)
export const trayIn = (): Promise<null> => http.post('tray/in')
export const trayOut = (): Promise<null> => http.post('tray/out')

8
src/apis/log.ts

@ -0,0 +1,8 @@
import http from 'libs/http'
export const getLogList = (params: System.Page = { pageNum: 1, pageSize: 999 }): Promise<System.PageResponse<Log.LogItem>> => http.post(`/receive-record/page`, params)
export const exportLog = (params: string): Promise<Blob> => http.post(`/receive-record/export`, params)
export const delLog = (ids: string): Promise<null> => http.delete(`/receive-record/${ids}`)
export const addLog = (params: Log.LogItem): Promise<null> => http.post(`/receive-record`, params)

4
src/apis/login.ts

@ -0,0 +1,4 @@
import http from 'libs/http'
export const login = (params: User.Login): Promise<User.User> => http.post('/auth/login', params)
export const logout = (): Promise<null> => http.post('/auth/logout')

4
src/apis/point.ts

@ -0,0 +1,4 @@
import http from 'libs/http'
export const getPointList = (): Promise<Point.Point[]> => http.get('/position/list')
export const updatePoint = (params: Point.UpdateParams): Promise<null> => http.put('/device-point', params)

3
src/apis/self.ts

@ -0,0 +1,3 @@
import http from 'libs/http'
export const getSelfFinish = (params: boolean): Promise<Record<string, boolean>> => http.post('/self-test/finish', { params: { mode: params } })

9
src/apis/solution.ts

@ -0,0 +1,9 @@
import http from 'libs/http'
export const getSolsList = (params: System.Page = { pageNum: 1, pageSize: 999 }): Promise<System.PageResponse<Solution.SolutionItem>> => http.post(`/solution/page`, params)
export const saveSols = (params: Solution.SolutionItem): Promise<null> => http.post(`/solution`, params)
export const editSols = (params: Solution.SolutionItem): Promise<null> => http.put(`/solution`, params)
export const delSols = (ids: string): Promise<null> => http.delete(`/solution/${ids}`)

12
src/apis/system.ts

@ -0,0 +1,12 @@
import http from 'libs/http'
export const debugControl = <T>(params: System.CmdControlParams<T>): Promise<null> => http.post('/debug/cmd', params)
export const control = <T>(params: System.CmdControlParams<T>): Promise<null> => http.post('/cmd', params)
export const getStatus = (): Promise<System.SystemStatus> => http.get('/device/device-status')
export const getPoint = (motor: string): Promise<string> => http.get(`/motor/position/${motor}`)
export const requireOutTray = (): Promise<{ moduleCode: string }[]> => http.get('/self-test/require-out-tray')
export const setIgnoreItem = (params: { ignoreSelfTestType: string, ignore: boolean }): Promise<null> => http.post('/self-test/set-ignore-item', params)
export const getTime = (): Promise<{ epochMilli: number }> => http.get('/sys/get-datetime')
export const setTime = (params: { epochMilli?: number }): Promise<null> => http.post('/sys/set-datetime', params)
export const configList = (params: System.Page = { pageNum: 1, pageSize: 999 }): Promise<System.PageResponse<System.SystemConfig>> => http.post('/system-config/list', params)
export const updateConfig = (params: System.SystemConfig): Promise<number> => http.put('/system-config', params)

7
src/apis/user.ts

@ -0,0 +1,7 @@
import http from 'libs/http'
export const current = (): Promise<User.User> => http.get('/auth/current')
export const addUser = (params: User.User): Promise<null> => http.post('/user', params)
export const updateUser = (params: User.User): Promise<null> => http.put('/user', params)
export const userList = (params: System.Page = { pageNum: 1, pageSize: 999 }): Promise<System.PageResponse<User.User>> => http.post('/user/page', params)
export const delUser = (params: string): Promise<null> => http.delete(`/user/${params}`)

110
src/app.vue

@ -0,0 +1,110 @@
<script setup lang="ts">
import { getStatus } from 'apis/system'
// import { getStatus } from 'apis/system'
import { socket } from 'libs/socket'
import { useSystemStore } from 'stores/systemStore'
import { onBeforeUnmount, onMounted, ref } from 'vue'
const systemStore = useSystemStore()
onMounted(async () => {
const res = await getStatus()
// console.log(res)
// console.log(systemStore.systemStatus)
systemStore.updateSystemStatus(res)
startProgress()
})
socket.init((data: System.SystemStatus) => {
console.log(data)
systemStore.updateSystemStatus(data)
}, 'status')
const progress = ref(0)
let timer: any = null
const version = __APP_VERSION__
const startProgress = () => {
const max = Math.floor(Math.random() * (90 - 80 + 1)) + 80
timer = setInterval(() => {
const randomStep = Math.floor(Math.random() * 9 + 1)
if (systemStore.systemStatus.initComplete) {
//
progress.value = Math.min(progress.value + randomStep, 100)
}
else {
progress.value = Math.min(progress.value + randomStep, max)
}
if (progress.value >= 100) {
clearInterval(timer)
}
}, 100)
}
//
onBeforeUnmount(() => {
clearInterval(timer)
})
</script>
<template lang="pug">
//
div(v-if="progress < 100" class="main-content")
div(class="progress-container")
div(class="progress-bar" :style="{ width: `${progress}%` }")
div(class="progress-text")
| v{{ version }}系统初始化中 {{ progress }}%
router-view(v-else v-slot="{ Component }" class="main-content")
transition(name="el-zoom-in-center")
component(:is="Component")
</template>
<style scoped lang="stylus">
.main-content
width 100%
height 100%
background url("assets/images/background.svg") no-repeat center
background-size cover
overflow hidden
.login-container
display flex
flex-direction column
align-items center
justify-content center
height 100vh
background #f0f2f5
img
width 600px
position absolute
top 40%
right 20%
.progress-container
width 50%
height 20px
background #e4e7ed
border-radius 30px
position relative
top 90%
margin 0 auto
.progress-bar
height 100%
background linear-gradient(90deg, #1989FA, #096ae0)
border-radius 30px
transition width 0.3s ease
.progress-text
position absolute
top 50%
left 50%
transform translate(-50%, -50%)
color #fff
font-size 12px
line-height 12px
font-weight 500
</style>

1
src/assets/images/auto.svg

@ -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="18" height="15" viewBox="0 0 18 15"><g><path d="M16.8883,6.32357C17.1394,6.06504,17.555,6.06145,17.8106,6.31559C18.0662,6.56974,18.0626,6.98288,17.8026,7.23257L16.3507,8.676C16.0986,8.92762,15.6888,8.92762,15.4368,8.676L13.9845,7.23257C13.7244,6.98288,13.7208,6.56974,13.9764,6.31559C14.2321,6.06145,14.6476,6.06504,14.8988,6.32357L15.173,6.59657C14.7307,3.59786,12.1338,1.28571,8.99594,1.28571C6.57928,1.28571,4.35617,2.69829,3.33321,4.884C3.17522,5.19296,2.79943,5.32194,2.48336,5.17569C2.1673,5.02944,2.0246,4.66054,2.16065,4.34143C3.39442,1.704,6.07836,0,8.99551,0C12.8882,0,16.0998,2.94557,16.4973,6.71186L16.8878,6.32357L16.8883,6.32357ZM15.5183,9.80443C15.8422,9.95409,15.9829,10.3364,15.8325,10.6586C14.597,13.2956,11.914,15,8.99637,15C5.10454,15,1.89209,12.0544,1.49506,8.28771L1.10406,8.67643C0.851578,8.92756,0.442122,8.92765,0.189517,8.67664C-0.0630881,8.42563,-0.0631846,8.01856,0.189301,7.76743L1.64206,6.32314C1.89452,6.07247,2.3035,6.07247,2.55596,6.32314L4.00785,7.76743C4.27567,8.01553,4.28312,8.43498,4.02427,8.69232C3.76542,8.94965,3.34351,8.94225,3.09395,8.676L2.81935,8.40343C3.26165,11.4021,5.8585,13.7143,8.99637,13.7143C11.4135,13.7143,13.6366,12.3017,14.6591,10.116C14.8098,9.79408,15.1945,9.65457,15.5183,9.80443Z" fill="#FFFFFF" fill-opacity="1"/></g></svg>

1
src/assets/images/background.svg
File diff suppressed because it is too large
View File

1
src/assets/images/empty.svg

@ -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="160" height="217" viewBox="0 0 160 217"><defs><clipPath id="master_svg0_701_8873"><rect x="0" y="0" width="160" height="217" rx="0"/></clipPath><linearGradient x1="0.8473145961761475" y1="-0.13048571348190308" x2="-0.21846741185260635" y2="0.45531219158762304" id="master_svg1_701_9703"><stop offset="0%" stop-color="#9CA0FF" stop-opacity="1"/><stop offset="100%" stop-color="#9CCFFF" stop-opacity="1"/></linearGradient><linearGradient x1="1.0152618885040283" y1="0.07957261055707932" x2="0.19026522035783114" y2="1.0885049011631125" id="master_svg2_701_9704"><stop offset="0%" stop-color="#F2F3FF" stop-opacity="1"/><stop offset="100%" stop-color="#F2F9FF" stop-opacity="1"/></linearGradient></defs><g clip-path="url(#master_svg0_701_8873)"><g><rect x="41.62646484375" y="0" width="76.74667358398438" height="42.228694915771484" rx="5" fill="url(#master_svg1_701_9703)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><rect x="0" y="21.1171875" width="160" height="195.88375854492188" rx="5" fill="url(#master_svg2_701_9704)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M108.87600390624999,94.94093875L51.01304390625,94.94093875C48.43994390625,94.94098875,46.35400390625,92.85729875,46.35400390625,90.28692875C46.35605003625,87.71803875,48.44143390625,85.6366722972,51.01304390625,85.63671875L108.87590390625,85.63671875C111.44750390625,85.6366722972,113.53290390625,87.71803875,113.53490390625,90.28692875C113.53500390625,92.85724875,111.44910390625,94.94098875,108.87600390624999,94.94093875Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M108.87600390624999,123.71047L51.01304390625,123.71047C48.43994390625,123.71052,46.35400390625,121.62683,46.35400390625,119.05646C46.35605003625,116.48757,48.44143390625,114.4062035472,51.01304390625,114.40625L108.87590390625,114.40625C111.44750390625,114.4062035472,113.53290390625,116.48757,113.53490390625,119.05646C113.53500390625,121.62678,111.44910390625,123.71052,108.87600390624999,123.71047Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M108.87600390624999,152.48000125L51.01304390625,152.48000125C48.43994390625,152.48000125,46.35400390625,150.39631125,46.35400390625,147.82599125C46.35614304625,145.25715125,48.44143390625,143.17578125,51.01304390625,143.17578125L108.87590390625,143.17578125C111.44750390625,143.17578125,113.53280390625,145.25715125,113.53490390625,147.82599125C113.53500390625,150.39631125,111.44910390625,152.48000125,108.87600390624999,152.48000125Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/error.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_685_8859"><rect x="0" y="0" width="80" height="80" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8859)"><g><path d="M39.9853890625,4.94140625C20.7118890625,4.94140625,4.9462890625,20.70700625,4.9462890625,39.98050625C4.9462890625,59.25390625,20.7118890625,75.01950625,39.9853890625,75.01950625C59.2587890625,75.01950625,75.0243890625,59.25390625,75.0243890625,39.98050625C75.0243890625,20.70700625,59.2587890625,4.94140625,39.9853890625,4.94140625ZM56.7274890625,52.05080625C57.8993890625,53.22260625,57.8993890625,55.36330625,56.7274890625,56.52730625C56.1415890625,57.11330625,55.3681890625,57.50390625,54.3915890625,57.50390625C53.6103890625,57.50390625,52.6415890625,57.11330625,52.0556890625,56.52730625L40.7665890625,45.23830625L29.4774890625,56.52730625C28.3056890625,57.69920625,26.1650890625,57.69920625,25.0009890625,56.52730625C23.8368890625,55.35550625,23.8290890625,53.21480625,25.0009890625,52.05080625L36.2900890625,40.76170625L25.0009890625,29.47260625C24.4150890625,28.88670625,24.0243890625,28.11330625,24.0243890625,27.13670625C24.0243890625,26.35550625,24.4150890625,25.38670625,25.0009890625,24.80080625C26.1728890625,23.62890625,28.3134890625,23.62890625,29.4774890625,24.80080625L40.7665890625,36.089806249999995L52.0556890625,24.80080625C52.6415890625,24.21480625,53.4150890625,23.82420625,54.3915890625,23.82420625C55.1728890625,23.82420625,56.1415890625,24.21480625,56.7275890625,24.80080625C57.3134890625,25.38670625,57.7040890625,26.16020625,57.7040890625,27.13670625C57.7040890625,27.91800625,57.3134890625,28.88670625,56.7275890625,29.47260625L45.4384890625,40.76170625L56.7274890625,52.05080625Z" fill="#DF1515" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/expand.svg

@ -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="30.666667938232422" height="26.83333396911621" viewBox="0 0 30.666667938232422 26.83333396911621"><g><path d="M0,0L30.6667,0L30.6667,3.83333L0,3.83333L0,0ZM0,23L30.6667,23L30.6667,26.8333L0,26.8333L0,23 ZM0,11.5L30.6667,11.5L30.6667,15.3333L0,15.3333L0,11.5Z" fill="#1989FA" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

1
src/assets/images/icon_add_s.svg

@ -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="26.303199768066406" height="26.303173065185547" viewBox="0 0 26.303199768066406 26.303173065185547"><g><path d="M24.5875,14.8666L14.8674,14.8666L14.8674,24.5882C14.8674,25.5356,14.099,26.3032,13.1516,26.3032C12.2043,26.3032,11.4359,25.5356,11.4359,24.5882L11.4359,14.8666L1.71574,14.8666C0.767578,14.8666,0,14.099,0,13.1516C0,12.2046,0.767666,11.4366,1.71574,11.4366L11.4359,11.4366L11.4359,1.71495C11.4359,0.76793,12.2042,0,13.1516,0C14.099,0,14.8673,0.767959,14.8673,1.71495L14.8673,11.4367L24.5874,11.4367C25.5356,11.4367,26.3032,12.2046,26.3032,13.1515C26.3032,14.0989,25.5356,14.8665,24.5874,14.8665L24.5875,14.8666Z" fill="#479CF1" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

1
src/assets/images/icon_arr_s.svg

@ -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="15" height="23" viewBox="0 0 15 23"><g transform="matrix(-1,0,0,-1,30,46)"><path d="M27.436500000000002,23C27.436500000000002,23,30,25.37044,30,25.37044C30,25.37044,20.12696,34.5,20.12696,34.5C20.12696,34.5,30,43.629599999999996,30,43.629599999999996C30,43.629599999999996,27.436500000000002,46,27.436500000000002,46C27.436500000000002,46,15,34.5,15,34.5C15,34.5,27.436500000000002,23,27.436500000000002,23C27.436500000000002,23,27.436500000000002,23,27.436500000000002,23Z" fill-rule="evenodd" fill="#384D5D" fill-opacity="1"/></g></svg>

1
src/assets/images/icon_del_s.svg

@ -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="33" height="33" viewBox="0 0 33 33"><defs><clipPath id="master_svg0_685_8832"><rect x="0" y="0" width="33" height="33" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8832)"><g><path d="M28.5707296875,29.2627375C27.6653296875,30.1682375,26.1906296875,30.1682375,25.2831296875,29.2627375L4.4580476875,8.4376975C3.5526096875,7.5301975,3.5505466875,6.0575675,4.4580476875,5.1500705C5.3614196875,4.2425705,6.8361096875000005,4.2425705,7.7477296875,5.1500705L28.5707296875,25.9730375C29.4761296875,26.8847375,29.4803296875,28.3552375,28.5707296875,29.2627375ZM28.5460296875,8.4273875L7.7229796875000005,29.2503375C6.8134196875,30.1599375,5.3407996875,30.1599375,4.4332966875,29.2503375C3.5257966875,28.3449375,3.5257966875,26.8743375,4.4353596875,25.9627375L25.2583296875,5.1418205C26.1679296875,4.2343205,27.6426296875,4.2343205,28.5460296875,5.1397585C29.4555296875,6.0472575,29.4514296875,7.519887499999999,28.5460296875,8.4273875Z" fill="#7F7F7F" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/ing.svg
File diff suppressed because it is too large
View File

1
src/assets/images/jaw.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749632093752" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4247" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M854.33 557.59L750.14 446.03c0.69-5.85 1.05-11.8 1.05-17.84V98.63c0-18.86-15.35-34.21-34.21-34.21H304.23c-18.86 0-34.21 15.35-34.21 34.21v329.56c0 6.94 0.48 13.77 1.39 20.47L169.67 557.59c-54.93 5.75-97.9 52.33-97.9 108.75 0 52.13 36.69 95.79 85.59 106.68l64.18 177.62c1.99 5.49 7.19 9.07 12.91 9.07 0.58 0 1.17-0.03 1.76-0.11 0.29-0.04 0.52-0.19 0.8-0.25 0.41 0.08 0.75 0.37 1.18 0.37 0.45 0 0.91-0.04 1.36-0.13L317.02 944c3.37-0.68 6.29-2.67 7.98-5.47 1.58-2.63 1.98-5.69 1.11-8.62l-58.26-197.28c12.82-16.78 20.97-37.32 22.31-59.7l94.42-97.67c11.87 2.99 24.28 4.59 37.07 4.59h177.91c13.58 0 26.75-1.81 39.29-5.17l94.98 98.26c1.34 22.38 9.49 42.92 22.31 59.7l-58.26 197.28c-0.87 2.93-0.47 5.99 1.11 8.62 1.69 2.8 4.61 4.79 7.98 5.47l77.46 15.59c0.46 0.09 0.91 0.13 1.36 0.13 0.43 0 0.77-0.29 1.18-0.37 0.28 0.05 0.51 0.21 0.8 0.25 0.59 0.08 1.18 0.11 1.76 0.11 5.72 0 10.92-3.57 12.91-9.07l64.18-177.62c48.9-10.89 85.59-54.55 85.59-106.68 0.02-56.43-42.95-103.01-97.88-108.76zM425.69 168.2c15.23 0 27.57 12.34 27.57 27.57s-12.34 27.57-27.57 27.57-27.57-12.34-27.57-27.57c0-15.22 12.34-27.57 27.57-27.57z m-71.1 0c15.23 0 27.57 12.34 27.57 27.57s-12.34 27.57-27.57 27.57-27.57-12.34-27.57-27.57c0-15.22 12.35-27.57 27.57-27.57z m-57.11 140.93h426.25v58.59H297.48v-58.59z m-71.12 574L187.43 775.4c18.26-1.05 35.29-6.56 50.07-15.51l-11.14 123.24z m36.03-207.04c-0.03 0.24-0.08 0.48-0.11 0.72-0.42 3.08-0.98 6.12-1.71 9.09-2.05 8.31-5.48 16.06-9.84 23.16-0.36 0.59-0.64 1.24-1.02 1.82-2.25 3.46-4.79 6.71-7.52 9.79-0.94 1.05-2 1.98-2.99 2.99-1.93 1.96-3.9 3.88-6.01 5.64-1.27 1.05-2.61 2-3.94 2.97a82.524 82.524 0 0 1-6.34 4.26 79.83 79.83 0 0 1-4.44 2.47c-2.3 1.19-4.66 2.24-7.08 3.21-1.52 0.61-3.04 1.24-4.61 1.76-2.71 0.9-5.5 1.58-8.33 2.19-1.39 0.3-2.75 0.7-4.16 0.93-4.29 0.7-8.67 1.13-13.15 1.13-2.78 0-5.52-0.14-8.23-0.42-2.49-0.25-4.95-0.64-7.37-1.11-0.19-0.04-0.39-0.05-0.57-0.09a81.34 81.34 0 0 1-14.97-4.57c-29.75-12.28-50.75-41.57-50.75-75.71 0-39.2 27.7-72.02 64.54-80 2.74-0.59 5.53-1.05 8.36-1.37l0.2-0.03c2.89-0.32 5.82-0.49 8.79-0.49 3.6 0 7.13 0.3 10.61 0.77 0.55 0.07 1.1 0.17 1.65 0.25 3.36 0.53 6.68 1.2 9.9 2.11 28.09 7.91 50.04 30.43 57.19 58.84 0.76 3.01 1.34 6.08 1.77 9.2 0.04 0.28 0.09 0.55 0.13 0.83 0.42 3.24 0.66 6.54 0.66 9.89-0.02 3.33-0.25 6.58-0.66 9.77z m24.06-38.84c-10.67-38.57-41.93-68.62-81.2-77.5l74.05-79.29c13.69 37.17 41.54 67.55 76.99 84.55l-69.84 72.24z m451.1 0l-70.73-73.18c35.22-17.5 62.71-48.3 75.86-85.78l76.07 81.46c-39.27 8.88-70.52 38.93-81.2 77.5z m60.09 245.88L786.5 759.88c14.77 8.96 31.81 14.47 50.07 15.51l-38.93 107.74z m76.37-141.08a82.117 82.117 0 0 1-14.97 4.57c-0.19 0.04-0.38 0.05-0.57 0.09-2.42 0.47-4.87 0.86-7.37 1.11a82.9 82.9 0 0 1-8.23 0.42c-4.48 0-8.86-0.44-13.15-1.13-1.42-0.23-2.77-0.63-4.16-0.93-2.82-0.61-5.62-1.29-8.33-2.19-1.57-0.52-3.08-1.15-4.61-1.76-2.42-0.97-4.78-2.02-7.08-3.21a79.83 79.83 0 0 1-4.44-2.47c-2.19-1.31-4.29-2.75-6.34-4.26-1.33-0.97-2.68-1.92-3.94-2.97-2.12-1.76-4.08-3.68-6.01-5.64-0.99-1.01-2.05-1.93-2.99-2.99-2.73-3.07-5.27-6.33-7.52-9.79-0.38-0.58-0.65-1.23-1.02-1.82-4.37-7.1-7.79-14.85-9.84-23.16-0.73-2.97-1.3-6.01-1.71-9.09-0.03-0.24-0.08-0.48-0.11-0.72-0.4-3.2-0.64-6.44-0.64-9.75 0-3.36 0.24-6.65 0.66-9.89 0.03-0.28 0.09-0.56 0.13-0.83 0.43-3.12 1.01-6.2 1.77-9.2 7.14-28.4 29.09-50.92 57.19-58.84 3.22-0.91 6.54-1.58 9.9-2.11 0.55-0.08 1.09-0.18 1.65-0.25 3.48-0.47 7.01-0.77 10.61-0.77 2.97 0 5.9 0.17 8.79 0.49l0.2 0.03c2.83 0.32 5.62 0.78 8.36 1.37 36.84 7.99 64.54 40.8 64.54 80-0.02 34.12-21.02 63.41-50.77 75.69z" fill="#2c2c2c" p-id="4248"></path><path d="M842.86 666.34m-38.04 0a38.04 38.04 0 1 0 76.08 0 38.04 38.04 0 1 0-76.08 0Z" fill="#2c2c2c" p-id="4249"></path><path d="M181.14 666.34m-38.04 0a38.04 38.04 0 1 0 76.08 0 38.04 38.04 0 1 0-76.08 0Z" fill="#2c2c2c" p-id="4250"></path><path d="M511.3 660.66c59.33 0 91.96-44.32 94.93-57.42H416.37c8.9 31.77 51.13 57.42 94.93 57.42z" fill="#2c2c2c" p-id="4251"></path></svg>

1
src/assets/images/liquied/liquied_bottle.svg

@ -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="162.44374084472656" height="227.99989318847656" viewBox="0 0 162.44374084472656 227.99989318847656"><g><path d="M0,54.0618L0,64.2474C0,65.1128,0.699314,65.8144,1.56196,65.8144C2.4246,65.8144,3.12392,66.516,3.12392,67.3814L3.12392,73.6495C3.12392,74.5149,2.4246,75.2165,1.56196,75.2165C0.699314,75.2165,0,75.918,0,76.7835L0,90.8866C0,91.752,0.699314,92.4536,1.56196,92.4536C2.4246,92.4536,3.12392,93.1551,3.12392,94.0206L3.12392,100.289C3.12392,101.154,2.4246,101.856,1.56196,101.856C0.699314,101.856,0,102.557,0,103.423L0,122.227C0,123.092,0.699314,123.794,1.56196,123.794C2.4246,123.794,3.12392,124.495,3.12392,125.361L3.12392,131.629C3.12392,132.494,2.4246,133.196,1.56196,133.196C0.699314,133.196,0,133.897,0,134.763L0,153.567C0,154.432,0.699314,155.134,1.56196,155.134C2.4246,155.134,3.12392,155.836,3.12392,156.701L3.12392,162.969C3.12392,163.834,2.4246,164.536,1.56196,164.536C0.699314,164.536,0,165.238,0,166.103L0,183.34C0,184.206,0.699314,184.907,1.56196,184.907C2.4246,184.907,3.12392,185.609,3.12392,186.474L3.12392,193.526C3.12392,194.391,2.4246,195.093,1.56196,195.093C0.699314,195.093,0,195.794,0,196.66L0,206.062C0,218.178,9.79038,228,21.8674,228L140.576,228C152.653,228,162.444,218.178,162.444,206.062L162.444,196.66C162.444,195.794,161.744,195.093,160.882,195.093C160.019,195.093,159.32,194.391,159.32,193.526L159.32,186.474C159.32,185.609,160.019,184.907,160.882,184.907C161.744,184.907,162.444,184.206,162.444,183.34L162.444,166.103C162.444,165.238,161.744,164.536,160.882,164.536C160.019,164.536,159.32,163.834,159.32,162.969L159.32,156.701C159.32,155.836,160.019,155.134,160.882,155.134C161.744,155.134,162.444,154.432,162.444,153.567L162.444,134.763C162.444,133.897,161.744,133.196,160.882,133.196C160.019,133.196,159.32,132.494,159.32,131.629L159.32,125.361C159.32,124.495,160.019,123.794,160.882,123.794C161.744,123.794,162.444,123.092,162.444,122.227L162.444,103.423C162.444,102.557,161.744,101.856,160.882,101.856C160.019,101.856,159.32,101.154,159.32,100.289L159.32,94.0206C159.32,93.1551,160.019,92.4536,160.882,92.4536C161.744,92.4536,162.444,91.752,162.444,90.8866L162.444,76.7835C162.444,75.918,161.744,75.2165,160.882,75.2165C160.019,75.2165,159.32,74.5149,159.32,73.6495L159.32,67.3814C159.32,66.516,160.019,65.8144,160.882,65.8144C161.744,65.8144,162.444,65.1128,162.444,64.2474L162.444,54.0618C162.444,41.9457,152.653,32.1237,140.576,32.1237L134.962,32.1237C132.711,32.1237,131.583,29.3931,133.175,27.7961C137.914,23.042,140.576,16.594,140.576,9.87062L140.576,4.70103C140.576,2.10472,138.478,0,135.89,0L26.5533,0C23.9654,0,21.8674,2.10472,21.8674,4.70103L21.8674,9.87062C21.8674,16.594,24.5297,23.042,29.2685,27.7961C30.8603,29.3931,29.7329,32.1237,27.4817,32.1237L21.8674,32.1237C9.79038,32.1237,0,41.9457,0,54.0618Z" fill="#EEEFF8" fill-opacity="1"/></g></svg>

1
src/assets/images/login.svg
File diff suppressed because it is too large
View File

1
src/assets/images/logo.svg
File diff suppressed because it is too large
View File

1
src/assets/images/logout.svg

@ -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="42" height="43" viewBox="0 0 42 43"><g><g><path d="M23.9012,26.80821171875L23.5184,26.80821171875C19.5186,26.80821171875,15.5189,26.80861171875,11.519,26.80821171875C10.926,26.80801171875,10.5396,26.52971171875,10.4443,26.03191171875C10.4255,25.93251171875,10.4273,25.82801171875,10.4273,25.72631171875C10.4266,22.08721171875,10.4265,18.44831171875,10.4268,14.80931171875C10.4269,14.11901171875,10.792,13.75181171875,11.4767,13.75181171875C15.4946,13.75161171875,19.5126,13.75161171875,23.5307,13.75161171875L23.9012,13.75161171875L23.9012,13.42041171875C23.9012,10.18168171875,23.9008,6.94273171875,23.9016,3.70375171875C23.9016,3.25804771875,24.1092,2.90257571875,24.4607,2.76641631875C24.8652,2.60961481875,25.224,2.68183999875,25.5289,3.01164571875C25.7037,3.20077071875,25.8941,3.3747387187499998,26.0736,3.55867171875C28.3386,5.87259171875,30.6032,8.18756171875,32.8676,10.50147171875C35.7762,13.47271171875,38.6848,16.44331171875,41.5933,19.41441171875C42.0776,19.90851171875,42.0802,20.42981171875,41.6017,20.91861171875C37.4394,25.17281171875,33.2774,29.42731171875,29.1138,33.67981171875C27.9297,34.88921171875,26.7392,36.09131171875,25.5561,37.30171171875C25.2516,37.61371171875,24.912,37.75041171875,24.4963,37.58871171875C24.092,37.43171171875,23.9017,37.10601171875,23.9017,36.59371171875C23.901,33.45751171875,23.9012,30.32081171875,23.9012,27.18461171875L23.9012,26.80821171875L23.9012,26.80821171875ZM16.4243,2.86945471875L16.4243,6.546731718749999L16.0943,6.546731718749999C13.049,6.546731718749999,10.0037,6.54631171875,6.95843,6.54694171875C5.02868,6.54723171875,3.60763,8.00513171875,3.60755,9.98472171875C3.60726,16.83461171875,3.61953,23.68451171875,3.59949,30.53391171875C3.59397,32.34621171875,4.94067,33.65191171875,6.18574,33.89041171875C6.46085,33.94251171875,6.74508,33.96611171875,7.02513,33.96681171875C10.0431,33.97221171875,13.0612,33.970111718750005,16.0793,33.970111718750005L16.4189,33.970111718750005L16.4189,37.62641171875C16.3759,37.63521171875,16.3258,37.65491171875,16.2756,37.65491171875C13.0666,37.65491171875,9.85733,37.68831171875,6.64918,37.64061171875C3.51369,37.59461171875,0.737073,35.15841171875,0.138685,32.005211718750004C0.0542352,31.56101171875,0.0129305,31.10101171875,0.0124397,30.64841171875C0.00466952,23.72381171875,-0.0132019,16.79961171875,0.0166111,9.87552171875C0.0290843,6.98330171875,1.43263,4.90707171875,3.88372,3.55774671875C4.74846,3.08148071875,5.70366,2.86639671875,6.68823,2.86388471875C9.8698,2.85509271875,13.0514,2.86053471875,16.2331,2.86074471875C16.2868,2.86078671875,16.3405,2.86560171875,16.4243,2.86945471875Z" fill="#1989FA" fill-opacity="1"/></g></g></svg>

1
src/assets/images/manual.svg
File diff suppressed because it is too large
View File

1
src/assets/images/menuIcon/n_debug.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_592_42038"><rect x="19" y="18.921875" width="41" height="41" rx="0"/></clipPath></defs><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g clip-path="url(#master_svg0_592_42038)"><g><path d="M53.8413984375,21.65234443077L25.1580984375,21.65234443077C23.2666884375,21.652344090385,21.733398779614,23.17788375,21.733399121728,25.05973375L21.733399121728,47.20904375L57.2666984375,47.20904375L57.2666984375,25.05973375C57.2670984375,23.17798375,55.7333984375,21.652344090385,53.8413984375,21.65234443077ZM52.9319984375,35.12904375C52.9319984375,35.83334375,52.3579984375,36.405643749999996,51.6500984375,36.406943749999996L47.5684984375,36.406943749999996C47.3869984375,36.40704375,47.2220984375,36.30194375,47.1462984375,36.13784375L46.7859984375,35.36184375C46.7178984375,35.21544375,46.5724984375,35.11984375,46.410498437499996,35.11504375C46.2483984375,35.11024375,46.0974984375,35.19694375,46.0206984375,35.33904375L42.2247984375,42.38224375C42.0768984375,42.65614375,41.7907984375,42.828143749999995,41.478398437500005,42.83104375C41.165898437500005,42.83394375,40.8765984375,42.66724375,40.7235984375,42.39624375L34.6923984375,31.69304375C34.6111984375,31.54864375,34.4531984375,31.46415375,34.2872984375,31.47640375C34.1214984375,31.48864375,33.9777984375,31.59540375,33.9187984375,31.75014375L32.3505984375,35.85744375C32.224298437499996,36.18814375,31.9057984375,36.40684375,31.5502384375,36.406943749999996L27.3519484375,36.406943749999996C26.6425784375,36.406943749999996,26.067528437500002,35.83474375,26.067528437500002,35.12904375C26.067528437500002,34.42324375,26.6425784375,33.85104375,27.3519484375,33.85104375L29.7753884375,33.85104375C30.1312484375,33.85104375,30.4494884375,33.63214375,30.5757584375,33.30154375L33.1400984375,26.58196375C33.2582984375,26.27280375,33.5454984375,26.05956375,33.8769984375,26.03496375C34.2084984375,26.01035375,34.5243984375,26.17881375,34.687298437500004,26.46711375L41.053898437499996,37.75784375C41.1302984375,37.89354375,41.2749984375,37.97704375,41.431298437500004,37.97554375C41.587698437499995,37.974143749999996,41.7307984375,37.887943750000005,41.804598437500005,37.75084375L45.789198437500005,30.36372375C45.9430984375,30.079963749999997,46.244798437499995,29.906903749999998,46.568698437500004,29.916573749999998C46.8925984375,29.926243749999998,47.1832984375,30.11697375,47.3197984375,30.40940375L48.6858984375,33.35554375C48.8261984375,33.65754375,49.129098437500005,33.85044375,49.4632984375,33.85104375L51.6500984375,33.85104375C52.3592984375,33.85104375,52.9344984375,34.423443750000004,52.9344984375,35.12904375L52.9319984375,35.12904375ZM21.733399121728,48.66654375L21.733399121728,53.77824375C21.733398779614,55.66014375,23.2666884375,57.18564375,25.1580984375,57.18564375L53.8413984375,57.18564375C55.7327984375,57.18564375,57.2660984375,55.66014375,57.2660984375,53.77824375L57.2660984375,48.66654375L21.733399121728,48.66654375ZM42.338998437499995,52.74404375C42.3368984375,53.44894375,41.7630984375,54.01984375,41.054598437500005,54.02194375L27.3519484375,54.02194375C26.6425784375,54.02194375,26.067528437500002,53.449743749999996,26.067528437500002,52.74404375C26.067528437500002,52.03824375,26.6425784375,51.46604375,27.3519484375,51.46604375L41.0519984375,51.46604375C41.761498437499995,51.46674375,42.3368984375,52.03814375,42.338998437499995,52.74404375ZM52.9319984375,52.74404375C52.9291984375,53.447443750000005,52.3570984375,54.01724375,51.6500984375,54.02064375L46.510498437500004,54.02064375C45.8010984375,54.02064375,45.2260984375,53.44854375,45.2260984375,52.74274375C45.2260984375,52.03694375,45.8010984375,51.46484375,46.510498437500004,51.46484375L51.6500984375,51.46484375C52.358098437500004,51.46834375,52.930598437499995,52.03954375,52.9319984375,52.74404375Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/n_expe.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><path d="M54.037,56.006L28.80688,56.006C27.22599,56.006,25.93399,54.6781,25.93399,53.0441C25.93399,51.6375,26.888939999999998,50.4627,28.16489,50.1565L28.16489,21.0455056C25.82164,21.380591,24,23.46143,24,25.96836L24,53.0523C24,55.7785,26.15066,58,28.79886,58L54.037,58C54.5706,58,55,57.5574,55,57.0072C55.004000000000005,56.457,54.5706,56.006,54.037,56.006ZM42.742000000000004,37.799800000000005L41.847300000000004,37.799800000000005L41.847300000000004,39.1815L40.5031,39.1815L40.5031,40.1081L41.847300000000004,40.1081L41.847300000000004,41.4898L42.742000000000004,41.4898L42.742000000000004,40.1081L44.090199999999996,40.1081L44.090199999999996,39.1815L42.742000000000004,39.1815L42.742000000000004,37.799800000000005ZM44.090199999999996,29.05031L40.5031,29.05031L40.5031,33.3775L39.2994,35.6817C39.817,35.5824,40.334599999999995,35.5617,40.852199999999996,35.6155C42.2605,35.7644,42.569500000000005,36.8814,44.4393,36.8814C44.985,36.8814,45.4384,36.8193,45.807500000000005,36.6952L44.090199999999996,33.3981L44.090199999999996,29.05031ZM53.2425,21L30.09086,21L30.09086,50.1276L30.5563,50.1276C30.612470000000002,50.1358,30.67266,50.1358,30.73284,50.1358L53.2425,50.1358C54.125299999999996,50.1358,54.8475,49.3912,54.8475,48.4811L54.8475,22.65888C54.8515,21.744634,54.125299999999996,21.000000315617,53.2425,21ZM49.3224,42.424800000000005C49.1619,42.6978,48.881,42.8674,48.5721,42.875699999999995L36.0212,42.875699999999995C35.7042,42.875699999999995,35.4113,42.7061,35.2508,42.424800000000005C35.0903,42.1435,35.082300000000004,41.8001,35.2348,41.5105L39.5963,33.2161L39.5963,29.05031L38.5089,29.05031C38.2521,29.05031,38.0475,28.8352,38.0475,28.57457C38.0475,28.309820000000002,38.2561,28.09884,38.5089,28.09884L46.0643,28.09884C46.3211,28.09884,46.5257,28.31395,46.5257,28.57457C46.5257,28.83933,46.317099999999996,29.05031,46.0643,29.05031L44.9769,29.05031L44.9769,33.2203L46.561800000000005,36.231899999999996L49.3425,41.5105C49.490899999999996,41.8001,49.4869,42.1434,49.3224,42.424800000000005Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/n_home.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><path d="M20.0370799,43.6256C20.866486,47.6246,22.91091,51.222300000000004,25.94731,54.0277C26.3526,54.4028,26.9106,54.5752,27.46181,54.4956C28.0134,54.4165,28.49784,54.0943,28.77694,53.6208L31.1482,49.591300000000004C31.5442,48.9178,31.451999999999998,48.070499999999996,30.92,47.4942C29.68039,46.1482,28.77662,44.537800000000004,28.28009,42.7903C28.06083,42.015,27.34183,41.4784,26.52231,41.4784L21.82395,41.4784C21.27636,41.4781,20.757754,41.7198,20.411853,42.1363C20.0647341,42.552,19.9270634,43.0991,20.0370799,43.6256ZM44.1657,51.909C43.7696,51.233000000000004,42.9726,50.8869,42.1963,51.053799999999995C40.231899999999996,51.4761,38.1899,51.3965,36.2658,50.8227C35.453900000000004,50.580600000000004,34.579,50.9191,34.1541,51.6398L31.8262,55.5982C31.5578,56.055,31.5084,56.6046,31.691000000000003,57.1004C31.872999999999998,57.5967,32.2697,57.9884,32.7742,58.1703C34.9795,58.9695,37.3089,59.375,39.695,59.375C41.6678,59.375,43.6156,59.0954,45.482600000000005,58.543C46.0156,58.3847,46.446,57.9968,46.652,57.4891C46.8572,56.9806,46.814099999999996,56.408,46.535,55.9346L44.1657,51.909ZM52.5476,24.57127C52.2201,24.3027,51.806799999999996,24.15552,51.379999999999995,24.15542C51.2742,24.15542,51.1663,24.166330000000002,51.060500000000005,24.18424C50.531,24.2771,50.0703,24.59457,49.8016,25.05176L47.4685,29.01324C47.045100000000005,29.73472,47.183499999999995,30.6473,47.802800000000005,31.2165C49.39,32.6707,50.5347,34.5286,51.1096,36.5833C51.3275,37.3604,52.0476,37.8989,52.8691,37.899100000000004L57.568,37.899100000000004C58.1145,37.8988,58.6321,37.658,58.9784,37.2432C59.3258,36.8281,59.464,36.2815,59.3546,35.7553C58.4579,31.3953,56.0407,27.42316,52.5476,24.57127ZM46.652,21.88784C46.446600000000004,21.37975,46.0159,20.99153,45.482600000000005,20.833661C43.6053,20.279568,41.6553,19.99869145,39.695,20.00000417001C37.3089,20.00000417001,34.9795,20.405219,32.7742,21.20446C31.714199999999998,21.58978,31.262,22.8179,31.8262,23.77903L34.1541,27.73687C34.579,28.457549999999998,35.453900000000004,28.79609,36.2658,28.55402C37.3775,28.22171,38.5332,28.05317,39.6953,28.05394C40.530100000000004,28.05394,41.372299999999996,28.14349,42.1963,28.32119C42.9721,28.48767,43.7685,28.14262,44.1657,27.46794L46.5353,23.44182C46.8143,22.96858,46.857299999999995,22.39608,46.652,21.88784ZM57.568,41.4781L52.8691,41.4781C52.0475,41.477599999999995,51.327,42.0163,51.1096,42.7936C50.5345,44.848299999999995,49.3898,46.7063,47.802800000000005,48.160799999999995C47.1834,48.729,47.0449,49.6411,47.4685,50.3618L49.8016,54.3249C50.07,54.7824,50.5309,55.1001,51.060500000000005,55.1927C51.1663,55.2106,51.2742,55.2196,51.379999999999995,55.2196C51.8066,55.2202,52.2199,55.0737,52.5476,54.8057C56.0407,51.9518,58.4579,47.9814,59.3546,43.622C59.4641,43.0957,59.3259,42.549099999999996,58.9784,42.134C58.6326,41.718599999999995,58.1147,41.4778,57.568,41.4781ZM20.411568,37.241C20.757316,37.6573,21.27588,37.8989,21.82367,37.8989L26.52259,37.8989C27.34233,37.8986,28.06128,37.361999999999995,28.280369999999998,36.587C28.776699999999998,34.8389,29.68048,33.2279,30.920299999999997,31.8814C31.4524,31.3057,31.544600000000003,30.4588,31.1485,29.785890000000002L28.77722,25.75641C28.49772,25.28303,28.01361,24.96039,27.46209,24.87994C27.37433,24.86765,27.28578,24.86166,27.19713,24.86203C26.73679,24.86203,26.28729,25.03413,25.9476,25.349510000000002C22.91091,28.15468,20.866486,31.7521,20.0370799,35.7513C19.9271883,36.2779,20.0647273,36.825,20.411568,37.241Z" fill="#4F85FB" fill-opacity="1"/></g></g></svg>

1
src/assets/images/menuIcon/n_liquid.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><path d="M30.42768,34.2143L30.42768,52.673C30.42768,53.4027,31.06121,54.0357,31.77429,54.0357L48.5584,54.0357C49.2714,54.0357,49.794,53.4027,49.794,52.673L49.794,34.2143L30.42768,34.2143ZM47.8574,46.726600000000005C47.8574,47.091499999999996,47.5684,47.387299999999996,47.2118,47.387299999999996C46.8553,47.387299999999996,46.5663,47.091499999999996,46.5663,46.726600000000005L46.5663,42.762299999999996C46.5663,42.397400000000005,46.8553,42.101600000000005,47.2118,42.101600000000005C47.5684,42.101600000000005,47.8574,42.397400000000005,47.8574,42.762299999999996L47.8574,46.726600000000005ZM47.2673,40.780100000000004C46.910799999999995,40.780100000000004,46.6218,40.4844,46.6218,40.1194C46.6218,39.7545,46.910799999999995,39.4587,47.2673,39.4587C47.6239,39.4587,47.9129,39.7545,47.9129,40.1194C47.9129,40.484300000000005,47.6239,40.780100000000004,47.2673,40.780100000000004ZM54.7629,21L29.21229,21C24.827023,21,24,23.26509,24,24.28292C26.44097,24.63393,26.55442,24.67522,26.55442,27.318080000000002L26.55442,52.673C26.55442,55.5922,28.92203,58,31.77429,58L48.5383,58C51.3904,58,53.6673,55.5922,53.6673,52.673L53.6673,24.96429C53.6673,23.28368,54.6596,21.803098,54.7579,21.6456C54.856300000000005,21.488186,55,21.331926,55,21.236123C55,21.139411,54.9664,21,54.7629,21ZM51.0851,24.96429L51.0851,52.673C51.0851,54.153,50.081,55.3571,48.679500000000004,55.3571L31.77429,55.3571C30.352719999999998,55.3571,29.136589999999998,54.128,29.136589999999998,52.673L29.136589999999998,27.318080000000002C29.136589999999998,26.34254,29.22487,24.24163,28.8277,23.6877C28.90202,23.62221,29.07898,23.64286,29.19211,23.64286L51.1939,23.64286C51.1345,23.64286,51.0851,24.53474,51.0851,24.96429Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/n_liquid_config.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><path d="M25.010964,27.14686L25.010964,52.3976C25.00721385,52.5305,25.0362768,52.6662,25.0915901,52.791799999999995C25.490033,53.8368,27.08099,54.6141,29.95072,55.1751C33.25546,55.7635,36.6258,56.0395,39.9999,55.9955C43.375,56.0285,46.7406,55.7525,50.0501,55.1741C52.915099999999995,54.6031,54.536100000000005,53.8083,54.9083,52.7909C54.9636,52.6662,54.992599999999996,52.5342,54.9889,52.3976L54.9889,27.14686C55.003699999999995,27.099980000000002,55.003699999999995,27.04982,54.9889,27.00294L54.9889,26.77745C54.9889,25.48132,53.3829,24.50509,50.0454,23.860689999999998C46.734700000000004,23.255981,43.3715,22.9686265,40.0037,23.00271173C36.6286,22.9697126,33.26296,23.245622,29.95353,23.824024C26.64599,24.468420000000002,25.0109623,25.44373,25.0109623,26.74078C24.999922606,26.81525,24.999922606,26.89089,25.0109623,26.96536C24.996346,27.011960000000002,24.996346,27.06176,25.0109623,27.10836L25.0109623,27.14502L25.010964,27.14686ZM46.0047,44.9994C46.0122,44.4503,46.524100000000004,44.0048,47.1578,43.9975L51.8398,43.9975L51.8398,45.9976L47.1578,45.9976C46.524100000000004,45.994,46.0122,45.548500000000004,46.0047,44.9994ZM46.0047,40.4987C46.0122,39.950500000000005,46.524100000000004,39.504999999999995,47.1578,39.497699999999995L51.7292,39.497699999999995L51.7292,41.4868L47.1578,41.4868C46.5278,41.4868,46.0122,41.047799999999995,46.0047,40.4996L46.0047,40.4987ZM46.0047,35.9888C46.0122,35.4388,46.5278,35.001599999999996,47.1578,35.001599999999996L51.8398,35.001599999999996L51.8398,36.990700000000004L47.1578,36.990700000000004C46.524100000000004,36.9824,46.0122,36.537,46.0047,35.987899999999996L46.0047,35.9888ZM29.501649999999998,45.4953C29.501649999999998,44.674,29.71822,43.8637,30.13072,43.1533C31.08773,41.4645,32.13675,39.827200000000005,33.27327,38.2483L33.27327,38.1823L33.51327,38.054L33.578900000000004,37.9981L33.96984,37.9981L33.96984,38.0531L34.035470000000004,38.1191Q34.09172,38.1191,34.09172,38.186C35.5242,39.727599999999995,36.7882,41.411100000000005,37.8633,43.209199999999996C38.841300000000004,44.8373,38.690200000000004,46.8866,37.483599999999996,48.3607C36.2789,49.8228,34.27922,50.3746,32.49232,49.730199999999996C30.70542,49.0858,29.51572,47.3928,29.52697,45.4953L29.501649999999998,45.4953ZM27.45319,27.739919999999998C28.58383,26.75362,29.8326,26.11288,31.13293,25.858060000000002C34.019059999999996,25.06777,37.0069,24.68957,40.0037,24.73517C42.9756,24.6875,45.9494,25.06699,48.8744,25.858060000000002C50.174800000000005,26.10555,51.4273,26.74628,52.5542,27.739919999999998C51.419799999999995,28.71615,50.171,29.35688,48.8744,29.62179C45.9848,30.39315,42.9988,30.76495,40.0037,30.72635C37.0084,30.76678,34.02223,30.39495,31.13293,29.62179C29.83728,29.3633,28.58383,28.72623,27.45319,27.739919999999998Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/n_log.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><path d="M32,30.00793C32.8,30.00793,33.5,29.30731,33.5,28.506610000000002L33.5,22.50132C33.5,21.700617,32.8,21,32,21C31.2,21,30.5,21.700617,30.5,22.50132L30.5,28.506610000000002C30.5,29.30731,31.2,30.00793,32,30.00793ZM45,30.00793C45.8,30.00793,46.5,29.30731,46.5,28.506610000000002L46.5,22.50132C46.5,21.700617,45.8,21,45,21C44.2,21,43.5,21.700617,43.5,22.50132L43.5,28.506610000000002C43.5,29.30731,44.2,30.00793,45,30.00793ZM40,50.0255C40,45.1212,43,40.8174,47.2,39.0159L28.5,39.0159C27.7,39.0159,27,38.315200000000004,27,37.5145C27,36.7138,27.7,36.0132,28.5,36.0132L47.5,36.0132C48.3,36.0132,49,36.7138,49,37.5145C49,37.9149,48.8,38.215199999999996,48.6,38.5154C49.7,38.215199999999996,50.8,38.015,52,38.015C52.3,38.015,52.7,38.015,53,38.1151L53,29.00705C53,26.80511,51.2,25.00352,49,25.00352L49,28.506610000000002C49,31.0088,47,33.0106,44.5,33.0106C42,33.0106,40,31.0088,40,28.506610000000002L40,25.00352L36,25.00352L36,28.506610000000002C36,31.0088,34,33.0106,31.5,33.0106C29,33.0106,27,31.0088,27,28.506610000000002L27,25.00352C24.8,25.00352,23,26.80511,23,29.00705L23,55.03C23,57.2319,24.8,59.0335,27,59.0335L44.1,59.0335C41.6,56.8315,40,53.6287,40,50.0255ZM37.5,51.026399999999995L28.5,51.026399999999995C27.7,51.026399999999995,27,50.3258,27,49.525099999999995C27,48.7244,27.7,48.0238,28.5,48.0238L37.5,48.0238C38.3,48.0238,39,48.7244,39,49.525099999999995C39,50.3258,38.3,51.026399999999995,37.5,51.026399999999995ZM37.5,45.021100000000004L28.5,45.021100000000004C27.7,45.021100000000004,27,44.320499999999996,27,43.519800000000004C27,42.7191,27.7,42.0185,28.5,42.0185L37.5,42.0185C38.3,42.0185,39,42.7191,39,43.519800000000004C39,44.320499999999996,38.3,45.021100000000004,37.5,45.021100000000004ZM52,41.0176C47,41.0176,43,45.1212,43,50.0255C43,54.9299,47.1,59.0335,52,59.0335C56.9,59.0335,61,54.9299,61,50.0255C61,45.1212,57,41.0176,52,41.0176ZM55.5,53.0282L50.5,53.0282C49.7,53.0282,49,52.327600000000004,49,51.5269L49,45.5216C49,44.7209,49.7,44.0203,50.5,44.0203C51.3,44.0203,52,44.7209,52,45.5216L52,50.0255L55.5,50.0255C56.3,50.0255,57,50.7262,57,51.5269C57,52.327600000000004,56.3,53.0282,55.5,53.0282Z" fill="#4F85FB" fill-opacity="1"/></g></g></svg>

1
src/assets/images/menuIcon/n_ore.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><path d="M51.951499999999996,39.8059C50.843199999999996,40.323899999999995,49.9413,40.7615,48.9636,41.225899999999996C48.4242,40.9535,47.7542,40.408699999999996,47.004000000000005,40.2435C44.3744,39.6987,41.8501,42.1279,41.9554,44.9411C41.9554,45.378699999999995,41.593,46.0619,41.2348,46.1958C39.8694,46.687,39.2499,47.723,39.174099999999996,49.0894C39.0982,51.2194,38.9423,53.4297,41.5467,54.2513C41.7531,54.3049,41.829,54.7693,41.959599999999995,55.0417C41.652,55.2069,41.3149,55.5329,41.0072,55.5329C37.5305,55.5597,34.0496,55.5597,30.5729,55.5597C28.97572,55.5597,27.37854,55.5865,25.78137,55.5597C23.745912,55.5061,23,54.6577,23,52.527699999999996L23,23.88686C23,21.895306,23.720627,21.0468861,25.62966,21.020094C33.539699999999996,20.99330188,41.4497,20.99330188,49.364000000000004,21.020094C51.037,21.020094,51.9136,21.895306,51.9388,23.83327C52.0021,29.18278,51.951499999999996,34.5635,51.951499999999996,39.8059ZM37.6232,24.75761C37.6232,24.730809999999998,37.6232,24.730809999999998,37.6232,24.75761C35.2001,24.75761,32.776920000000004,24.730809999999998,30.35798,24.75761C29.17379,24.75761,28.19188,25.76678,28.21717,26.86079C28.26774,27.9816,29.144289999999998,28.79876,30.35798,28.79876C35.0737,28.79876,39.763999999999996,28.79876,44.4797,28.77197C45.950500000000005,28.77197,46.591,28.00839,46.565799999999996,26.56161C46.5405,25.44081,45.765100000000004,24.78886,44.4797,24.78886C42.183,24.730809999999998,39.915800000000004,24.75761,37.6232,24.75761ZM33.7841,36.3899C35.0189,36.3899,36.2578,36.4435,37.4673,36.3631C38.445,36.3095,39.1951,35.7335,39.2963,34.6171C39.4269,33.3624,38.6515,32.4336,37.6485,32.38C35.0737,32.2416,32.46928,32.4336,29.8902,32.5184C28.68073,32.5452,28.242449999999998,33.5544,28.26774,34.568C28.29302,35.7424,29.09372,36.3988,30.25262,36.3988L33.7841,36.3988L33.7841,36.3899ZM56.9495,50.3441C57.156,51.326499999999996,56.7177,51.9294,55.8412,52.3089C54.2693,52.9921,53.856300000000005,53.7825,54.1934,55.5016C54.3999,56.5644,53.7046,57.002,53.0851,57.4128C52.4403,57.8236,51.7956,58.3952,50.893699999999995,57.6048C49.6295,56.4572,48.727599999999995,56.6225,47.210499999999996,57.5245C46.6964,57.8236,45.8198,57.7968,45.2256,57.578C44.504999999999995,57.3057,43.7549,56.8145,43.9867,55.6669C44.3491,53.8941,43.5231,52.7465,42.081900000000005,52.143699999999995C40.9988,51.6793,41.1547,50.7237,41.18,49.9869C41.2053,49.415400000000005,41.6436,48.566900000000004,42.1071,48.3213C43.5231,47.584599999999995,44.1679,47.0085,44.0415,44.6062C43.965599999999995,43.324600000000004,44.787400000000005,43.021,45.4827,42.695C45.9463,42.4494,46.8228,42.3958,47.185199999999995,42.695C48.5001,43.815799999999996,49.7348,43.7577,50.948499999999996,42.7218C52.0821,41.7662,52.7269,42.775400000000005,53.5529,43.2398C54.3536,43.6774,54.2988,44.2757,54.0923,45.0706C53.7847,46.298500000000004,54.4547,47.6917,55.6136,48.0757C56.7177,48.4062,57.0802,49.143,56.9495,50.3441ZM45.7145,49.9333C45.6892,52.143699999999995,46.9787,53.5905,49.039500000000004,53.6173C50.7673,53.6441,52.259100000000004,52.2509,52.313900000000004,50.585300000000004C52.3645,48.2365,51.0497,46.682500000000005,48.9383,46.5977C47.210499999999996,46.5486,45.7398,48.049,45.7145,49.9333Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/n_point.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_94_4549"><rect x="18" y="18" width="44" height="44" rx="0"/></clipPath></defs><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g clip-path="url(#master_svg0_94_4549)"><g><path d="M39.9964013671875,20.74951171875C31.6590513671875,20.74951171875,24.8739013671875,27.53466171875,24.8739013671875,35.87201171875C24.8739013671875,43.92101171875,38.4294013671875,58.21571171875,39.0059013671875,58.82171171875C39.2646013671875,59.09521171875,39.6268013671875,59.25041171875,40.0038013671875,59.25041171875L40.0333013671875,59.25041171875C40.4177013671875,59.25041171875,40.7872013671875,59.07311171875,41.0385013671875,58.77741171875L45.7320013671875,53.40401171875C51.9702013671875,45.76881171875,55.126201367187505,39.87061171875,55.126201367187505,35.87941171875C55.126201367187505,27.53471171875,48.3411013671875,20.74955640795,39.9964013671875,20.74951171875ZM39.9964013671875,42.745811718750005C36.1973013671875,42.745811718750005,33.1225213671875,39.67101171875,33.1225213671875,35.87201171875C33.1225213671875,32.07291171875,36.1973013671875,28.998131718750003,39.9964013671875,28.998131718750003C43.7954013671875,28.998131718750003,46.870201367187505,32.07291171875,46.870201367187505,35.87201171875C46.870201367187505,39.67101171875,43.7954013671875,42.745811718750005,39.9964013671875,42.745811718750005Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/n_ps.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_94_4745"><rect x="21" y="59" width="38" height="38" rx="0"/></clipPath></defs><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g transform="matrix(1,0,0,-1,0,118)" clip-path="url(#master_svg0_94_4745)"><g><path d="M56.9528,97L23.04725,97C21.916585,97,21,96.0834,21,94.9528L21,61.04725C21,59.91675,21.91675,59,23.04725,59L56.9551,59C58.0832,59,59,59.91675,59,61.04725L59,94.9551C58.9987,96.0849,58.0825,97,56.9528,97ZM50.8134,83.21549999999999L50.8134,64.88525C50.8108,64.25542,50.300799999999995,63.74548,49.671,63.74288C49.0412,63.74548,48.5312,64.25541,48.5286,64.88525L48.5286,83.2226C46.297200000000004,83.8023,44.843599999999995,85.9491,45.1338,88.2362C45.424099999999996,90.5233,47.3679,92.239,49.6734,92.24289999999999C51.9827,92.2411,53.9304,90.52250000000001,54.2198,88.2313C54.5091,85.9402,53.0497,83.7914,50.8134,83.21549999999999ZM41.142399999999995,73.5754L41.142399999999995,64.90663C41.1398,64.27679,40.6298,63.76685,40,63.76425C39.3702,63.76685,38.8602,64.27679,38.857600000000005,64.90663L38.857600000000005,73.5754C36.839,74.1033,35.4307,75.9268,35.430099999999996,78.0133C35.4296,80.0999,36.8369,81.9241,38.8553,82.4531L38.8553,91.1219C38.8553,91.74889999999999,39.370599999999996,92.2642,39.9976,92.2642C40.6275,92.2616,41.1374,91.7517,41.14,91.1219L41.14,82.4531C43.1652,81.93209999999999,44.5811,80.10640000000001,44.5816,78.0152C44.5822,75.924,43.1673,74.0975,41.142399999999995,73.5754ZM30.33138,63.73575C28.02941,63.74415,26.09074,65.45857,25.80085,67.74223C25.51095,70.02590000000001,26.95977,72.1703,29.186619999999998,72.7536L29.186619999999998,91.09100000000001C29.186619999999998,91.718,29.701999999999998,92.2334,30.329,92.2334C30.95883,92.2308,31.4688,91.7208,31.4714,91.09100000000001L31.4714,72.7536C33.7053,72.1781,35.1629,70.0312,34.873599999999996,67.74254C34.584199999999996,65.45384,32.6383,63.73726,30.33138,63.73575Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/n_setting.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><g><path d="M57.7309,36.6424L54.4199,35.1065C52.2821,34.1115,51.0169,31.80957,51.2919,29.41513L51.7134,25.70348C49.9764,24.13487,47.9673,22.91636,45.7913,22.111649L42.809,24.29289C40.9002,25.70218,38.3223,25.67794,36.438900000000004,24.23298L33.5495,22C31.3612,22.766417,29.33189,23.9468,27.56639,25.48018L27.92691,29.18911C28.16995,31.58721,26.871940000000002,33.8705,24.71933,34.8315L21.35269,36.3074C20.9039103,38.6357,20.883231,41.0297,21.291719,43.3658L24.60269,44.9071C26.74368,45.8995,28.01241,48.202,27.73869,50.5985L27.30925,54.2911C29.0484,55.858,31.056800000000003,57.0779,33.2313,57.8884L36.1897,55.7098C38.098,54.2997,40.6759,54.3229,42.559799999999996,55.767L45.4705,58C47.6601,57.2361,49.6906,56.0565,51.456199999999995,54.5225L51.0984,50.8054C50.8651,48.409099999999995,52.158699999999996,46.1352,54.306,45.1685L57.6461,43.6953C58.0967,41.3643,58.1179,38.9679,57.7044,36.6287L57.7309,36.6424ZM39.5113,49.514700000000005C34.3981,49.514700000000005,30.25307,45.2566,30.25307,40.0041C30.25307,34.7515,34.3981,30.49349,39.5113,30.49349C44.6245,30.49349,48.7696,34.7515,48.7696,40.0041C48.7696,45.2566,44.6245,49.514700000000005,39.5113,49.514700000000005Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M39.503226597900394,32.666666984558105C35.85293659790039,32.6648691245581,32.89285659790039,35.650166984558105,32.89285659790039,39.3333369845581C32.89285659790039,43.01646698455811,35.85293659790039,46.0017669845581,39.503226597900394,45.99996698455811C43.15095659790039,45.998166984558104,46.10715659790039,43.01396698455811,46.10715659790039,39.3333369845581C46.10715659790039,35.65270698455811,43.15095659790039,32.66846320455811,39.503226597900394,32.666666984558105ZM39.503226597900394,43.0462669845581C37.535416597900394,42.95376698455811,35.98716659790039,41.316986984558106,35.98716659790039,39.329296984558106C35.98716659790039,37.34159698455811,37.535416597900394,35.704856984558106,39.503226597900394,35.61227698455811C41.495636597900386,35.7097269845581,43.08915659790039,37.317586984558105,43.185756597900394,39.3279469845581C43.17395659790039,41.372516984558104,41.52956659790039,43.024566984558106,39.503226597900394,43.0274669845581L39.503226597900394,43.0462669845581Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/n_user.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g><path d="M29.44471,32.3043C29.44472,37.9952,34.0687,42.608599999999996,39.772800000000004,42.608599999999996C45.4768,42.608599999999996,50.100899999999996,37.9952,50.100899999999996,32.3043C50.100899999999996,26.6134,45.4768,22,39.772800000000004,22C34.0687,22,29.44472,26.6134,29.44471,32.3043ZM55.678,46.5004L51.0002,46.5004C50.2702,46.5004,49.678200000000004,45.9097,49.678200000000004,45.1814C49.678200000000004,44.4531,50.2702,43.8625,51.0002,43.8625L55.678,43.8625C56.408,43.8625,57,44.4531,57,45.1814C57,45.9097,56.408,46.5004,55.678,46.5004ZM55.678,52.2502L47.580799999999996,52.2502C46.8508,52.2502,46.2588,51.6595,46.2588,50.931200000000004C46.2588,50.2029,46.8508,49.612300000000005,47.580799999999996,49.612300000000005L55.678,49.612300000000005C56.408,49.612300000000005,57,50.2029,57,50.931200000000004C57,51.6595,56.408,52.2502,55.678,52.2502ZM55.678,58L47.580799999999996,58C46.8508,58,46.2588,57.4094,46.2588,56.681C46.2588,55.9527,46.8508,55.3621,47.580799999999996,55.3621L55.678,55.3621C56.408,55.3621,57,55.9527,57,56.681C57,57.4094,56.408,58,55.678,58ZM41.260000000000005,52.9303C41.260000000000005,48.602900000000005,43.934200000000004,44.898700000000005,47.723299999999995,43.3724C48.3662,43.113600000000005,48.4289,42.229,47.825,41.8898C45.435,40.546099999999996,42.6911,39.782,39.772800000000004,39.782C30.50933,39.782,23,47.4797,23,56.9757C23,57.0475,23.000413211,57.1188,23.00123932,57.1901C23.0066098,57.6398,23.376768,58,23.827485,58L41.2753,58C41.865700000000004,58,42.262299999999996,57.4015,42.037099999999995,56.857C41.5364,55.6469,41.260000000000005,54.3209,41.260000000000005,52.9303Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/s_debug.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_592_42099"><rect x="19" y="18.921875" width="41" height="41" rx="0"/></clipPath></defs><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g clip-path="url(#master_svg0_592_42099)"><g><path d="M53.8413984375,21.65234443077L25.1580984375,21.65234443077C23.2666884375,21.652344090385,21.733398779614,23.17788375,21.733399121728,25.05973375L21.733399121728,47.20904375L57.2666984375,47.20904375L57.2666984375,25.05973375C57.2670984375,23.17798375,55.7333984375,21.652344090385,53.8413984375,21.65234443077ZM52.9319984375,35.12904375C52.9319984375,35.83334375,52.3579984375,36.405643749999996,51.6500984375,36.406943749999996L47.5684984375,36.406943749999996C47.3869984375,36.40704375,47.2220984375,36.30194375,47.1462984375,36.13784375L46.7859984375,35.36184375C46.7178984375,35.21544375,46.5724984375,35.11984375,46.410498437499996,35.11504375C46.2483984375,35.11024375,46.0974984375,35.19694375,46.0206984375,35.33904375L42.2247984375,42.38224375C42.0768984375,42.65614375,41.7907984375,42.828143749999995,41.478398437500005,42.83104375C41.165898437500005,42.83394375,40.8765984375,42.66724375,40.7235984375,42.39624375L34.6923984375,31.69304375C34.6111984375,31.54864375,34.4531984375,31.46415375,34.2872984375,31.47640375C34.1214984375,31.48864375,33.9777984375,31.59540375,33.9187984375,31.75014375L32.3505984375,35.85744375C32.224298437499996,36.18814375,31.9057984375,36.40684375,31.5502384375,36.406943749999996L27.3519484375,36.406943749999996C26.6425784375,36.406943749999996,26.067528437500002,35.83474375,26.067528437500002,35.12904375C26.067528437500002,34.42324375,26.6425784375,33.85104375,27.3519484375,33.85104375L29.7753884375,33.85104375C30.1312484375,33.85104375,30.4494884375,33.63214375,30.5757584375,33.30154375L33.1400984375,26.58196375C33.2582984375,26.27280375,33.5454984375,26.05956375,33.8769984375,26.03496375C34.2084984375,26.01035375,34.5243984375,26.17881375,34.687298437500004,26.46711375L41.053898437499996,37.75784375C41.1302984375,37.89354375,41.2749984375,37.97704375,41.431298437500004,37.97554375C41.587698437499995,37.974143749999996,41.7307984375,37.887943750000005,41.804598437500005,37.75084375L45.789198437500005,30.36372375C45.9430984375,30.079963749999997,46.244798437499995,29.906903749999998,46.568698437500004,29.916573749999998C46.8925984375,29.926243749999998,47.1832984375,30.11697375,47.3197984375,30.40940375L48.6858984375,33.35554375C48.8261984375,33.65754375,49.129098437500005,33.85044375,49.4632984375,33.85104375L51.6500984375,33.85104375C52.3592984375,33.85104375,52.9344984375,34.423443750000004,52.9344984375,35.12904375L52.9319984375,35.12904375ZM21.733399121728,48.66654375L21.733399121728,53.77824375C21.733398779614,55.66014375,23.2666884375,57.18564375,25.1580984375,57.18564375L53.8413984375,57.18564375C55.7327984375,57.18564375,57.2660984375,55.66014375,57.2660984375,53.77824375L57.2660984375,48.66654375L21.733399121728,48.66654375ZM42.338998437499995,52.74404375C42.3368984375,53.44894375,41.7630984375,54.01984375,41.054598437500005,54.02194375L27.3519484375,54.02194375C26.6425784375,54.02194375,26.067528437500002,53.449743749999996,26.067528437500002,52.74404375C26.067528437500002,52.03824375,26.6425784375,51.46604375,27.3519484375,51.46604375L41.0519984375,51.46604375C41.761498437499995,51.46674375,42.3368984375,52.03814375,42.338998437499995,52.74404375ZM52.9319984375,52.74404375C52.9291984375,53.447443750000005,52.3570984375,54.01724375,51.6500984375,54.02064375L46.510498437500004,54.02064375C45.8010984375,54.02064375,45.2260984375,53.44854375,45.2260984375,52.74274375C45.2260984375,52.03694375,45.8010984375,51.46484375,46.510498437500004,51.46484375L51.6500984375,51.46484375C52.358098437500004,51.46834375,52.930598437499995,52.03954375,52.9319984375,52.74404375Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/s_expe.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><path d="M54.037,56.006L28.80688,56.006C27.22599,56.006,25.93399,54.6781,25.93399,53.0441C25.93399,51.6375,26.888939999999998,50.4627,28.16489,50.1565L28.16489,21.0455056C25.82164,21.380591,24,23.46143,24,25.96836L24,53.0523C24,55.7785,26.15066,58,28.79886,58L54.037,58C54.5706,58,55,57.5574,55,57.0072C55.004000000000005,56.457,54.5706,56.006,54.037,56.006ZM42.742000000000004,37.799800000000005L41.847300000000004,37.799800000000005L41.847300000000004,39.1815L40.5031,39.1815L40.5031,40.1081L41.847300000000004,40.1081L41.847300000000004,41.4898L42.742000000000004,41.4898L42.742000000000004,40.1081L44.090199999999996,40.1081L44.090199999999996,39.1815L42.742000000000004,39.1815L42.742000000000004,37.799800000000005ZM44.090199999999996,29.05031L40.5031,29.05031L40.5031,33.3775L39.2994,35.6817C39.817,35.5824,40.334599999999995,35.5617,40.852199999999996,35.6155C42.2605,35.7644,42.569500000000005,36.8814,44.4393,36.8814C44.985,36.8814,45.4384,36.8193,45.807500000000005,36.6952L44.090199999999996,33.3981L44.090199999999996,29.05031ZM53.2425,21L30.09086,21L30.09086,50.1276L30.5563,50.1276C30.612470000000002,50.1358,30.67266,50.1358,30.73284,50.1358L53.2425,50.1358C54.125299999999996,50.1358,54.8475,49.3912,54.8475,48.4811L54.8475,22.65888C54.8515,21.744634,54.125299999999996,21.000000315617,53.2425,21ZM49.3224,42.424800000000005C49.1619,42.6978,48.881,42.8674,48.5721,42.875699999999995L36.0212,42.875699999999995C35.7042,42.875699999999995,35.4113,42.7061,35.2508,42.424800000000005C35.0903,42.1435,35.082300000000004,41.8001,35.2348,41.5105L39.5963,33.2161L39.5963,29.05031L38.5089,29.05031C38.2521,29.05031,38.0475,28.8352,38.0475,28.57457C38.0475,28.309820000000002,38.2561,28.09884,38.5089,28.09884L46.0643,28.09884C46.3211,28.09884,46.5257,28.31395,46.5257,28.57457C46.5257,28.83933,46.317099999999996,29.05031,46.0643,29.05031L44.9769,29.05031L44.9769,33.2203L46.561800000000005,36.231899999999996L49.3425,41.5105C49.490899999999996,41.8001,49.4869,42.1434,49.3224,42.424800000000005Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/s_home.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><path d="M20.0370799,43.6256C20.866486,47.6246,22.91091,51.222300000000004,25.94731,54.0277C26.3526,54.4028,26.9106,54.5752,27.46181,54.4956C28.0134,54.4165,28.49784,54.0943,28.77694,53.6208L31.1482,49.591300000000004C31.5442,48.9178,31.451999999999998,48.070499999999996,30.92,47.4942C29.68039,46.1482,28.77662,44.537800000000004,28.28009,42.7903C28.06083,42.015,27.34183,41.4784,26.52231,41.4784L21.82395,41.4784C21.27636,41.4781,20.757754,41.7198,20.411853,42.1363C20.0647341,42.552,19.9270634,43.0991,20.0370799,43.6256ZM44.1657,51.909C43.7696,51.233000000000004,42.9726,50.8869,42.1963,51.053799999999995C40.231899999999996,51.4761,38.1899,51.3965,36.2658,50.8227C35.453900000000004,50.580600000000004,34.579,50.9191,34.1541,51.6398L31.8262,55.5982C31.5578,56.055,31.5084,56.6046,31.691000000000003,57.1004C31.872999999999998,57.5967,32.2697,57.9884,32.7742,58.1703C34.9795,58.9695,37.3089,59.375,39.695,59.375C41.6678,59.375,43.6156,59.0954,45.482600000000005,58.543C46.0156,58.3847,46.446,57.9968,46.652,57.4891C46.8572,56.9806,46.814099999999996,56.408,46.535,55.9346L44.1657,51.909ZM52.5476,24.57127C52.2201,24.3027,51.806799999999996,24.15552,51.379999999999995,24.15542C51.2742,24.15542,51.1663,24.166330000000002,51.060500000000005,24.18424C50.531,24.2771,50.0703,24.59457,49.8016,25.05176L47.4685,29.01324C47.045100000000005,29.73472,47.183499999999995,30.6473,47.802800000000005,31.2165C49.39,32.6707,50.5347,34.5286,51.1096,36.5833C51.3275,37.3604,52.0476,37.8989,52.8691,37.899100000000004L57.568,37.899100000000004C58.1145,37.8988,58.6321,37.658,58.9784,37.2432C59.3258,36.8281,59.464,36.2815,59.3546,35.7553C58.4579,31.3953,56.0407,27.42316,52.5476,24.57127ZM46.652,21.88784C46.446600000000004,21.37975,46.0159,20.99153,45.482600000000005,20.833661C43.6053,20.279568,41.6553,19.99869145,39.695,20.00000417001C37.3089,20.00000417001,34.9795,20.405219,32.7742,21.20446C31.714199999999998,21.58978,31.262,22.8179,31.8262,23.77903L34.1541,27.73687C34.579,28.457549999999998,35.453900000000004,28.79609,36.2658,28.55402C37.3775,28.22171,38.5332,28.05317,39.6953,28.05394C40.530100000000004,28.05394,41.372299999999996,28.14349,42.1963,28.32119C42.9721,28.48767,43.7685,28.14262,44.1657,27.46794L46.5353,23.44182C46.8143,22.96858,46.857299999999995,22.39608,46.652,21.88784ZM57.568,41.4781L52.8691,41.4781C52.0475,41.477599999999995,51.327,42.0163,51.1096,42.7936C50.5345,44.848299999999995,49.3898,46.7063,47.802800000000005,48.160799999999995C47.1834,48.729,47.0449,49.6411,47.4685,50.3618L49.8016,54.3249C50.07,54.7824,50.5309,55.1001,51.060500000000005,55.1927C51.1663,55.2106,51.2742,55.2196,51.379999999999995,55.2196C51.8066,55.2202,52.2199,55.0737,52.5476,54.8057C56.0407,51.9518,58.4579,47.9814,59.3546,43.622C59.4641,43.0957,59.3259,42.549099999999996,58.9784,42.134C58.6326,41.718599999999995,58.1147,41.4778,57.568,41.4781ZM20.411568,37.241C20.757316,37.6573,21.27588,37.8989,21.82367,37.8989L26.52259,37.8989C27.34233,37.8986,28.06128,37.361999999999995,28.280369999999998,36.587C28.776699999999998,34.8389,29.68048,33.2279,30.920299999999997,31.8814C31.4524,31.3057,31.544600000000003,30.4588,31.1485,29.785890000000002L28.77722,25.75641C28.49772,25.28303,28.01361,24.96039,27.46209,24.87994C27.37433,24.86765,27.28578,24.86166,27.19713,24.86203C26.73679,24.86203,26.28729,25.03413,25.9476,25.349510000000002C22.91091,28.15468,20.866486,31.7521,20.0370799,35.7513C19.9271883,36.2779,20.0647273,36.825,20.411568,37.241Z" fill="#FFFFFF" fill-opacity="1"/></g></g></svg>

1
src/assets/images/menuIcon/s_liquid.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><path d="M30.42768,34.2143L30.42768,52.673C30.42768,53.4027,31.06121,54.0357,31.77429,54.0357L48.5584,54.0357C49.2714,54.0357,49.794,53.4027,49.794,52.673L49.794,34.2143L30.42768,34.2143ZM47.8574,46.726600000000005C47.8574,47.091499999999996,47.5684,47.387299999999996,47.2118,47.387299999999996C46.8553,47.387299999999996,46.5663,47.091499999999996,46.5663,46.726600000000005L46.5663,42.762299999999996C46.5663,42.397400000000005,46.8553,42.101600000000005,47.2118,42.101600000000005C47.5684,42.101600000000005,47.8574,42.397400000000005,47.8574,42.762299999999996L47.8574,46.726600000000005ZM47.2673,40.780100000000004C46.910799999999995,40.780100000000004,46.6218,40.4844,46.6218,40.1194C46.6218,39.7545,46.910799999999995,39.4587,47.2673,39.4587C47.6239,39.4587,47.9129,39.7545,47.9129,40.1194C47.9129,40.484300000000005,47.6239,40.780100000000004,47.2673,40.780100000000004ZM54.7629,21L29.21229,21C24.827023,21,24,23.26509,24,24.28292C26.44097,24.63393,26.55442,24.67522,26.55442,27.318080000000002L26.55442,52.673C26.55442,55.5922,28.92203,58,31.77429,58L48.5383,58C51.3904,58,53.6673,55.5922,53.6673,52.673L53.6673,24.96429C53.6673,23.28368,54.6596,21.803098,54.7579,21.6456C54.856300000000005,21.488186,55,21.331926,55,21.236123C55,21.139411,54.9664,21,54.7629,21ZM51.0851,24.96429L51.0851,52.673C51.0851,54.153,50.081,55.3571,48.679500000000004,55.3571L31.77429,55.3571C30.352719999999998,55.3571,29.136589999999998,54.128,29.136589999999998,52.673L29.136589999999998,27.318080000000002C29.136589999999998,26.34254,29.22487,24.24163,28.8277,23.6877C28.90202,23.62221,29.07898,23.64286,29.19211,23.64286L51.1939,23.64286C51.1345,23.64286,51.0851,24.53474,51.0851,24.96429Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/s_liquid_config.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><path d="M25.010964,27.14686L25.010964,52.3976C25.00721385,52.5305,25.0362768,52.6662,25.0915901,52.791799999999995C25.490033,53.8368,27.08099,54.6141,29.95072,55.1751C33.25546,55.7635,36.6258,56.0395,39.9999,55.9955C43.375,56.0285,46.7406,55.7525,50.0501,55.1741C52.915099999999995,54.6031,54.536100000000005,53.8083,54.9083,52.7909C54.9636,52.6662,54.992599999999996,52.5342,54.9889,52.3976L54.9889,27.14686C55.003699999999995,27.099980000000002,55.003699999999995,27.04982,54.9889,27.00294L54.9889,26.77745C54.9889,25.48132,53.3829,24.50509,50.0454,23.860689999999998C46.734700000000004,23.255981,43.3715,22.9686265,40.0037,23.00271173C36.6286,22.9697126,33.26296,23.245622,29.95353,23.824024C26.64599,24.468420000000002,25.0109623,25.44373,25.0109623,26.74078C24.999922606,26.81525,24.999922606,26.89089,25.0109623,26.96536C24.996346,27.011960000000002,24.996346,27.06176,25.0109623,27.10836L25.0109623,27.14502L25.010964,27.14686ZM46.0047,44.9994C46.0122,44.4503,46.524100000000004,44.0048,47.1578,43.9975L51.8398,43.9975L51.8398,45.9976L47.1578,45.9976C46.524100000000004,45.994,46.0122,45.548500000000004,46.0047,44.9994ZM46.0047,40.4987C46.0122,39.950500000000005,46.524100000000004,39.504999999999995,47.1578,39.497699999999995L51.7292,39.497699999999995L51.7292,41.4868L47.1578,41.4868C46.5278,41.4868,46.0122,41.047799999999995,46.0047,40.4996L46.0047,40.4987ZM46.0047,35.9888C46.0122,35.4388,46.5278,35.001599999999996,47.1578,35.001599999999996L51.8398,35.001599999999996L51.8398,36.990700000000004L47.1578,36.990700000000004C46.524100000000004,36.9824,46.0122,36.537,46.0047,35.987899999999996L46.0047,35.9888ZM29.501649999999998,45.4953C29.501649999999998,44.674,29.71822,43.8637,30.13072,43.1533C31.08773,41.4645,32.13675,39.827200000000005,33.27327,38.2483L33.27327,38.1823L33.51327,38.054L33.578900000000004,37.9981L33.96984,37.9981L33.96984,38.0531L34.035470000000004,38.1191Q34.09172,38.1191,34.09172,38.186C35.5242,39.727599999999995,36.7882,41.411100000000005,37.8633,43.209199999999996C38.841300000000004,44.8373,38.690200000000004,46.8866,37.483599999999996,48.3607C36.2789,49.8228,34.27922,50.3746,32.49232,49.730199999999996C30.70542,49.0858,29.51572,47.3928,29.52697,45.4953L29.501649999999998,45.4953ZM27.45319,27.739919999999998C28.58383,26.75362,29.8326,26.11288,31.13293,25.858060000000002C34.019059999999996,25.06777,37.0069,24.68957,40.0037,24.73517C42.9756,24.6875,45.9494,25.06699,48.8744,25.858060000000002C50.174800000000005,26.10555,51.4273,26.74628,52.5542,27.739919999999998C51.419799999999995,28.71615,50.171,29.35688,48.8744,29.62179C45.9848,30.39315,42.9988,30.76495,40.0037,30.72635C37.0084,30.76678,34.02223,30.39495,31.13293,29.62179C29.83728,29.3633,28.58383,28.72623,27.45319,27.739919999999998Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/s_log.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><path d="M32,30.00793C32.8,30.00793,33.5,29.30731,33.5,28.506610000000002L33.5,22.50132C33.5,21.700617,32.8,21,32,21C31.2,21,30.5,21.700617,30.5,22.50132L30.5,28.506610000000002C30.5,29.30731,31.2,30.00793,32,30.00793ZM45,30.00793C45.8,30.00793,46.5,29.30731,46.5,28.506610000000002L46.5,22.50132C46.5,21.700617,45.8,21,45,21C44.2,21,43.5,21.700617,43.5,22.50132L43.5,28.506610000000002C43.5,29.30731,44.2,30.00793,45,30.00793ZM40,50.0255C40,45.1212,43,40.8174,47.2,39.0159L28.5,39.0159C27.7,39.0159,27,38.315200000000004,27,37.5145C27,36.7138,27.7,36.0132,28.5,36.0132L47.5,36.0132C48.3,36.0132,49,36.7138,49,37.5145C49,37.9149,48.8,38.215199999999996,48.6,38.5154C49.7,38.215199999999996,50.8,38.015,52,38.015C52.3,38.015,52.7,38.015,53,38.1151L53,29.00705C53,26.80511,51.2,25.00352,49,25.00352L49,28.506610000000002C49,31.0088,47,33.0106,44.5,33.0106C42,33.0106,40,31.0088,40,28.506610000000002L40,25.00352L36,25.00352L36,28.506610000000002C36,31.0088,34,33.0106,31.5,33.0106C29,33.0106,27,31.0088,27,28.506610000000002L27,25.00352C24.8,25.00352,23,26.80511,23,29.00705L23,55.03C23,57.2319,24.8,59.0335,27,59.0335L44.1,59.0335C41.6,56.8315,40,53.6287,40,50.0255ZM37.5,51.026399999999995L28.5,51.026399999999995C27.7,51.026399999999995,27,50.3258,27,49.525099999999995C27,48.7244,27.7,48.0238,28.5,48.0238L37.5,48.0238C38.3,48.0238,39,48.7244,39,49.525099999999995C39,50.3258,38.3,51.026399999999995,37.5,51.026399999999995ZM37.5,45.021100000000004L28.5,45.021100000000004C27.7,45.021100000000004,27,44.320499999999996,27,43.519800000000004C27,42.7191,27.7,42.0185,28.5,42.0185L37.5,42.0185C38.3,42.0185,39,42.7191,39,43.519800000000004C39,44.320499999999996,38.3,45.021100000000004,37.5,45.021100000000004ZM52,41.0176C47,41.0176,43,45.1212,43,50.0255C43,54.9299,47.1,59.0335,52,59.0335C56.9,59.0335,61,54.9299,61,50.0255C61,45.1212,57,41.0176,52,41.0176ZM55.5,53.0282L50.5,53.0282C49.7,53.0282,49,52.327600000000004,49,51.5269L49,45.5216C49,44.7209,49.7,44.0203,50.5,44.0203C51.3,44.0203,52,44.7209,52,45.5216L52,50.0255L55.5,50.0255C56.3,50.0255,57,50.7262,57,51.5269C57,52.327600000000004,56.3,53.0282,55.5,53.0282Z" fill="#FFFFFF" fill-opacity="1"/></g></g></svg>

1
src/assets/images/menuIcon/s_ore.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><path d="M51.951499999999996,39.8059C50.843199999999996,40.323899999999995,49.9413,40.7615,48.9636,41.225899999999996C48.4242,40.9535,47.7542,40.408699999999996,47.004000000000005,40.2435C44.3744,39.6987,41.8501,42.1279,41.9554,44.9411C41.9554,45.378699999999995,41.593,46.0619,41.2348,46.1958C39.8694,46.687,39.2499,47.723,39.174099999999996,49.0894C39.0982,51.2194,38.9423,53.4297,41.5467,54.2513C41.7531,54.3049,41.829,54.7693,41.959599999999995,55.0417C41.652,55.2069,41.3149,55.5329,41.0072,55.5329C37.5305,55.5597,34.0496,55.5597,30.5729,55.5597C28.97572,55.5597,27.37854,55.5865,25.78137,55.5597C23.745912,55.5061,23,54.6577,23,52.527699999999996L23,23.88686C23,21.895306,23.720627,21.0468861,25.62966,21.020094C33.539699999999996,20.99330188,41.4497,20.99330188,49.364000000000004,21.020094C51.037,21.020094,51.9136,21.895306,51.9388,23.83327C52.0021,29.18278,51.951499999999996,34.5635,51.951499999999996,39.8059ZM37.6232,24.75761C37.6232,24.730809999999998,37.6232,24.730809999999998,37.6232,24.75761C35.2001,24.75761,32.776920000000004,24.730809999999998,30.35798,24.75761C29.17379,24.75761,28.19188,25.76678,28.21717,26.86079C28.26774,27.9816,29.144289999999998,28.79876,30.35798,28.79876C35.0737,28.79876,39.763999999999996,28.79876,44.4797,28.77197C45.950500000000005,28.77197,46.591,28.00839,46.565799999999996,26.56161C46.5405,25.44081,45.765100000000004,24.78886,44.4797,24.78886C42.183,24.730809999999998,39.915800000000004,24.75761,37.6232,24.75761ZM33.7841,36.3899C35.0189,36.3899,36.2578,36.4435,37.4673,36.3631C38.445,36.3095,39.1951,35.7335,39.2963,34.6171C39.4269,33.3624,38.6515,32.4336,37.6485,32.38C35.0737,32.2416,32.46928,32.4336,29.8902,32.5184C28.68073,32.5452,28.242449999999998,33.5544,28.26774,34.568C28.29302,35.7424,29.09372,36.3988,30.25262,36.3988L33.7841,36.3988L33.7841,36.3899ZM56.9495,50.3441C57.156,51.326499999999996,56.7177,51.9294,55.8412,52.3089C54.2693,52.9921,53.856300000000005,53.7825,54.1934,55.5016C54.3999,56.5644,53.7046,57.002,53.0851,57.4128C52.4403,57.8236,51.7956,58.3952,50.893699999999995,57.6048C49.6295,56.4572,48.727599999999995,56.6225,47.210499999999996,57.5245C46.6964,57.8236,45.8198,57.7968,45.2256,57.578C44.504999999999995,57.3057,43.7549,56.8145,43.9867,55.6669C44.3491,53.8941,43.5231,52.7465,42.081900000000005,52.143699999999995C40.9988,51.6793,41.1547,50.7237,41.18,49.9869C41.2053,49.415400000000005,41.6436,48.566900000000004,42.1071,48.3213C43.5231,47.584599999999995,44.1679,47.0085,44.0415,44.6062C43.965599999999995,43.324600000000004,44.787400000000005,43.021,45.4827,42.695C45.9463,42.4494,46.8228,42.3958,47.185199999999995,42.695C48.5001,43.815799999999996,49.7348,43.7577,50.948499999999996,42.7218C52.0821,41.7662,52.7269,42.775400000000005,53.5529,43.2398C54.3536,43.6774,54.2988,44.2757,54.0923,45.0706C53.7847,46.298500000000004,54.4547,47.6917,55.6136,48.0757C56.7177,48.4062,57.0802,49.143,56.9495,50.3441ZM45.7145,49.9333C45.6892,52.143699999999995,46.9787,53.5905,49.039500000000004,53.6173C50.7673,53.6441,52.259100000000004,52.2509,52.313900000000004,50.585300000000004C52.3645,48.2365,51.0497,46.682500000000005,48.9383,46.5977C47.210499999999996,46.5486,45.7398,48.049,45.7145,49.9333Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/menuIcon/s_point.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_94_4654"><rect x="18" y="18" width="44" height="44" rx="0"/></clipPath></defs><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g clip-path="url(#master_svg0_94_4654)"><g><path d="M39.9964013671875,20.74951171875C31.6590513671875,20.74951171875,24.8739013671875,27.53466171875,24.8739013671875,35.87201171875C24.8739013671875,43.92101171875,38.4294013671875,58.21571171875,39.0059013671875,58.82171171875C39.2646013671875,59.09521171875,39.6268013671875,59.25041171875,40.0038013671875,59.25041171875L40.0333013671875,59.25041171875C40.4177013671875,59.25041171875,40.7872013671875,59.07311171875,41.0385013671875,58.77741171875L45.7320013671875,53.40401171875C51.9702013671875,45.76881171875,55.126201367187505,39.87061171875,55.126201367187505,35.87941171875C55.126201367187505,27.53471171875,48.3411013671875,20.74955640795,39.9964013671875,20.74951171875ZM39.9964013671875,42.745811718750005C36.1973013671875,42.745811718750005,33.1225213671875,39.67101171875,33.1225213671875,35.87201171875C33.1225213671875,32.07291171875,36.1973013671875,28.998131718750003,39.9964013671875,28.998131718750003C43.7954013671875,28.998131718750003,46.870201367187505,32.07291171875,46.870201367187505,35.87201171875C46.870201367187505,39.67101171875,43.7954013671875,42.745811718750005,39.9964013671875,42.745811718750005Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/s_ps.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_94_4553"><rect x="21" y="59" width="38" height="38" rx="0"/></clipPath></defs><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#EEEFF8" fill-opacity="1"/></g><g transform="matrix(1,0,0,-1,0,118)" clip-path="url(#master_svg0_94_4553)"><g><path d="M56.9528,97L23.04725,97C21.916585,97,21,96.0834,21,94.9528L21,61.04725C21,59.91675,21.91675,59,23.04725,59L56.9551,59C58.0832,59,59,59.91675,59,61.04725L59,94.9551C58.9987,96.0849,58.0825,97,56.9528,97ZM50.8134,83.21549999999999L50.8134,64.88525C50.8108,64.25542,50.300799999999995,63.74548,49.671,63.74288C49.0412,63.74548,48.5312,64.25541,48.5286,64.88525L48.5286,83.2226C46.297200000000004,83.8023,44.843599999999995,85.9491,45.1338,88.2362C45.424099999999996,90.5233,47.3679,92.239,49.6734,92.24289999999999C51.9827,92.2411,53.9304,90.52250000000001,54.2198,88.2313C54.5091,85.9402,53.0497,83.7914,50.8134,83.21549999999999ZM41.142399999999995,73.5754L41.142399999999995,64.90663C41.1398,64.27679,40.6298,63.76685,40,63.76425C39.3702,63.76685,38.8602,64.27679,38.857600000000005,64.90663L38.857600000000005,73.5754C36.839,74.1033,35.4307,75.9268,35.430099999999996,78.0133C35.4296,80.0999,36.8369,81.9241,38.8553,82.4531L38.8553,91.1219C38.8553,91.74889999999999,39.370599999999996,92.2642,39.9976,92.2642C40.6275,92.2616,41.1374,91.7517,41.14,91.1219L41.14,82.4531C43.1652,81.93209999999999,44.5811,80.10640000000001,44.5816,78.0152C44.5822,75.924,43.1673,74.0975,41.142399999999995,73.5754ZM30.33138,63.73575C28.02941,63.74415,26.09074,65.45857,25.80085,67.74223C25.51095,70.02590000000001,26.95977,72.1703,29.186619999999998,72.7536L29.186619999999998,91.09100000000001C29.186619999999998,91.718,29.701999999999998,92.2334,30.329,92.2334C30.95883,92.2308,31.4688,91.7208,31.4714,91.09100000000001L31.4714,72.7536C33.7053,72.1781,35.1629,70.0312,34.873599999999996,67.74254C34.584199999999996,65.45384,32.6383,63.73726,30.33138,63.73575Z" fill="#4F85FB" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/s_setting.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><g><path d="M57.7309,36.6424L54.4199,35.1065C52.2821,34.1115,51.0169,31.80957,51.2919,29.41513L51.7134,25.70348C49.9764,24.13487,47.9673,22.91636,45.7913,22.111649L42.809,24.29289C40.9002,25.70218,38.3223,25.67794,36.438900000000004,24.23298L33.5495,22C31.3612,22.766417,29.33189,23.9468,27.56639,25.48018L27.92691,29.18911C28.16995,31.58721,26.871940000000002,33.8705,24.71933,34.8315L21.35269,36.3074C20.9039103,38.6357,20.883231,41.0297,21.291719,43.3658L24.60269,44.9071C26.74368,45.8995,28.01241,48.202,27.73869,50.5985L27.30925,54.2911C29.0484,55.858,31.056800000000003,57.0779,33.2313,57.8884L36.1897,55.7098C38.098,54.2997,40.6759,54.3229,42.559799999999996,55.767L45.4705,58C47.6601,57.2361,49.6906,56.0565,51.456199999999995,54.5225L51.0984,50.8054C50.8651,48.409099999999995,52.158699999999996,46.1352,54.306,45.1685L57.6461,43.6953C58.0967,41.3643,58.1179,38.9679,57.7044,36.6287L57.7309,36.6424ZM39.5113,49.514700000000005C34.3981,49.514700000000005,30.25307,45.2566,30.25307,40.0041C30.25307,34.7515,34.3981,30.49349,39.5113,30.49349C44.6245,30.49349,48.7696,34.7515,48.7696,40.0041C48.7696,45.2566,44.6245,49.514700000000005,39.5113,49.514700000000005Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M39.503226597900394,32.666666984558105C35.85293659790039,32.6648691245581,32.89285659790039,35.650166984558105,32.89285659790039,39.3333369845581C32.89285659790039,43.01646698455811,35.85293659790039,46.0017669845581,39.503226597900394,45.99996698455811C43.15095659790039,45.998166984558104,46.10715659790039,43.01396698455811,46.10715659790039,39.3333369845581C46.10715659790039,35.65270698455811,43.15095659790039,32.66846320455811,39.503226597900394,32.666666984558105ZM39.503226597900394,43.0462669845581C37.535416597900394,42.95376698455811,35.98716659790039,41.316986984558106,35.98716659790039,39.329296984558106C35.98716659790039,37.34159698455811,37.535416597900394,35.704856984558106,39.503226597900394,35.61227698455811C41.495636597900386,35.7097269845581,43.08915659790039,37.317586984558105,43.185756597900394,39.3279469845581C43.17395659790039,41.372516984558104,41.52956659790039,43.024566984558106,39.503226597900394,43.0274669845581L39.503226597900394,43.0462669845581Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></g></svg>

1
src/assets/images/menuIcon/s_user.svg

@ -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="80" height="80" viewBox="0 0 80 80"><g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="#479CF1" fill-opacity="1"/></g><g><path d="M29.44471,32.3043C29.44472,37.9952,34.0687,42.608599999999996,39.772800000000004,42.608599999999996C45.4768,42.608599999999996,50.100899999999996,37.9952,50.100899999999996,32.3043C50.100899999999996,26.6134,45.4768,22,39.772800000000004,22C34.0687,22,29.44472,26.6134,29.44471,32.3043ZM55.678,46.5004L51.0002,46.5004C50.2702,46.5004,49.678200000000004,45.9097,49.678200000000004,45.1814C49.678200000000004,44.4531,50.2702,43.8625,51.0002,43.8625L55.678,43.8625C56.408,43.8625,57,44.4531,57,45.1814C57,45.9097,56.408,46.5004,55.678,46.5004ZM55.678,52.2502L47.580799999999996,52.2502C46.8508,52.2502,46.2588,51.6595,46.2588,50.931200000000004C46.2588,50.2029,46.8508,49.612300000000005,47.580799999999996,49.612300000000005L55.678,49.612300000000005C56.408,49.612300000000005,57,50.2029,57,50.931200000000004C57,51.6595,56.408,52.2502,55.678,52.2502ZM55.678,58L47.580799999999996,58C46.8508,58,46.2588,57.4094,46.2588,56.681C46.2588,55.9527,46.8508,55.3621,47.580799999999996,55.3621L55.678,55.3621C56.408,55.3621,57,55.9527,57,56.681C57,57.4094,56.408,58,55.678,58ZM41.260000000000005,52.9303C41.260000000000005,48.602900000000005,43.934200000000004,44.898700000000005,47.723299999999995,43.3724C48.3662,43.113600000000005,48.4289,42.229,47.825,41.8898C45.435,40.546099999999996,42.6911,39.782,39.772800000000004,39.782C30.50933,39.782,23,47.4797,23,56.9757C23,57.0475,23.000413211,57.1188,23.00123932,57.1901C23.0066098,57.6398,23.376768,58,23.827485,58L41.2753,58C41.865700000000004,58,42.262299999999996,57.4015,42.037099999999995,56.857C41.5364,55.6469,41.260000000000005,54.3209,41.260000000000005,52.9303Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/password_icon.svg

@ -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="32.66561508178711" height="39.13572692871094" viewBox="0 0 32.66561508178711 39.13572692871094"><g><path d="M29.768,16.829C29.4345,16.829,27.5584,16.8498,27.204,16.8498L27.204,10.9347C27.204,4.37387,22.9722,0.0208277,16.3641,0C9.75591,0,5.4408,4.58215,5.4408,10.9347L5.4408,16.7873C5.21149,16.7873,2.8142,16.8082,2.60574,16.8082C1.02145,16.8082,0,18.162,0,19.6199L0,36.2615C0,37.9069,0.87553,39.1357,2.56405,39.1357L29.8514,39.1357C31.1647,39.1357,32.6656,37.9485,32.6656,35.8033L32.6656,19.9948C32.6656,18.3703,32.1236,16.829,29.768,16.829ZM19.9704,31.7626C19.9704,33.8246,18.3444,35.4908,16.3432,35.4908C14.342,35.4908,12.716,33.8246,12.716,31.7626L12.716,31.7001C12.716,30.3255,13.4456,29.1175,14.5296,28.4718L14.5296,21.5986C14.5296,20.6197,15.3009,20.5155,16.2598,20.5155C17.2188,20.5155,18.1568,20.6197,18.1568,21.5986L18.1568,28.4718C19.2408,29.1175,19.9704,30.3255,19.9704,31.7001L19.9704,31.7626ZM23.6185,16.7873L9.08884,16.7873L9.08884,9.28927C9.08884,5.68603,13.1121,3.7282,16.1348,3.7282L16.8018,3.7282C19.8245,3.7282,23.6185,5.54024,23.6185,9.28927L23.6185,16.7873Z" fill="#1989FA" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

1
src/assets/images/run.svg

@ -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="36" height="36" viewBox="0 0 36 36"><g><path d="M0.0338876,21.6006C0.791888,25.2568,2.6603,28.5461,5.43529,31.1111C5.80569,31.454,6.31565,31.6116,6.8194,31.5389C7.3235,31.4665,7.76624,31.1719,8.02131,30.7391L10.1884,27.0549C10.5503,26.4391,10.4661,25.6645,9.97991,25.1375C8.84698,23.9069,8.02102,22.4346,7.56723,20.8368C7.36685,20.128,6.70975,19.6374,5.96078,19.6374L1.66693,19.6374C1.16648,19.6372,0.692517,19.8581,0.376395,20.2389C0.0591609,20.619,-0.0666573,21.1192,0.0338876,21.6006ZM22.0852,29.174C21.7232,28.5559,20.9949,28.2395,20.2854,28.3921C18.4901,28.7781,16.6239,28.7054,14.8655,28.1807C14.1235,27.9594,13.3239,28.2689,12.9355,28.9278L10.808,32.5469C10.5628,32.9646,10.5176,33.4671,10.6845,33.9204C10.8509,34.3741,11.2133,34.7322,11.6745,34.8985C13.6899,35.6293,15.8187,36,17.9994,36C19.8024,36,21.5824,35.7444,23.2887,35.2393C23.7758,35.0946,24.1692,34.7399,24.3574,34.2758C24.545,33.8109,24.5056,33.2873,24.2505,32.8545L22.0852,29.174ZM29.7455,4.17944C29.4462,3.9339,29.0685,3.79934,28.6784,3.79924C28.5817,3.79924,28.4831,3.80922,28.3864,3.82559C27.9025,3.91049,27.4815,4.20075,27.2359,4.61875L25.1037,8.24068C24.7167,8.90032,24.8432,9.73465,25.4092,10.255C26.8597,11.5847,27.9059,13.2833,28.4313,15.1619C28.6304,15.8724,29.2886,16.3647,30.0393,16.3649L34.3337,16.3649C34.8331,16.3646,35.3062,16.1445,35.6226,15.7652C35.9401,15.3857,36.0664,14.886,35.9664,14.4048C35.1469,10.4185,32.9378,6.78689,29.7455,4.17944ZM24.3574,1.72602C24.1697,1.26149,23.7761,0.906541,23.2887,0.762205C21.5731,0.255605,19.791,-0.00119639,17.9994,0.00000381258C15.8187,0.00000381258,13.6899,0.370486,11.6745,1.10122C10.7057,1.45352,10.2924,2.57637,10.808,3.45511L12.9355,7.07371C13.3239,7.73262,14.1235,8.04214,14.8655,7.82082C15.8814,7.51699,16.9376,7.3629,17.9996,7.3636C18.7626,7.3636,19.5323,7.44547,20.2854,7.60794C20.9944,7.76016,21.7222,7.44468,22.0852,6.82783L24.2508,3.1468C24.5058,2.71413,24.5451,2.1907,24.3574,1.72602ZM34.3337,19.6371L30.0393,19.6371C29.2884,19.6367,28.63,20.1292,28.4313,20.8399C27.9057,22.7185,26.8595,24.4171,25.4092,25.747C24.8431,26.2665,24.7165,27.1004,25.1037,27.7593L27.2359,31.3828C27.4812,31.8011,27.9024,32.0915,28.3864,32.1762C28.4832,32.1926,28.5817,32.2008,28.6784,32.2008C29.0683,32.2013,29.446,32.0673,29.7455,31.8223C32.9378,29.2131,35.1469,25.583,35.9665,21.5972C36.0665,21.1161,35.9402,20.6163,35.6226,20.2368C35.3066,19.857,34.8333,19.6368,34.3337,19.6371ZM0.376135,15.7632C0.692116,16.1438,1.16603,16.3647,1.66666,16.3647L5.96105,16.3647C6.71021,16.3644,7.36726,15.8738,7.5675,15.1652C8.02109,13.5669,8.84706,12.0941,9.98017,10.863C10.4664,10.3367,10.5507,9.56236,10.1887,8.9471L8.02157,5.263C7.76613,4.8302,7.3237,4.53522,6.81966,4.46166C6.73946,4.45042,6.65853,4.44495,6.57751,4.44528C6.1568,4.44528,5.746,4.60263,5.43555,4.89099C2.6603,7.45571,0.791888,10.7448,0.0338876,14.4012C-0.0665431,14.8826,0.0591547,15.3828,0.376135,15.7632Z" fill="#4F85FB" fill-opacity="1"/></g></svg>

1
src/assets/images/solution.svg

@ -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="8" height="17" viewBox="0 0 8 17"><g><path d="M5.81818,10.625L2.18182,10.625L2.18182,2.125L1.45455,2.125L1.45455,14.5208C1.45455,15.8879,2.59636,17,4,17C5.40364,17,6.54546,15.8879,6.54546,14.5208L6.54546,2.125L5.81818,2.125L5.81818,10.625ZM6.90909,2.125L1.09091,2.125C0.489454,2.125,0,1.64829,0,1.0625C0,0.476708,0.489454,0,1.09091,0L6.90909,0C7.51055,0,8,0.476708,8,1.0625C8,1.64829,7.51055,2.125,6.90909,2.125ZM1.09091,0.708333C0.890148,0.708429,0.72745,0.866967,0.72745,1.0625C0.72745,1.25803,0.890148,1.41657,1.09091,1.41667L6.90909,1.41667C7.10992,1.41667,7.27273,1.2581,7.27273,1.0625C7.27273,0.866899,7.10992,0.708333,6.90909,0.708333L1.09091,0.708333Z" fill="#2892F3" fill-opacity="1"/></g></svg>

1
src/assets/images/success.svg

@ -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="70" height="70" viewBox="0 0 70 70"><defs><clipPath id="master_svg0_685_8843"><rect x="0" y="0" width="70" height="70" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8843)"><g><path d="M35,70C15.6712,70,0,54.3288,0,35C0,15.6712,15.6712,0,35,0C54.3288,0,70,15.6712,70,35C70,54.3288,54.3288,70,35,70ZM27.195,48.7433C28.6189,50.1676,30.9278,50.1676,32.3517,48.7433L54.4542,26.6408C55.8781,25.2169,55.8781,22.9081,54.4542,21.4842C53.0302,20.0602,50.7215,20.0602,49.2975,21.4842L29.6158,40.8508L20.8075,32.0425C19.3838,30.6166,17.0736,30.6158,15.6488,32.0405C14.2241,33.4653,14.225,35.7755,15.6508,37.1992L27.195,48.7433Z" fill="#14A656" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

22
src/assets/images/user-cancel.svg

@ -0,0 +1,22 @@
<svg width="108" height="108" viewBox="0 0 108 108" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_447_4258)">
<circle cx="54" cy="50" r="50" fill="url(#paint0_linear_447_4258)"/>
<path d="M54 45.1119L71.1119 28L76 32.8881L58.8881 50L76 67.1119L71.1119 72L54 54.8881L36.8881 72L32 67.1119L49.1119 50L32 32.8881L36.8881 28L54 45.1119Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_447_4258" x="0" y="0" width="108" height="108" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.877278 0 0 0 0 0.28742 0 0 0 0 0.421121 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_447_4258"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_447_4258" result="shape"/>
</filter>
<linearGradient id="paint0_linear_447_4258" x1="30.5" y1="17" x2="84.5" y2="100" gradientUnits="userSpaceOnUse">
<stop stop-color="#F08564"/>
<stop offset="1" stop-color="#EA467D"/>
</linearGradient>
</defs>
</svg>

1
src/assets/images/user.svg

@ -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="40" height="40" viewBox="0 0 40 40"><defs><clipPath id="master_svg0_609_03555/609_03497"><rect x="8" y="8" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="40" height="40" rx="20" fill="#1989FA" fill-opacity="1"/><g clip-path="url(#master_svg0_609_03555/609_03497)"><g><path d="M28.120604907226564,25.896875C27.67840490722656,24.849575,27.03680490722656,23.898375,26.231504907226565,23.096075C25.428604907226564,22.291475,24.47750490722656,21.649974999999998,23.430704907226563,21.207075C23.421304907226563,21.202375,23.41200490722656,21.199975000000002,23.40260490722656,21.195275000000002C24.862704907226565,20.140625,25.812004907226562,18.422655,25.812004907226562,16.484375C25.812004907226562,13.273435,23.21040490722656,10.671875,19.99946490722656,10.671875C16.788524907226563,10.671875,14.186964907226562,13.273435,14.186964907226562,16.484375C14.186964907226562,18.422655,15.136184907226562,20.140625,16.596334907226563,21.197675C16.586964907226562,21.202375,16.577584907226562,21.204675,16.56821490722656,21.209375C15.518214907226563,21.652375,14.576024907226563,22.287475,13.767434907226562,23.098475C12.962844907226563,23.901375,12.321344907226562,24.852475,11.878369907226563,25.899175C11.443186907226563,26.924075,11.208483707226563,28.022775,11.186963515026562,29.135975C11.186337956226563,29.160975,11.190725517226563,29.185875,11.199867807226562,29.209175C11.209010107226563,29.232375,11.222722007226562,29.253675,11.240195707226562,29.271575C11.257669407226562,29.289475,11.278551207226563,29.303675,11.301610907226562,29.313375C11.324669907226562,29.323175,11.349440907226562,29.328175,11.374463907226563,29.328075C11.374463907226563,29.328075,12.780714907226562,29.328075,12.780714907226562,29.328075C12.883834907226563,29.328075,12.965864907226562,29.246075,12.968214907226562,29.145275C13.015084907226562,27.335975,13.741654907226563,25.641375,15.026024907226562,24.357075000000002C16.354934907226564,23.028174999999997,18.119774907226564,22.296875,19.99946490722656,22.296875C21.879104907226562,22.296875,23.644004907226563,23.028174999999997,24.972904907226564,24.357075000000002C26.257304907226562,25.641375,26.983804907226563,27.335975,27.030704907226564,29.145275C27.033104907226562,29.248475,27.115104907226563,29.328075,27.218204907226564,29.328075C27.218204907226564,29.328075,28.624504907226562,29.328075,28.624504907226562,29.328075C28.64950490722656,29.328175,28.674304907226563,29.323175,28.697304907226563,29.313375C28.720404907226563,29.303675,28.741304907226564,29.289475,28.758704907226562,29.271575C28.776204907226564,29.253675,28.789904907226564,29.232375,28.799104907226564,29.209175C28.808204907226564,29.185875,28.81260490722656,29.160975,28.812004907226562,29.135975C28.788504907226564,28.015675,28.55650490722656,26.925775,28.120604907226564,25.896875C28.120604907226564,25.896875,28.120604907226564,25.896875,28.120604907226564,25.896875ZM19.99946490722656,20.515625C18.923684907226562,20.515625,17.911184907226563,20.096095,17.149464907226562,19.334375C16.387744907226562,18.572655,15.968214907226564,17.560155,15.968214907226564,16.484375C15.968214907226564,15.408595,16.387744907226562,14.396094999999999,17.149464907226562,13.634375C17.911184907226563,12.872655,18.923684907226562,12.453125,19.99946490722656,12.453125C21.075244907226562,12.453125,22.087704907226563,12.872655,22.84950490722656,13.634375C23.611204907226565,14.396094999999999,24.030704907226564,15.408595,24.030704907226564,16.484375C24.030704907226564,17.560155,23.611204907226565,18.572655,22.84950490722656,19.334375C22.087704907226563,20.096095,21.075244907226562,20.515625,19.99946490722656,20.515625Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></svg>

1
src/assets/images/user_icon.svg

@ -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="33.87468338012695" height="33.84542465209961" viewBox="0 0 33.87468338012695 33.84542465209961"><g><path d="M33.8747,32.442C33.8747,25.5468,28.9971,19.6889,22.2628,17.6265C24.8808,15.9057,26.6152,12.9605,26.6152,9.61666C26.6152,4.31204,22.275,0,16.9373,0C11.5996,0,7.25944,4.31204,7.25944,9.61259C7.25944,12.9565,8.99389,15.9017,11.6118,17.6224C4.87763,19.6889,0,25.5427,0,32.442L0,33.8454L33.8747,33.8454L33.8747,32.4623L33.8747,32.442Z" fill="#1989FA" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

1
src/assets/images/wait.svg

@ -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="80" height="80" viewBox="0 0 80 80"><defs><clipPath id="master_svg0_685_8855"><rect x="0" y="0" width="80" height="80" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8855)"><g><path d="M40.00636015625,5.01953125C20.68606015625,5.01953125,5.01416254044,20.69143125,5.01416254044,40.01173125C5.01416254044,59.33203125,20.68606015625,74.99613125,40.00636015625,74.99613125C59.32666015625,74.99613125,74.99856015625,59.32423125,74.99856015625,40.00393125C74.99856015625,20.683631249999998,59.32666015625,5.01953125,40.00636015625,5.01953125ZM21.97506015625,45.97263125C18.678260156249998,45.97263125,16.00636015625,43.30073125,16.00636015625,40.00393125C16.00636015625,36.70703125,18.678260156249998,34.03513125,21.97506015625,34.03513125C25.27196015625,34.03513125,27.94386015625,36.70703125,27.94386015625,40.00393125C27.94386015625,43.30073125,25.27196015625,45.97263125,21.97506015625,45.97263125ZM39.92046015625,45.97263125C36.62356015625,45.97263125,33.95166015625,43.30073125,33.95166015625,40.00393125C33.95166015625,36.70703125,36.62356015625,34.03513125,39.92046015625,34.03513125C43.21726015625,34.03513125,45.88916015625,36.70703125,45.88916015625,40.00393125C45.88916015625,43.30073125,43.21726015625,45.97263125,39.92046015625,45.97263125ZM57.86576015625,45.97263125C54.56886015625,45.97263125,51.89696015625,43.30073125,51.89696015625,40.00393125C51.89696015625,36.70703125,54.56886015625,34.03513125,57.86576015625,34.03513125C61.16256015625,34.03513125,63.83446015625,36.70703125,63.83446015625,40.00393125C63.83446015625,43.30073125,61.16256015625,45.97263125,57.86576015625,45.97263125Z" fill="#EE8223" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

1
src/assets/images/wifi-active.svg

@ -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="42" height="34" viewBox="0 0 42 34"><g><path d="M41.5238,8.34171C30.1914,-2.78057,11.812,-2.78057,0.479575,8.34171C-0.159858,8.96929,-0.159858,9.98404,0.479575,10.6072C1.11901,11.2347,2.15289,11.2347,2.78777,10.6072C12.8459,0.735472,29.1575,0.735472,39.2156,10.6072C39.8551,11.2347,40.889,11.2347,41.5238,10.6072C42.1587,9.984,42.1587,8.96929,41.5238,8.34171ZM6.63327,15.2314C5.99383,15.859,5.99383,16.8737,6.63327,17.4968C7.2727,18.1244,8.30658,18.1244,8.94146,17.4968C15.5985,10.9632,26.3958,10.9632,33.0529,17.4968C33.6923,18.1244,34.7262,18.1244,35.3611,17.4968C36.0005,16.8692,36.0005,15.8545,35.3611,15.2314C27.4297,7.44712,14.5691,7.44712,6.63327,15.2314L6.63327,15.2314ZM29.2346,22.5395L29.2436,22.5306C24.7089,18.0799,17.358,18.0799,12.8278,22.5306C12.1883,23.1581,12.1883,24.1728,12.8278,24.7959C13.4672,25.4235,14.5011,25.4235,15.136,24.7959C18.3965,21.5959,23.6795,21.5959,26.9355,24.7959L26.9445,24.7871C26.9828,24.8337,27.0237,24.8783,27.0669,24.9206C27.7064,25.5481,28.7403,25.5481,29.3752,24.9206C30.0146,24.293,30.0146,23.2783,29.3752,22.6552C29.3253,22.6151,29.2799,22.5795,29.2346,22.5395ZM18.596,31.5966C18.596,32.924,19.6923,34,21.0448,34C22.3972,34,23.4935,32.924,23.4935,31.5966C23.4935,30.2693,22.3972,29.1932,21.0448,29.1932C19.6923,29.1932,18.596,30.2692,18.596,31.5966Z" fill="#1989FA" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

1
src/assets/images/wifi.svg

@ -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="42" height="34" viewBox="0 0 42 34"><g><path d="M41.5238,8.34171C30.1914,-2.78057,11.812,-2.78057,0.479575,8.34171C-0.159858,8.96929,-0.159858,9.98404,0.479575,10.6072C1.11901,11.2347,2.15289,11.2347,2.78777,10.6072C12.8459,0.735472,29.1575,0.735472,39.2156,10.6072C39.8551,11.2347,40.889,11.2347,41.5238,10.6072C42.1587,9.984,42.1587,8.96929,41.5238,8.34171ZM6.63327,15.2314C5.99383,15.859,5.99383,16.8737,6.63327,17.4968C7.2727,18.1244,8.30658,18.1244,8.94146,17.4968C15.5985,10.9632,26.3958,10.9632,33.0529,17.4968C33.6923,18.1244,34.7262,18.1244,35.3611,17.4968C36.0005,16.8692,36.0005,15.8545,35.3611,15.2314C27.4297,7.44712,14.5691,7.44712,6.63327,15.2314L6.63327,15.2314ZM29.2346,22.5395L29.2436,22.5306C24.7089,18.0799,17.358,18.0799,12.8278,22.5306C12.1883,23.1581,12.1883,24.1728,12.8278,24.7959C13.4672,25.4235,14.5011,25.4235,15.136,24.7959C18.3965,21.5959,23.6795,21.5959,26.9355,24.7959L26.9445,24.7871C26.9828,24.8337,27.0237,24.8783,27.0669,24.9206C27.7064,25.5481,28.7403,25.5481,29.3752,24.9206C30.0146,24.293,30.0146,23.2783,29.3752,22.6552C29.3253,22.6151,29.2799,22.5795,29.2346,22.5395ZM18.596,31.5966C18.596,32.924,19.6923,34,21.0448,34C22.3972,34,23.4935,32.924,23.4935,31.5966C23.4935,30.2693,22.3972,29.1932,21.0448,29.1932C19.6923,29.1932,18.596,30.2692,18.596,31.5966Z" fill="#DF1515" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

92
src/assets/styles/common.scss

@ -0,0 +1,92 @@
/* CSS Document */
html {
//font-family: 'PingFangSC-Regular', 'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
font-family: Source Han Sans CN, sans-serif;
height: 100vh;
font-size: 14px;
}
html, body {
overflow: hidden;
}
html,
body,
ol,
dl,
dd,
dt,
p,
h1,
h2,
h3,
h4,
h5,
h6,
form,
fieldset,
legend,
img {
margin: 0;
padding: 0;
}
fieldset {
border: none;
}
img {
display: block;
}
address,
caption,
cite,
code,
dfn,
th,
var {
font-style: normal;
font-weight: normal;
}
ul,
ol,
li {
list-style: none;
}
a {
color: #666;
text-decoration: none;
}
* {
box-sizing: border-box !important;
}
a {
&:visited {
color: inherit;
}
}
input,
button,
select,
textarea {
outline: none;
}
textarea {
resize: none;
}
input[type='number'] {
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
}
-moz-appearance: textfield;
}
.clear {
clear: both;
}
.konvajs-content{
canvas{
border: 1px solid #ccc !important;
}
}

73
src/assets/styles/element.scss

@ -0,0 +1,73 @@
:root {
// --el-font-size-base: 50px;
// --el-button-size: 80px;
--el-color-primary: #1989fa;
//--el-button-active-bg-color: linear-gradient(90deg, #0657C0 24%, #096AE0 101%);
--text-color-primary: #17213c;
//--el-color-success: rgba(88, 162, 95, 1);
//--text-color-info: #838b99;
//--el-input-border: #dae0f2;
//--el-font-weight-primary: 400;
//--color-red: #f56c6c;
//--color-green: #67c23a;
//--color-yellow: #e6a23c;
//--color-blue: --el-color-primary;
//--el-font-family: 'PingFangSC-Regular', 'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
--el-font-family: Source Han Sans CN, sans-serif;
}
.el-dialog {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin: 0;
padding: 0;
.el-dialog__header {
background: rgba(0, 0, 0, .03);
padding: 10px;
}
.el-dialog__body {
padding: 10px 20px;
}
.el-dialog__footer {
padding: 10px;
}
}
.el-input-group__append {
padding: 0 10px;
.el-icon {
margin: 0;
}
}
.init-message {
.el-message-box__content {
.el-message-box__container {
align-items: flex-start;
ul {
padding-left: 10px;
font-size: 15px;
li {
font-weight: 700;
color: #FE0A0A;
}
}
}
}
}
.button-popper {
inset: auto 242px 20px auto !important;
.el-popper__arrow {
top: 100px !important;
}
}
.el-message__content {
font-size: 16px;
}

3
src/assets/styles/main.scss

@ -0,0 +1,3 @@
@use './common.scss';
@use './element.scss';

5
src/assets/styles/variable.scss

@ -0,0 +1,5 @@
$primary-color: #1989FA;
$success-color: #14A656;
$danger-color: #DF1515;
$warn-color: #EE8223;
$info-color: #909399;

158
src/components/common/FTButton/index.vue

@ -0,0 +1,158 @@
<script setup lang="ts">
import { ref } from 'vue'
interface FTButton {
type?: 'default' | 'primary' | 'info' | 'danger'
size?: 'small' | 'default' | 'large'
disabled?: boolean
loading?: boolean
clickHandle?: () => any
}
const props = withDefaults(defineProps<FTButton>(), {
type: 'default',
size: 'default',
disabled: false,
loading: false,
clickHandle: () => {},
})
const isLoading = ref(false)
async function handleClick() {
if (!props.clickHandle || isLoading.value)
return
isLoading.value = true // loading
try {
await props.clickHandle() //
}
finally {
isLoading.value = false // loading
}
}
const setLoading = (loading: boolean) => {
isLoading.value = loading
}
defineExpose({
setLoading,
})
</script>
<template>
<div class="ft-button" :class="{ 'ft-button-disabled': disabled || isLoading, [`ft-button-${size}`]: true }" @click="handleClick">
<!-- 添加 loading 判断 -->
<div v-show="disabled || isLoading" class="my-button-shadow" /> <!-- 添加 loading 判断 -->
<div
class="my-button" :class="{
[`my-button-${type}`]: true,
[`my-button-${size}`]: true,
'button-disabled': disabled || isLoading, // loading
}"
>
<el-icon v-if="isLoading" :color="type === 'default' ? '#26509C' : '#fff'">
<!-- 添加 loading 判断 -->
<Loading class="rotate-loading" /> <!-- 添加旋转类 -->
</el-icon>
<slot />
</div>
</div>
</template>
<style scoped lang="scss">
.ft-button {
position: relative;
display: inline-block;
margin-right: 10px;
}
.ft-button-small {
margin-right: 5px;
}
.ft-button-disabled {
pointer-events: none;
}
.my-button-shadow {
position: absolute;
width: 100%;
height: 100%;
z-index: 100;
}
.my-button {
height: 30px;
padding: 5px 20px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 14px;
//width: fit-content;
position: relative;
.el-icon {
position: absolute;
left: 5px;
svg {
width: 35px;
}
}
}
.button-disabled {
opacity: 0.5;
}
.my-button-large {
height: 40px;
font-size: 14px;
padding: 3px 15px;
.el-icon {
position: absolute;
left: 3px;
svg {
width: 25px;
}
}
}
.my-button-small {
height: 25px;
font-size: 12px;
padding: 3px 15px;
.el-icon {
position: absolute;
left: 3px;
svg {
width: 25px;
}
}
}
.my-button-default {
background: #fff;
color: $primary-color;
border: 1px solid $primary-color;
}
.my-button-primary {
background: $primary-color;
color: #fff;
border: 1px solid $primary-color;
}
.my-button-info {
background: #335AA5;
color: #fff;
border: 1px solid #335AA5;
}
.my-button-danger {
background: #e74444;
color: #fff;
border: 1px solid #e74444;
}
.rotate-loading {
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>

81
src/components/common/FTChart/index.vue

@ -0,0 +1,81 @@
<script lang="ts" setup>
import type { EChartsOption } from 'echarts/types/dist/shared'
import * as echarts from 'echarts'
import { markRaw, nextTick, onMounted, ref, watch } from 'vue'
interface Props {
option?: EChartsOption
}
const props = withDefaults(defineProps<Props>(), {
option: undefined,
})
const emits = defineEmits(['onClick', 'getInstance'])
const chart = ref()
let myChart: undefined | echarts.ECharts
onMounted(() => {
setOption()
window.addEventListener('resize', () => {
resize()
})
})
const setOption = () => {
myChart = echarts.getInstanceByDom(chart.value as HTMLElement)
if (!myChart) {
myChart = markRaw(echarts.init(chart.value as HTMLElement, null, { renderer: 'svg' }))
}
const series = myChart?.getOption()?.series
myChart.clear()
if (props.option) {
const option = markRaw(props.option)
if (series && series?.length > 0) {
option.series = series
}
myChart?.setOption(option, true)
setTimeout(() => {
resize()
}, 100)
}
myChart.on('click', (params) => {
emits('onClick', params)
})
emits('getInstance', myChart)
}
const updateOption = (data: any) => {
myChart?.setOption(data)
}
const resize = () => {
nextTick(() => {
const option = myChart?.getOption()
option && myChart?.setOption(option, { notMerge: true })
myChart?.resize()
})
}
watch(
() => props.option,
() =>
nextTick(() => {
console.log('有变化了', props.option)
setOption()
}),
{ deep: true },
)
defineExpose({
resize,
updateOption,
})
</script>
<template>
<div ref="chart" class="my-chart" />
</template>
<style lang="scss" scoped>
.my-chart {
width: 100%;
height: 100%;
}
</style>

108
src/components/common/FTDatetime/index.vue

@ -0,0 +1,108 @@
<script setup lang="ts">
import { getTime, setTime } from 'apis/system'
import { FtMessage } from 'libs/message'
import { formatDateTime } from 'libs/utils'
import { onMounted, onUnmounted, ref } from 'vue'
const serverTime = ref<number | undefined>() //
const clientFetchTime = ref<number | null>(null) //
const currentTime = ref<string>('0001/00/00 00:00:00')
const editVisible = ref(false)
let interval: number | null = null
onMounted(async () => {
try {
await getDateTime()
}
catch (error) {
// currentTime.value = formatDateTime(undefined, new Date())
console.error('获取服务器时间失败')
}
})
const openDialog = () => {
form.value.epochMilli = serverTime.value
editVisible.value = true
}
const closeDialog = () => {
editVisible.value = false
}
const getDateTime = async () => {
serverTime.value = (await getTime())?.epochMilli
clientFetchTime.value = Date.now()
let num = 0
if (interval)
clearInterval(interval)
interval = window.setInterval(async () => {
if (num > 60) {
serverTime.value = (await getTime())?.epochMilli
clientFetchTime.value = Date.now()
num = 0
}
if (serverTime.value && clientFetchTime.value) {
const elapsed = Date.now() - clientFetchTime.value
const currentServerTime = serverTime.value + elapsed
currentTime.value = formatDateTime(undefined, new Date(currentServerTime))
num++
}
}, 1000)
}
const setDateTime = async (time: number) => {
await setTime({ epochMilli: time })
await getDateTime()
}
const form = ref<{ epochMilli?: number }>({})
const formRef = ref()
const rules = {
epochMilli: [
{ required: true, message: '请选择时间', trigger: 'change' },
],
}
const okHandle = async () => {
try {
const valid = await formRef.value.validate()
if (!valid) {
return
}
await setDateTime(form.value.epochMilli as number)
FtMessage.success('修改成功')
closeDialog()
}
catch (e) {
console.log(e)
}
}
onUnmounted(() => {
if (interval)
clearInterval(interval)
})
</script>
<template>
<span @click="openDialog">{{ currentTime }}</span>
<ft-dialog :visible="editVisible" title="设置日期与时间" width="40%" :ok-handle="okHandle" @cancel="closeDialog">
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto">
<el-form-item label="日期与时间" prop="epochMilli">
<el-date-picker
v-model="form.epochMilli"
:show-now="false"
format="YYYY-MM-DD hh:mm:ss"
value-format="x"
style="width: 100%"
type="datetime"
placeholder="请选择日期和时间"
/>
</el-form-item>
</el-form>
</ft-dialog>
</template>

82
src/components/common/FTDialog/index.vue

@ -0,0 +1,82 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
const props = defineProps({
title: {
type: String,
default: '',
},
visible: {
type: Boolean,
default: false,
},
width: {
type: String,
default: '50%',
},
okHandle: {
type: Function,
default: () => {},
},
loading: {
type: Boolean,
default: false,
},
})
const emits = defineEmits(['update:visible', 'ok', 'cancel'])
const cancel = () => {
show.value = false
emits('cancel')
}
const show = ref(false)
watch(
() => props.visible,
(newVal) => {
show.value = newVal
},
{
//
deep: true,
immediate: true,
},
)
</script>
<template>
<el-dialog
v-model="show"
center
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
destroy-on-close
append-to-body
:title="title"
:width="width"
:before-close="cancel"
>
<div v-loading="loading">
<slot />
</div>
<template #footer>
<div v-if="$slots.footer" class="dialog-footer">
<slot name="footer" />
</div>
<div v-else class="dialog-footer">
<ft-button :click-handle="cancel">
取消
</ft-button>
<ft-button type="primary" :click-handle="okHandle">
确认
</ft-button>
</div>
</template>
</el-dialog>
</template>
<style scoped lang="scss">
</style>

35
src/components/common/FTImage/index.vue

@ -0,0 +1,35 @@
<script setup lang="ts">
import { Knova } from 'knova'
// knova
const knovaInstance = ref<Knova | null>(null)
const images = ref([
'https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
'https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
])
onMounted(() => {
const container = document.getElementById('knova-container')
if (container) {
// knova
knovaInstance.value = new Knova(container, {
items: images.value.map(src => ({
src,
type: 'image',
})),
gestures: true, //
zoom: true, //
doubleTap: true, //
})
}
})
</script>
<template lang="pug">
div#knova-container
</template>
<style scoped lang="scss">
</style>

356
src/components/common/FTInput/index.vue

@ -0,0 +1,356 @@
<script setup lang="ts">
import 'simple-keyboard/build/css/index.css'
import Keyboard from 'simple-keyboard'
import layout from 'simple-keyboard-layouts/build/layouts/chinese.js'
import { useDeviceStore } from 'stores/deviceStore'
import { computed, onUnmounted, ref } from 'vue'
defineOptions({
inheritAttrs: false,
})
const props = defineProps({
layoutName: {
type: String,
default: 'default',
},
// layoutNamenumber
precision: {
type: Number,
default: 2,
},
})
const emits = defineEmits(['onChange', 'enter', 'close', 'focus'])
const deviceStore = useDeviceStore()
const deviceType = computed(() => {
return __DEVICE_TYPE__
})
const model = defineModel()
const keyboard = ref<any>(null)
const visible = ref(false)
const inputRef = ref()
const popoverRef = ref()
const entering = ref(false)
const width = ref(800)
if (props.layoutName === 'number')
width.value = 300
const displayDefault = ref({
'{bksp}': 'backspace',
'{lock}': 'caps',
'{enter}': '回车',
'{tab}': 'tab',
'{shift}': 'shift',
'{change}': 'en',
'{space}': 'space',
'{clear}': '清空',
'{close}': '关闭',
'{arrowleft}': '←',
'{arrowright}': '→',
})
const open = () => {
if (visible.value)
return
inputRef.value.focus()
emits('focus')
visible.value = true
}
const focusInput = (e: any) => {
const rect = e.target.getBoundingClientRect()
const scrollTop = window.scrollY || document.documentElement.scrollTop
console.log(rect.top + scrollTop)
if (window.innerHeight - rect.bottom < 300) {
placement.value = 'top'
}
else {
placement.value = 'bottom'
}
if (visible.value)
return
if (deviceType.value !== deviceStore.deviceTypeMap.LargeSpaceDM_B)
visible.value = true
}
emits('focus')
// const blurInput = debounce(() => {
// if (!entering.value) {
// handleClose()
// } else {
// entering.value = false
// }
// }, 100)
const blurInput = () => {
if (ignoreBlur.value) {
ignoreBlur.value = false
return
}
setTimeout(() => {
if (!entering.value) {
handleClose()
}
else {
entering.value = false
}
}, 100)
}
const afterEnter = () => {
//
const prevKeyboard = document.querySelectorAll('.init-keyboard')
if (prevKeyboard.length > 0)
prevKeyboard[0]?.remove()
keyboard.value = new Keyboard('simple-keyboard', {
onChange,
onKeyPress,
onInit,
layout: {
//
default: [
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
'{tab} q w e r t y u i o p [ ] \\',
'{lock} a s d f g h j k l ; \' {enter}',
'{change} z x c v b n m , . / {clear}',
'{arrowleft} {arrowright} {space} {close}',
],
//
shift: [
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
'{tab} Q W E R T Y U I O P { } |',
'{lock} A S D F G H J K L : " {enter}',
'{change} Z X C V B N M < > ? {clear}',
'{arrowleft} {arrowright} {space} {close}',
],
//
number: ['7 8 9', '4 5 6', '1 2 3', '. 0 {bksp}', '{arrowleft} {arrowright} {clear} {close}'],
},
layoutName: props.layoutName,
display: displayDefault.value,
theme: 'hg-theme-default init-keyboard', // class
})
}
const beforeLeave = () => {
visible.value = false
entering.value = false
inputRef.value.blur()
displayDefault.value['{change}'] = 'en'
document.removeEventListener('click', handlePopClose)
}
const onInit = (keyboard: any) => {
keyboard.setInput(model.value)
keyboard.setCaretPosition(inputRef.value?.ref.selectionEnd)
document.addEventListener('click', handlePopClose)
}
const onChange = (input: any) => {
ignoreBlur.value = true
model.value = input
setTimeout(() => {
ignoreBlur.value = false
}, 150)
emits('onChange', input)
}
const onKeyPress = (button: any) => {
ignoreBlur.value = true
if (button === '{lock}')
return handleLock()
if (button === '{change}')
return handleChange()
if (button === '{clear}')
return handleClear()
if (button === '{enter}')
return handleEnter()
if (button === '{close}')
return handleClose()
if (button === '{arrowleft}')
return handleArrow(0)
if (button === '{arrowright}')
return handleArrow(1)
if (button === '{bksp}')
return handleBackspace()
}
const ignoreBlur = ref(false)
const handleBackspace = () => {
ignoreBlur.value = true
const input = model.value?.toString() || ''
let index: number | null
//
const start = keyboard.value.getCaretPosition()
const end = keyboard.value.getCaretPositionEnd()
model.value = input.slice(0, start) + input.slice(end)
// eslint-disable-next-line prefer-const
index = start
//
keyboard.value.setCaretPosition(index)
// blur
setTimeout(() => {
ignoreBlur.value = false
}, 150)
}
const handleLock = () => {
entering.value = true
const currentLayout = keyboard.value.options.layoutName
const shiftToggle = currentLayout === 'default' ? 'shift' : 'default'
keyboard.value.setOptions({
layoutName: shiftToggle,
})
setTimeout(() => {
ignoreBlur.value = false
}, 150)
}
const handleChange = () => {
entering.value = true
const layoutCandidates = keyboard.value.options.layoutCandidates
//
if (layoutCandidates !== null && layoutCandidates !== undefined) {
displayDefault.value['{change}'] = 'en'
keyboard.value.setOptions({
layoutName: 'default',
layoutCandidates: null,
display: displayDefault.value,
})
}
else {
displayDefault.value['{change}'] = '中'
keyboard.value.setOptions({
layoutName: 'default',
layoutCandidates: (layout as any).layoutCandidates,
display: displayDefault.value,
})
}
setTimeout(() => {
ignoreBlur.value = false
}, 150)
}
const handleClear = () => {
keyboard.value.clearInput()
model.value = ''
setTimeout(() => {
ignoreBlur.value = false
}, 150)
}
const handleEnter = () => {
setTimeout(() => {
ignoreBlur.value = false
}, 150)
emits('enter')
}
const handleClose = () => {
if (props.layoutName === 'number') {
//
// model.value = model.value?.replace(new RegExp(`(\\d+)\\.(\\d{${props.precision}}).*$`), '$1.$2').replace(/\.$/, '')
}
popoverRef.value?.hide()
setTimeout(() => {
ignoreBlur.value = false
}, 150)
emits('close')
}
const handleArrow = (num: number) => {
//
const index = keyboard.value.getCaretPositionEnd()
if (num === 0 && index - 1 >= 0) {
keyboard.value.setCaretPosition(index - 1)
}
else if (num === 1 && index + 1 <= (model.value?.length || 0)) {
keyboard.value.setCaretPosition(index + 1)
}
setTimeout(() => {
ignoreBlur.value = false
}, 150)
}
const handlePopClose = (e: any) => {
//
if (
(e.target as Element).closest('.keyboard-popper')
|| e.target === inputRef.value?.ref
|| /hg-candidate-box/.test(e.target.className)
) {
entering.value = true
const index = keyboard.value.getCaretPositionEnd()
inputRef.value.ref.selectionStart = inputRef.value.ref.selectionEnd = index
inputRef.value.focus()
}
else {
visible.value = false
}
}
const close = () => {
handleClose()
}
const placement = ref('bottom')
onUnmounted(() => {
//
document.removeEventListener('click', handlePopClose)
})
const focus = () => {
inputRef.value.focus()
}
defineExpose({ inputRef, visible, open, close, focus })
</script>
<template>
<el-input
ref="inputRef"
v-model="model"
v-bind="$attrs"
@focus="focusInput"
@blur="blurInput"
@keyup.enter="handleEnter"
>
<template v-for="(item, index) in $slots" :key="index" #[index]>
<slot :name="index" />
</template>
</el-input>
<el-popover
ref="popoverRef"
:visible="visible"
:virtual-ref="inputRef"
virtual-triggering
:width="width"
:show-arrow="false"
:hide-after="0"
:placement="placement"
popper-style="padding: 0px;color:#000"
:persistent="false"
popper-class="keyboard-popper"
@after-enter="afterEnter"
@before-leave="beforeLeave"
>
<div class="simple-keyboard" />
</el-popover>
</template>
<style>
.hg-theme-default .hg-button.hg-button-arrowleft,
.hg-theme-default .hg-button.hg-button-arrowright {
max-width: 70px;
}
.hg-theme-default .hg-button.hg-button-close {
max-width: 100px;
}
.hg-layout-number .hg-button.hg-button-close {
max-width: none;
}
.hg-layout-number .hg-button.hg-button-bksp {
max-width: 92px;
}
</style>

182
src/components/common/FTStream/index.vue

@ -0,0 +1,182 @@
<script setup lang="ts">
import { cmdNameMap } from 'libs/utils'
import { useSystemStore } from 'stores/systemStore'
import { computed, nextTick, ref, watch } from 'vue'
defineProps({
visible: {
type: Boolean,
default: false,
},
})
const systemStore = useSystemStore()
const title = computed(() => {
const commandKey = systemStore.systemList[0]?.command.replace(/^debug_/, '')
return cmdNameMap[commandKey as keyof typeof cmdNameMap] || systemStore.systemList[0]?.command
})
const maskBodyRef = ref<HTMLElement | null>(null)
const maskRef = ref<HTMLElement | null>(null)
const maskHeaderRef = ref<HTMLElement | null>(null)
const statusMap = {
error: 'danger',
fail: 'danger',
success: 'success',
finish: 'primary',
SEND: 'primary',
receive: 'primary',
start: 'primary',
result: 'primary',
}
watch(
() => systemStore.systemList,
async () => {
await nextTick()
if (maskBodyRef.value) {
maskBodyRef.value.scrollTop = maskBodyRef.value.scrollHeight
}
},
{ deep: true },
)
//
let isDragging = false
let offsetX = 0
let offsetY = 0
const handleMouseDown = (event: MouseEvent | TouchEvent) => {
if (maskRef.value && maskHeaderRef.value) {
isDragging = true
const clientX = 'clientX' in event ? event.clientX : event.touches[0].clientX
const clientY = 'clientY' in event ? event.clientY : event.touches[0].clientY
offsetX = clientX - maskRef.value.offsetLeft
offsetY = clientY - maskRef.value.offsetTop
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('touchmove', handleMouseMove)
document.addEventListener('touchend', handleMouseUp)
}
}
const handleMouseMove = (event: MouseEvent | TouchEvent) => {
if (maskRef.value && isDragging) {
const clientX = 'clientX' in event ? event.clientX : event.touches[0].clientX
const clientY = 'clientY' in event ? event.clientY : event.touches[0].clientY
// body
const bodyWidth = document.body.clientWidth
const bodyHeight = document.body.clientHeight
// body
const newLeft = Math.max(0, Math.min(clientX - offsetX, bodyWidth - maskRef.value.offsetWidth))
const newTop = Math.max(0, Math.min(clientY - offsetY, bodyHeight - maskRef.value.offsetHeight))
maskRef.value.style.left = `${newLeft}px`
maskRef.value.style.top = `${newTop}px`
}
}
const handleMouseUp = () => {
isDragging = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
document.removeEventListener('touchmove', handleMouseMove)
document.removeEventListener('touchend', handleMouseUp)
}
</script>
<template>
<teleport to="body">
<!-- 使用 transition 组件包裹 mask 元素 -->
<transition name="mask-fade">
<div
v-if="visible && systemStore.isDebug"
ref="maskRef"
class="mask"
>
<div
ref="maskHeaderRef" class="mask-header" @mousedown="handleMouseDown"
@touchstart="handleMouseDown"
>
<p>{{ title }}</p>
<el-icon @click="systemStore.updateStreamVisible(false)">
<Close />
</el-icon>
</div>
<div ref="maskBodyRef" class="mask-body">
<el-timeline>
<el-timeline-item
v-for="item in systemStore.systemList" :key="item"
:timestamp="JSON.stringify(item.content)"
>
<el-tag :type="statusMap[item.status as keyof typeof statusMap]" class="mask-tag">
{{ item.title }}
</el-tag>
</el-timeline-item>
</el-timeline>
</div>
</div>
</transition>
</teleport>
</template>
<style scoped lang="scss">
.mask {
width: 400px;
height: 250px;
padding: 5px 10px;
background: #fff;
box-shadow: var(--el-box-shadow-light);
position: absolute;
bottom: 20px;
right: 20px;
border-radius: 8px;
font-size: 30px;
z-index: 5000;
.mask-header {
display: flex;
justify-content: space-between;
align-items: center;
height: 30px;
font-size: 16px;
border-bottom: 1px solid #ddd;
cursor: move; //
.el-icon svg{
width: 18px;
cursor: pointer;
}
}
.mask-body {
padding: 5px 2px;
height: calc(100% - 31px);
overflow: auto;
}
}
/* 定义过渡效果 */
//.mask-fade-enter-active, .mask-fade-leave-active {
// transition: transform 0.5s ease;
//}
//
//.mask-fade-enter-from {
// transform: translateX(100%);
//}
//
//.mask-fade-leave-to {
// transform: translateX(100%);
//}
:deep(.el-timeline-item__timestamp.is-bottom) {
white-space: pre-wrap; /* 保留空格和换行符,允许自动换行 */
word-wrap: break-word; /* 允许长单词或URL强制断行 */
overflow-wrap: break-word;
}
.mask-tag {
max-width: 100%;
height: fit-content;
padding: 5px;
white-space: pre-wrap;
}
</style>

7
src/components/common/FTTable/expand.ts

@ -0,0 +1,7 @@
export default {
props: ['row', 'render', 'index', 'column'],
inheritAttrs: false,
setup(props: any) {
return () => props.render(props.row)
},
}

216
src/components/common/FTTable/index.vue

@ -0,0 +1,216 @@
<script setup lang="ts">
import type { VNode } from 'vue'
import { onMounted, reactive } from 'vue'
import Expand from './expand'
defineOptions({
name: 'FtTable',
})
const props = withDefaults(defineProps<TableProp>(), {
columns: () => [],
mustInit: true,
hasHeader: false,
hasPage: false,
searchList: () => [],
getDataFn: () => Promise.resolve([]),
})
const emits = defineEmits([
'add',
'edit',
'detail',
'copy',
'sort',
'save',
'cancel',
'del',
'import',
'export',
'clickTreeNode',
'newTreeNode',
'editTreeNode',
'delTreeNode',
'rowClick',
'rowDblclick',
])
enum ColumnType {
index = 'index',
selection = 'selection',
expand = 'expand',
}
interface TableColumn {
title: string
key: string
type?: ColumnType
width?: number //
fixed?: 'left' | 'right' | undefined //
render?: (row: any) => VNode //
selectable?: (row: any) => boolean
}
interface Btn {
name: string
icon?: string
type?: string
serverUrl: string
serverCondition?: 0 | 1 | 2
}
interface Search {
name: string
icon?: string
key?: string
type?: string
serverUrl: string
}
interface TableProp {
columns?: TableColumn[]
getDataFn?: (params: any) => Promise<any> //
mustInit?: boolean // mountedgetDataFn
hasHeader?: boolean
hasPage?: boolean
btnList?: Btn[]
searchList?: Search[]
}
async function methodParent(fn: any) {
const newFn = fn[0] === '/' ? fn.slice(1) : fn
emits(newFn as never, state.selectedRows)
}
onMounted(() => {
if (props.mustInit) {
initData()
}
})
const state = reactive({
loading: false,
dataTotal: 0,
tableData: [],
selectedRows: [],
filterObj: { pageSize: 10, pageNum: 1 },
})
function initData() {
state.loading = true
props
.getDataFn(state.filterObj)
.then((data) => {
console.log(data)
state.tableData = props.hasPage ? data.list : data
state.dataTotal = data.total
})
.finally(() => {
state.loading = false
})
}
const handleSelectionChange = (val: any) => {
state.selectedRows = val
}
defineExpose({
initData,
})
</script>
<template>
<div class="ft-table">
<div v-if="hasHeader" class="header">
<div v-for="search in searchList" :key="search.key" class="search">
<el-input v-model="state.filterObj[search.key]" :placeholder="search.title" clearable>
<template #append>
<el-icon class="el-input__icon" @click="initData">
<Search />
</el-icon>
</template>
</el-input>
</div>
<div v-for="btn in btnList" :key="btn.serverUrl">
<ft-button
:icon="btn.icon"
:type="btn.type"
:disabled="
!btn.serverCondition
? false
: btn.serverCondition === 1
? state.selectedRows.length !== 1
: state.selectedRows.length < 1
"
@click="methodParent(btn.serverUrl)"
>
{{ btn.name }}
</ft-button>
</div>
</div>
<div class="table-main">
<el-table
v-loading="state.loading"
:="$attrs"
:data="state.tableData"
style="width: 100%"
height="100%"
:highlight-current-row="true"
class="container-table"
header-row-class-name="header-row-class"
v-on="$attrs"
@selection-change="handleSelectionChange"
>
<template v-for="(column, index) in columns" :key="column.key">
<el-table-column
show-overflow-tooltip
:prop="column.key"
:label="column.title"
:width="column.width"
:type="column.type"
:fixed="column.fixed"
:selectable="column.selectable"
>
<template v-if="column.render" #default="scope">
<Expand :column="column" :row="scope.row" :render="column.render" :index="index" />
</template>
</el-table-column>
</template>
</el-table>
</div>
<div v-if="hasPage" class="table-page">
<el-pagination v-model:current-page="state.filterObj.pageNum" v-model:page-size="state.filterObj.pageSize" size="small" background layout="total, sizes, prev, pager, next" :total="state.dataTotal" @change="initData" />
</div>
</div>
</template>
<style lang="scss" scoped>
.ft-table {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.header {
display: flex;
justify-content: flex-start;
align-items: center;
margin-bottom: 10px;
.search {
width: 200px;
}
}
.ft-button {
margin: 0 5px;
}
.table-main {
flex: 1;
overflow: auto;
}
.table-page {
margin-top: 10px;
display: flex;
justify-content: flex-end;
}
:deep(.header-row-class) {
th {
background-color: rgba(0,0,0,0.02 ) !important;
color: rgba(0, 0, 0, 0.85)
}
}
</style>

97
src/components/home/Receive/index.vue

@ -0,0 +1,97 @@
<script setup lang="ts">
import { addLog } from 'apis/log'
import { editSols, getSolsList, saveSols } from 'apis/solution'
import { userList as userListApi } from 'apis/user'
import { FtMessage } from 'libs/message'
import { useSystemStore } from 'stores/systemStore'
import { inject, onMounted, ref } from 'vue'
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
})
const emits = defineEmits(['ok', 'cancel'])
const systemStore = useSystemStore()
onMounted(async () => {
await getUserList()
await getSolutionList()
})
const form = ref<Log.LogItem>({})
const formRef = ref()
const rules = {
name: [
{ required: true, message: '请输入溶液名称', trigger: 'blur' },
],
}
const userList = ref<User.User[]>([])
const getUserList = async () => {
userList.value = (await userListApi()).list
}
const solutionList = ref<Solution.SolutionItem[]>([])
const getSolutionList = async () => {
solutionList.value = (await getSolsList()).list
}
const okHandle = async () => {
try {
const valid = await formRef.value.validate()
if (!valid) {
return
}
await addLog({
...form.value,
channelCode: props.data.channelCode,
})
FtMessage.success('保存成功')
emits('ok')
}
catch (error) {
console.log(error)
}
}
const cancel = () => {
emits('cancel')
}
const channelMap = {
CHANNEL_1: '通道1',
CHANNEL_2: '通道2',
CHANNEL_3: '通道3',
CHANNEL_4: '通道4',
}
</script>
<template lang="pug">
FtDialog(visible :title="`${channelMap[data?.channelCode]}-领取`" width="30%" :ok-handle="okHandle" @cancel="cancel")
el-form(ref="formRef" label-width="auto" :model="form" :rules="rules")
el-form-item(label="溶液名称" prop="solutionId")
el-select(v-model="form.solutionId" placeholder="请选择溶液")
el-option(v-for="item in solutionList" :key="item.id" :label="item.name" :value="item.id")
el-form-item(label="溶液浓度" prop="concentration")
el-input(v-model="form.concentration" placeholder="请输入溶液浓度")
template(#append)
span %
el-form-item(label="发放人" prop="issuerId")
el-select(v-model="form.issuerId" placeholder="请选择发放人")
el-option(v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id")
el-form-item(label="领取人" prop="receiverId")
el-tag {{systemStore.systemStatus.currentUser.nickname}}
el-form-item(label="容量" prop="receivedVolume")
el-input(v-model="form.receivedVolume" placeholder="请输入容量")
template(#append)
span mL
</template>
<style lang="stylus" scoped>
.el-tag
margin-right 5px
</style>

53
src/components/solution/Edit/index.vue

@ -0,0 +1,53 @@
<script setup lang="ts">
import { editSols, saveSols } from 'apis/solution'
import { FtMessage } from 'libs/message'
import { inject, ref } from 'vue'
const emits = defineEmits(['ok', 'cancel'])
const data = inject<Solution.SolutionItem>('currentData')
const form = ref<Solution.SolutionItem>({ ...(data as any)?.value })
const formRef = ref()
const rules = {
name: [
{ required: true, message: '请输入溶液名称', trigger: 'blur' },
],
}
const okHandle = async () => {
try {
const valid = await formRef.value.validate()
if (!valid) {
return
}
if (data?.value.id) {
await editSols(form.value)
}
else {
await saveSols(form.value)
}
FtMessage.success('保存成功')
emits('ok')
}
catch (error) {
console.log(error)
}
}
const cancel = () => {
emits('cancel')
}
</script>
<template lang="pug">
FtDialog(visible :title="data?.id ? '编辑' : '新增'" width="30%" :ok-handle="okHandle" @cancel="cancel")
el-form(ref="formRef" label-width="auto" :model="form" :rules="rules")
el-form-item(label="溶液名称" prop="name")
el-input(v-model="form.name" placeholder="请输入溶液名称")
</template>
<style lang="stylus" scoped>
.el-tag
margin-right 5px
</style>

255
src/components/system/Check/index.vue

@ -0,0 +1,255 @@
<script lang="ts" setup>
import { getSelfFinish } from 'apis/self'
import { ElMessageBox } from 'element-plus'
import { socket } from 'libs/socket'
import { useHomeStore } from 'stores/homeStore'
import { useSystemStore } from 'stores/systemStore'
import { onMounted, ref } from 'vue'
const emits = defineEmits(['close'])
const homeStore = useHomeStore()
const systemStore = useSystemStore()
const checkMap = ref(new Map([
['zOrigin', { status: '', ignoreKey: 'zOriginIsIgnore', name: 'Z轴回原点', params: { commandId: '', command: `check_z_origin`, params: {} } }],
['xyOrigin', { status: '', ignoreKey: 'xyOriginIsIgnore', name: '机械臂回原点', params: { commandId: '', command: `check_xy_origin`, params: {} } }],
['titrationOrigin', { status: '', ignoreKey: 'titrationOriginIsIgnore', name: '滴定电机回原点', params: { commandId: '', command: `check_titration_motor_origin`, params: {} } }],
['shakeOrigin', { status: '', ignoreKey: 'shakeOriginIsIgnore', name: '摇匀电机回原点', params: { commandId: '', command: `check_shake_motor_origin`, params: {} } }],
['stirOrigin', { status: '', ignoreKey: 'stirOriginIsIgnore', name: '磁子投放电机回原点', params: { commandId: '', command: `check_stir_motor_origin`, params: {} } }],
]))
const checkList = ref<any[]>([])
onMounted(async () => {
socket.init(receiveMessage1, 'cmd_debug')
socket.init(receiveMessage2, 'cmd_response')
socket.init(receiveMessageSelfMove, 'self_move_test')
await ElMessageBox.confirm(
'设备转运机械臂、滴定电机、摇匀电机、磁子投放电机,请确认机械臂行进路径无杂物',
'提示',
{
confirmButtonText: '确认',
showClose: false,
showCancelButton: false,
closeOnClickModal: false,
closeOnPressEscape: false,
type: 'warning',
customClass: 'init-message',
},
)
const keys = [...checkMap.value.keys()]
for (let i = 0; i < keys.length; i++) {
checkList.value.push(checkMap.value.get(keys[i]))
}
})
let currentCommandId = ''
const receiveMessage1 = (data: Socket.cmdData) => {
data.commandId === currentCommandId && systemStore.pushSystemList(data)
}
const receiveMessage2 = (data: Socket.cmdData) => {
data.commandId === currentCommandId && systemStore.pushSystemList(data)
const item = checkList.value.find(item => item.params.commandId === data.commandId)
if (item && data.commandId === item.params.commandId && ['success', 'error'].includes(data.status)) {
item.status = data.status
}
}
const commandHandle = async (data: any) => {
data.params.commandId = currentCommandId = Date.now().toString()
await homeStore.sendControl(data!.params)
}
const onConfirm = async () => {
await getSelfFinish(true)
emits('close')
}
const percentage = ref(0)
const checkHandle = async () => {
activeStep.value = 1
await ElMessageBox.confirm(
'设备即将开始自检',
'提示',
{
confirmButtonText: '确认',
showClose: false,
showCancelButton: false,
closeOnClickModal: false,
closeOnPressEscape: false,
type: 'warning',
customClass: 'init-message',
},
)
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'check_move_test',
params: {},
}
await homeStore.sendControl(params)
}
const checkTextList = ref<{ title: string, type: 'success' | 'error' }[]>([])
const selfAgain = ref(true)
const receiveMessageSelfMove = (data: any) => {
checkTextList.value.push(data)
percentage.value = data.schedule
if (data.type === 'error') {
selfAgain.value = true
}
}
const activeStep = ref(0)
const checkAgain = async () => {
selfAgain.value = false
checkTextList.value = []
percentage.value = 0
currentCommandId = Date.now().toString()
const params = {
commandId: currentCommandId,
command: 'check_move_test',
params: {},
}
await homeStore.sendControl(params)
selfAgain.value = true
}
</script>
<template>
<FtDialog visible title="设备初始化" width="60%">
<!-- <el-steps style="max-width: 600px" :active="activeStep" finish-status="success">
<el-step title="初始化" />
<el-step title="自检" />
<el-step title="设备状态" />
</el-steps> -->
<div v-if="activeStep === 0" class="check-main">
<div v-for="item in checkList" :key="item.name" class="check-item">
<el-tag>{{ item.name }}</el-tag>
<el-icon v-if="item.status === 'success'" color="#26D574">
<CircleCheckFilled />
</el-icon>
<el-icon v-else-if="item.status === 'error'" color="#FE0A0A">
<CircleCloseFilled />
</el-icon>
<el-icon v-else-if="item.status === ''" class="el-icon--loading">
<Loading />
</el-icon>
<el-icon v-else-if="item.status === 'ignore'">
<More />
</el-icon>
<ft-button v-if="!['ignore', 'success'].includes(item.status)" type="primary" size="small" :click-handle="() => commandHandle(item)">
回原点
</ft-button>
<!-- <ft-button v-if="!['ignore', 'success'].includes(item.status) && item.name === '门电机回原点'" size="small" type="primary" :click-handle="() => ignore(item)">
忽略
</ft-button>
<ft-button v-if="item.status === 'ignore' && item.name === '门电机回原点'" size="small" type="danger" :click-handle="() => ignoreFalse(item)">
取消忽略
</ft-button> -->
</div>
</div>
<div v-if="activeStep === 1" class="check-box">
<div class="progress-box">
<p>自检进度: </p>
<el-progress
:stroke-width="20"
:percentage="percentage"
/>
</div>
<ul>
<li v-for="(item, index) in checkTextList" :key="index">
<span :style="{ color: item.type === 'success' ? '#14A656' : '#DF1515' }">{{ item.title }}</span>
</li>
</ul>
</div>
<template #footer>
<div style="height: 40px">
<FtButton v-if="activeStep === 0 && checkList.every(item => ['success', 'ignore'].includes(item.status))" type="primary" :click-handle="checkHandle">
下一步
</FtButton>
<FtButton v-if="activeStep === 1 && selfAgain" type="primary" :click-handle="checkAgain">
重新自检
</FtButton>
<FtButton v-if="activeStep === 1" :click-handle="onConfirm">
关闭
</FtButton>
</div>
</template>
</FtDialog>
</template>
<style scoped>
.check-box {
height: 30vh;
ul {
li {
margin: 3px 0;
}
}
}
.progress-box {
width: 100%;
height: 40px;
display: flex;
align-items: center;
p {
margin-right: 10px;
}
span {
margin-left: 10px;
}
.el-progress {
width: 80%;
}
}
.check-main{
height: 25vh;
overflow: auto;
display: flex;
flex-direction: column;
justify-content: flex-start;
margin-top: 20px;
}
.check-item {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
.el-tag {
width: 50%;
}
.el-icon {
margin: 0 10px;
font-size: 18px;
}
}
.check-status{
display: grid;
grid-template-columns: 2fr 1fr 1fr;
margin-top: 5px;
height: 30px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.el-icon.el-icon--loading {
animation: spin 1s linear infinite;
}
.ft-button {
width:120px
}
</style>

64
src/components/system/EditDate/index.vue

@ -0,0 +1,64 @@
<script setup lang="ts">
import { useServerTime } from 'hooks/useServerTime'
import { FtMessage } from 'libs/message'
import { ref } from 'vue'
const props = defineProps({
datetime: {
type: Number,
default: 0,
},
})
const emits = defineEmits(['ok', 'close'])
const form = ref<{ epochMilli?: number }>({
epochMilli: props.datetime,
})
const formRef = ref()
const rules = {
epochMilli: [
{ required: true, message: '请选择时间', trigger: 'change' },
],
}
const okHandle = async () => {
try {
const valid = await formRef.value.validate()
if (!valid) {
return
}
emits('ok')
}
catch (e) {
console.log(e)
}
}
const cancel = () => {
emits('close')
}
</script>
<template>
<ft-dialog visible title="设置日期与时间" width="40%" :ok-handle="okHandle" @cancel="cancel">
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto">
<el-form-item label="日期与时间" prop="epochMilli">
<el-date-picker
v-model="form.epochMilli"
:show-now="false"
format="YYYY-MM-DD hh:mm:ss"
value-format="x"
style="width: 100%"
type="datetime"
placeholder="请选择日期和时间"
/>
</el-form-item>
</el-form>
</ft-dialog>
</template>
<style scoped lang="scss">
</style>

28
src/components/system/Stop/index.vue

@ -0,0 +1,28 @@
<script setup lang="ts">
</script>
<template>
<Teleport to="body">
<div class="mask-box">
设备急停中
</div>
</Teleport>
</template>
<style scoped lang="scss">
.mask-box {
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
color: var(--el-color-danger);
font-size: 50px;
z-index: 10000;
top: 0;
left: 0;
}
</style>

53
src/components/systemConfig/Edit/index.vue

@ -0,0 +1,53 @@
<script setup lang="ts">
import { updateConfig } from 'apis/system'
import { FtMessage } from 'libs/message'
import { inject, ref } from 'vue'
const emits = defineEmits(['ok', 'cancel'])
const data = inject('currentData')
const form = ref<System.SystemConfig>(data as System.SystemConfig)
const formRef = ref()
const rules = {
value: [
{ required: true, message: '请输入值', trigger: 'blur' },
],
}
const okHandle = async () => {
try {
const valid = await formRef.value.validate()
if (!valid) {
return
}
await updateConfig(form.value)
FtMessage.success('保存成功')
emits('ok')
}
catch (error) {
console.log(error)
}
}
const cancel = () => {
emits('cancel')
}
</script>
<template lang="pug">
FtDialog(visible title="编辑" width="30%" :ok-handle="okHandle" @cancel="cancel")
el-form(ref="formRef" label-width="auto" :model="form" :rules="rules" label-suffix=": ")
el-form-item(label="名称")
el-tag {{ form.name }}
el-form-item(label="code")
el-tag {{ form.code }}
el-form-item(label="值" prop="value")
el-input(v-model="form.value" placeholder="请输入值")
</template>
<style scoped lang="stylus">
.el-tag
margin-right 5px
</style>

184
src/components/user/Edit/index.vue

@ -0,0 +1,184 @@
<script setup lang="ts">
import { addUser, updateUser } from 'apis/user'
import { FtMessage } from 'libs/message'
import { useSystemStore } from 'stores/systemStore'
import { onMounted, onUnmounted, ref } from 'vue'
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
})
const emits = defineEmits(['ok', 'cancel'])
onMounted(() => {
form.value.password = undefined
})
onUnmounted(() => {
})
const form = ref<User.User>(props.data.id ? props.data : {})
const formRef = ref()
const validateHandle = (rule: any, value: any, callback: any) => {
if (!value?.length) {
callback(new Error('请选择试管'))
}
else {
callback()
}
}
const passwordValidateHandle = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error('请输入密码'))
}
else if (value.length > 6) {
callback(new Error('密码长度不能大于6个字符'))
}
else {
callback()
}
}
const passwordValidateHandle1 = (rule: any, value: any, callback: any) => {
console.log('passwordValidateHandle1', value)
if (!value) {
callback(new Error('请输入密码'))
}
else if (value !== form.value.password) {
callback(new Error('两次密码输入不一致'))
}
else {
callback()
}
}
const rules = {
username: [
{ required: true, message: '请输入账号', trigger: 'blur', validator: validateHandle },
],
role: [
{ required: true, message: '请选择角色', trigger: 'change' },
],
nickname: [
{ required: false, message: '请输入用户名', trigger: 'blur' },
],
password: [
{ required: true, trigger: 'blur', validator: passwordValidateHandle },
],
passwordAgain: [
{ required: true, trigger: 'blur', validator: passwordValidateHandle1 },
],
}
const okHandle = async () => {
try {
const valid = await formRef.value.validate()
if (!valid) {
return
}
if (form.value.id) {
await updateUser(form.value)
}
else {
form.value.deleted = 'DISABLE'
form.value.fixedUser = 'DISABLE'
await addUser(form.value)
}
// , 退
if (form.value.id === useSystemStore().systemStatus.currentUser?.id) {
useSystemStore().logout()
}
FtMessage.success('保存成功')
emits('ok')
}
catch (e) {
console.log(e)
}
}
const cancel = () => {
emits('cancel')
}
const roleList = [
{
label: '管理员',
value: 'ADMIN',
},
{
label: '开发者',
value: 'DEVELOPER',
},
{
label: '普通用户',
value: 'USER',
},
]
</script>
<template lang="pug">
FtDialog(visible :title="data.id ? '编辑用户' : '新增用户'" width="40%" :ok-handle="okHandle" @cancel="cancel")
el-form(ref="formRef" :model="form" :rules="rules" label-width="auto")
el-form-item(label="账号" prop="username")
el-input(v-model="form.username" maxlength="10" show-word-limit :disabled="data.id && form.fixedUser === 'ENABLE'" placeholder="请输入账号")
el-form-item(label="用户名" prop="nickname")
el-input(v-model="form.nickname" maxlength="10" show-word-limit :disabled="data.id && form.fixedUser === 'ENABLE'" placeholder="请输入用户名")
el-form-item(label="角色" prop="role")
el-select(v-model="form.role" placeholder="请选择角色")
el-option( v-for="item in roleList" :key="item.value" :label="item.label" :value="item.value")
el-form-item(label="密码" prop="password" v-if="useSystemStore().systemStatus.currentUser?.fixedUser === 'ENABLE'")
el-input(v-model="form.password" maxlength="6" autocomplete="new-password" show-word-limit show-password type="password" placeholder="请输入密码")
el-form-item(label="再次输入密码" prop="passwordAgain" v-if="useSystemStore().systemStatus.currentUser?.fixedUser === 'ENABLE'")
el-input(v-model="form.passwordAgain" maxlength="6" autocomplete="new-password" show-word-limit show-password type="password" placeholder="请输入密码")
</template>
<style scoped lang="stylus">
.el-tag
margin-right 5px
.el-row
height 450px
.el-col
height 100%
overflow auto
:deep(.el-tag)
width 100%
margin-bottom 5px
.el-tag__content
display flex
width 100%
justify-content space-between
.tube-item
padding 5px
background #384D5D
border-radius 10px
display grid
grid-template-columns repeat(5, 1fr)
grid-template-rows repeat(1, 1fr)
grid-gap 5px
position relative
.tube-line
display flex
flex-direction column
.tube-line-inner
display inline-block
width 25px
height 25px
border-radius 50%
background #fff
margin 2px
transition background 0.5s
.tube-line-disable
.tube-line-inner
background #C6C6C6
.tube-line-active
.tube-line-inner
background #26D574
</style>

21
src/env.d.ts

@ -0,0 +1,21 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly FT_NODE_ENV: string
readonly FT_WS_URL: string
readonly FT_PROXY: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
declare const __APP_VERSION__: string
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<object, object, any>
export default component
}
declare module 'lodash'

33
src/hooks/useActivateDebug.ts

@ -0,0 +1,33 @@
import { FtMessage } from 'libs/message'
import { useSystemStore } from 'stores/systemStore'
import { ref } from 'vue'
export const useActivateDebug = () => {
const systemStore = useSystemStore()
const logoClickCount = ref(0)
let clickTimeout: NodeJS.Timeout | null = null
const handleLogoClick = () => {
if (clickTimeout) {
clearTimeout(clickTimeout)
}
logoClickCount.value++
if (logoClickCount.value === 10) {
console.log('isDebug', systemStore.isDebug)
systemStore.updateDebug()
logoClickCount.value = 0 // 重置计数器
if (systemStore.isDebug) {
FtMessage.success('已开启调试模式')
}
else {
FtMessage.error('已关闭调试模式')
}
}
clickTimeout = setTimeout(() => {
logoClickCount.value = 0 // 重置计数器
}, 1000)
}
return {
handleLogoClick,
}
}

29
src/hooks/useApiData.ts

@ -0,0 +1,29 @@
import http from 'libs/http'
import { ref } from 'vue'
export default function useApiData(url: string, params?: any, init?: boolean) {
const data = ref(null)
const loading = ref(false)
const error = ref()
const fetchData = async () => {
loading.value = true
error.value = null
try {
const response = await http.post(url, params)
data.value = response.data
}
catch (err) {
error.value = err
}
finally {
loading.value = false
}
}
init && fetchData().then(() => {})
return {
data,
loading,
error,
fetchData,
}
}

64
src/hooks/useServerTime.ts

@ -0,0 +1,64 @@
import { getTime, setTime } from 'apis/system'
import { formatDateTime } from 'libs/utils'
import { onMounted, onUnmounted, ref } from 'vue'
export function useServerTime() {
const serverTime = ref<number | undefined>() // 初始服务器时间戳
const clientFetchTime = ref<number | null>(null) // 获取服务器时间时的客户端时间戳
const currentTime = ref<string>('0001-00-00 00:00:00')
const editVisible = ref(false)
let interval: number | null = null
onMounted(async () => {
try {
await getDateTime()
}
catch (error) {
// currentTime.value = formatDateTime(undefined, new Date())
console.error('获取服务器时间失败')
}
})
const openDialog = () => {
editVisible.value = true
}
const closeDialog = () => {
editVisible.value = false
}
const getDateTime = async () => {
serverTime.value = (await getTime())?.epochMilli
clientFetchTime.value = Date.now()
let num = 0
if (interval)
clearInterval(interval)
interval = window.setInterval(async () => {
if (num > 60) {
serverTime.value = (await getTime())?.epochMilli
clientFetchTime.value = Date.now()
num = 0
}
if (serverTime.value && clientFetchTime.value) {
const elapsed = Date.now() - clientFetchTime.value
const currentServerTime = serverTime.value + elapsed
currentTime.value = formatDateTime(undefined, new Date(currentServerTime))
num++
}
}, 1000)
}
const setDateTime = async (time: number) => {
await setTime({ epochMilli: time })
await getDateTime()
}
onUnmounted(() => {
if (interval)
clearInterval(interval)
})
return { currentTime, serverTime, editVisible, setDateTime, openDialog, closeDialog }
}

413
src/layouts/default.vue

@ -0,0 +1,413 @@
<script setup lang="ts">
import autoIcon from 'assets/images/auto.svg'
import logoutIcon from 'assets/images/logout.svg'
import manualIcon from 'assets/images/manual.svg'
import FtDatetime from 'components/common/FTDatetime/index.vue'
import Check from 'components/system/Check/index.vue'
import Stop from 'components/system/Stop/index.vue'
import { ElMessageBox } from 'element-plus'
import { useActivateDebug } from 'hooks/useActivateDebug'
import { FtMessage } from 'libs/message'
import { isClose, socket } from 'libs/socket'
import { authRoutes } from 'router/routes'
import { useDebugStore } from 'stores/debugStore'
import { useSystemStore } from 'stores/systemStore'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
const { handleLogoClick } = useActivateDebug()
const systemStore = useSystemStore()
const router = useRouter()
onMounted(async () => {
socket.init(receiveMessage, 'alarm')
socket.init(receiveMessage1, 'warn')
if (!systemStore.systemStatus.currentUser) {
await router.push('/login')
}
// if (!systemStore.systemStatus.selfTest && systemStore.systemStatus.currentUser && systemStore.systemStatus.currentUser?.username !== 'test') {
// isCheck.value = true
// }
})
onUnmounted(() => {
socket.unregisterCallback(receiveMessage, 'alarm')
socket.unregisterCallback(receiveMessage, 'warn')
})
let flag = false
const receiveMessage1 = (data: any) => {
FtMessage.warning(data)
}
const receiveMessage = async (data: any) => {
if (flag) {
return
}
flag = true
await ElMessageBox.confirm(
data,
'提示',
{
confirmButtonText: '确认',
showClose: false,
showCancelButton: false,
closeOnClickModal: false,
closeOnPressEscape: false,
type: 'warning',
},
)
flag = false
}
watch (() => isClose.value, async (newVal) => {
if (newVal) {
// await checkCraft()
}
})
watch(() => systemStore.systemStatus, () => {
if (!systemStore.systemStatus.currentUser) {
router.push('/login')
}
// if (!systemStore.systemStatus.selfTest && systemStore.systemStatus.currentUser && systemStore.systemStatus.currentUser?.username !== 'test') {
// isCheck.value = true
// }
})
const checkCraftVisible = ref(false)
// const checkCraft = async () => {
// const res = await craftList()
// systemStore.errorCraft = res && res.length > 0
// systemStore.errCraftList = res
// }
// metaisDefault=true isDebug=true,debug
const menuList = computed(() => {
return authRoutes.filter((item) => {
if (item.meta?.isDefault) {
return true
}
return (['/debug', '/positionDebug'].includes(item.path) && systemStore.isDebug)
})
})
watch(() => systemStore.isDebug, () => {
console.log('isDebug', systemStore.isDebug)
if (!systemStore.isDebug && router.currentRoute.value.path === '/debug') {
router.push('/')
}
})
const isCheck = ref(false)
const statusMap = {
start: {
type: 'primary',
name: '指令开始执行',
},
success: {
type: 'success',
name: '指令执行成功',
},
fail: {
type: 'danger',
name: '指令执行异常',
},
}
console.log(systemStore.systemStatus)
const commandHandle = async (command: string, params?: unknown) => {
const data = {
commandId: Date.now().toString(),
command,
params,
}
await useDebugStore().sendControl(data)
}
const containerStatus = computed(() => {
const empty = systemStore.systemStatus.solutionModule?.solutionContainer?.find(item => item.empty)
if (empty) {
return 'empty'
}
return 'full'
// return 'empty'
})
</script>
<template lang="pug">
el-container(class="main")
el-header(class="header")
div(class="logo")
img(src="../assets/images/logo.svg" alt="" @click="handleLogoClick")
div(class="menu-box")
el-tag(
v-for="item in menuList"
:key="item.path"
class="menu-tag"
:effect="router.currentRoute.value.path.includes(item.path) ? 'dark' : 'plain'"
@click="router.push(item.path)"
)
| {{ item?.meta?.title }}
div(class="header-right")
el-dropdown(class="wifi-dropdown" trigger="click")
div(class="wifi-icon")
img(v-if="isClose" src="../assets/images/wifi.svg" alt="")
img(v-else src="../assets/images/wifi-active.svg" alt="")
template(#dropdown)
el-dropdown-menu
el-dropdown-item
div(class="logout")
span(v-if="!isClose") 已连接
span(v-else) 已断开
div(class="user")
el-dropdown(class="user-dropdown" trigger="click")
div(class="user-dropdown-item")
img(src="../assets/images/user.svg" alt="")
span {{ systemStore.systemStatus.currentUser?.nickname || systemStore.systemStatus.currentUser?.username }}
template(#dropdown)
el-dropdown-menu
el-dropdown-item(@click="systemStore.logout()")
div(class="logout")
img(:src="logoutIcon" alt="")
span 退出登录
el-container(class="container")
el-main(:class="{ 'main-no-background': router.currentRoute.value.path.includes('home') || router.currentRoute.value.path.includes('craft') || router.currentRoute.value.path.includes('setting') }")
router-view(class="content")
el-footer(class="footer" :class="{ 'footer-expand': !systemStore.menuExpand }")
div(v-if="systemStore.systemStatus.mode === 'AUTO'" class="model-box model-auto-box")
div(style="display: flex;align-items: center;")
img(:src="autoIcon" alt="")
span 自动模式
div(class="right-box")
span 间隔:
span(style="color: #0D72EA;margin: 0 7px") {{ systemStore.systemStatus.delay }}
span
div(v-if="systemStore.systemStatus.mode === 'CLICK'" class="model-box model-manual-box")
div(style="display: flex;align-items: center;")
img(:src="manualIcon" alt="")
span 手动模式
div(class="right-box")
| 点动控制
div(class="footer-left")
img(src="../assets/images/run.svg" alt="")
span(v-if="!systemStore.systemLogList.length" class="text") 设备运行状态
el-popover(v-else width="auto" trigger="click" placement="top")
template(#reference)
el-tag(style="width: 100%" :type="statusMap[systemStore.systemLogList[0]?.status].type")
| {{ systemStore.systemLogList[0]?.cmdName }}: {{ statusMap[systemStore.systemLogList[0]?.status ].name }} {{ systemStore.systemLogList[0]?.time }}
template(#default)
div(class="log-box")
el-tag(v-for="(item, key) in systemStore.systemLogList" :key="key" :type="statusMap[item?.status ].type")
div(style="display: flex;justify-content: space-between;width: 100%")
span
| {{ item.cmdName }}:
| {{ statusMap[item.status].name }}
span {{ item.time }}
div(class="footer-right")
FtDatetime
FtStream(:visible="systemStore.streamVisible")
Check(v-if="isCheck" @close="isCheck = false")
Stop(v-if="systemStore.systemStatus.emergencyStop")
</template>
<style scoped lang="stylus">
.main
box-sizing border-box
height 100%
background #fff
.header, .footer
height 60px
width 100%
display flex
align-items center
justify-content space-between
padding 10px 15px
.header
color #393F46
border-bottom 1px solid rgba(9, 39, 62, 0.09)
.logo
height 100%
display flex
align-items center
.title
margin 0 10px
color #8799AB
font-weight 600
img
height 100%
.expand-icon
height 15px
transition all 0.3s
.fold-icon
height 15px
transform rotate(90deg)
transition all 0.3s
.menu-box
width 100%
display flex
justify-content center
.header-right
display flex
align-items center
height 100%
.wifi-dropdown
height 100%
.wifi-icon
width 40px
height 100%
background #fff
border-radius 5px
display flex
align-items center
justify-content center
img
height 50%
.time
margin 0 10px
height 100%
width 170px
padding 0 10px
display flex
align-items center
justify-content center
background #fff
border-radius 5px
.container
height calc(100% - 100px)
background #FAFCFF
padding 12px 16px
.main-no-background
padding 0 !important
background transparent !important
box-shadow none !important
.el-main
overflow hidden
box-shadow 0 0 5px 0 rgba(9, 39, 62, 0.15)
border-radius 10px
background #fff
padding 10px
.content
width 100%
height 100%
.user-dropdown-item
display flex
align-items center
height 100%
color #393F46
font-weight bold
img
height 30px
margin-right 10px
.footer-expand
padding 10px 15px 10px 85px !important
.footer
border-top 1px solid rgba(9, 39, 62, 0.09)
display flex
justify-content space-between
align-items center
.model-auto-box
background linear-gradient(180deg, #44A6FF 0%, #2892F3 98%)
.model-manual-box
background linear-gradient(180deg, #30E7A7 0%, #31D79E 100%)
.model-box
width 250px
height 100%
padding 5px
display flex
align-items center
justify-content space-between
border-radius 5px
color #F6F6F6
img
height 40%
margin 0 5px 0 15px
.right-box
height 100%
width 100px
background #fff
border-radius 5px
color #3C445C
display flex
align-items center
justify-content center
font-weight 500
.footer-left
height 100%
border-radius 5px
display flex
align-items center
padding 0 20px
width 50%
border-right 5px solid #F6F6F6
background #F5F5F5
img
height 60%
margin-right 20px
.text
color #1C1C1C
margin-left 10px
font-size 14px
.footer-right
.status-error
background #F56C6C !important
.aside-item:hover
.swing-icon
animation swing 1s ease-in-out
.logout
display flex
img
width 15px
margin-right 10px
.container-box
width 400px
display grid
grid-template-columns repeat(4, 1fr)
grid-template-rows repeat(1, 1fr)
grid-gap 10px
.container-main
display flex
flex-direction column
align-items center
.log-box
width 500px
height 400px
overflow auto
:deep(.el-tag)
margin 5px 0
width 100%
.el-tag__content
width 100%
@keyframes swing
0%
transform rotate(0deg)
25%
transform rotate(-30deg)
50%
transform rotate(30deg)
75%
transform rotate(-15deg)
100%
transform rotate(0deg)
.menu-tag
padding 15px 20px
font-size 16px
.el-tag--plain
border none
color #3C445C
font-weight 500
font-size 16px
</style>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save