初始化
This commit is contained in:
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
|
||||
charset = utf-8
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
end_of_line = lf
|
||||
max_line_length = 100
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
/.vs
|
||||
/.vscode
|
||||
/obj
|
||||
12
CHANGELOG.md
Normal file
12
CHANGELOG.md
Normal file
@@ -0,0 +1,12 @@
|
||||
This file explains how Visual Studio created the project.
|
||||
|
||||
The following tools were used to generate this project:
|
||||
- create-vite
|
||||
|
||||
The following steps were used to generate this project:
|
||||
- Create vue project with create-vite: `npm init --yes vue@latest rcu_web_vue -- --eslint `.
|
||||
- Updating `vite.config.js` with port.
|
||||
- Create project file (`rcu_web_vue.esproj`).
|
||||
- Create `launch.json` to enable debugging.
|
||||
- Add project to solution.
|
||||
- Write this file.
|
||||
35
README.md
Normal file
35
README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# rcu_web_vue
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vite.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
24
eslint.config.js
Normal file
24
eslint.config.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||
import globals from 'globals'
|
||||
import js from '@eslint/js'
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
name: 'app/files-to-lint',
|
||||
files: ['**/*.{js,mjs,jsx,vue}'],
|
||||
},
|
||||
|
||||
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
|
||||
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
js.configs.recommended,
|
||||
...pluginVue.configs['flat/essential'],
|
||||
])
|
||||
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>宝来威智能(广东)有限公司</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
8
jsconfig.json
Normal file
8
jsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
5602
package-lock.json
generated
Normal file
5602
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
44
package.json
Normal file
44
package.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "rcu_web_vue",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint . --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"axios": "^1.8.3",
|
||||
"dayjs": "^1.11.13",
|
||||
"element-china-area-data": "^6.1.0",
|
||||
"element-plus": "^2.10.2",
|
||||
"jquery": "^3.7.1",
|
||||
"mqtt": "^5.13.0",
|
||||
"qs": "^6.14.0",
|
||||
"ssh2-sftp-client": "^12.0.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^11.1.3",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue-simple-verify": "^1.1.0",
|
||||
"vuex": "^4.1.0",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-plugin-vue": "~10.0.0",
|
||||
"globals": "^16.0.0",
|
||||
"unplugin-auto-import": "^19.1.1",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vite": "^6.2.1",
|
||||
"vite-plugin-vue-devtools": "^7.7.2"
|
||||
}
|
||||
}
|
||||
12
public/config.js
Normal file
12
public/config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const config = {
|
||||
// http访问后端接口
|
||||
Api: "http://service-info.blv-oa.com:9998/api/",
|
||||
Ads: "http://service-info.blv-oa.com:9998/",
|
||||
|
||||
|
||||
// 本地调试接口
|
||||
/*Api: "http://localhost:19368/api/",
|
||||
Ads: "http://localhost:19368/",*/
|
||||
}
|
||||
|
||||
export default config
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
92
public/image/advertisement.svg
Normal file
92
public/image/advertisement.svg
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW 2020 (64-Bit) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="380px" height="200px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 42.98 22.61"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<font id="FontID1" horiz-adv-x="600" font-variant="normal" style="fill-rule:nonzero" font-weight="300">
|
||||
<font-face
|
||||
font-family="思源黑体 CN Normal">
|
||||
<font-face-src>
|
||||
<font-face-name name="思源黑体 CN Normal"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<missing-glyph><path d="M0 0z"/></missing-glyph>
|
||||
<glyph unicode="优" horiz-adv-x="999" d="M881.495 661.616c-28.9979,39.9828 -88.9721,102.924 -137.935,146.916l-45.9698 -32.9806c48.9633,-45.9698 107.948,-109.953 134.916,-151.914l48.9893 37.9784zm-602.657 170.89c-53.9611,-152.903 -141.918,-302.812 -235.862,-400.765 12,-14.9935 31.9914,-48.9633 38.9676,-62.9677 31.0023,33.9958 60.9633,71.9742 89.9612,114.95l0 -558.692 62.9677 0 0 659.612c40.9719,72.9634 76.946,150.925 104.929,229.875l-60.9633 17.987zm460.739 -818.502c-31.0023,0 -36.0001,5.987 -36.0001,35.9741l0 403.758 -64.946 0 0 -403.758c0,-75.9569 19.9914,-97.9526 93.9439,-97.9526l119.922 0c69.9699,0 86.9417,39.9828 92.9547,186.899 -16.9979,4.99785 -43.9915,16.9719 -58.985,27.9827 -2.9935,-129.918 -8.98051,-152.903 -38.9676,-152.903l-107.922 0zm-153.918 583.655c3.98266,74.9417 4.99785,151.888 4.99785,225.866l-65.9612 0c0,-73.9785 -1.01519,-150.925 -4.00869,-225.866l-228.86 0 0 -62.9677 224.877 0c-14.9935,-226.881 -65.9612,-437.754 -236.877,-557.676 16.9979,-10.9849 37.9784,-30.9762 48.9893,-46.985 180.886,131.922 235.862,359.793 253.849,604.661l362.786 0 0 62.9677 -359.793 0z"/>
|
||||
<glyph unicode="创" horiz-adv-x="999" d="M271.836 -2.9935c-51.9568,0 -61.9525,7.00219 -61.9525,43.9654l0 370.778 226.855 0c-7.99135,-127.914 -17.987,-178.881 -29.9871,-192.886 -7.99135,-7.99135 -15.9827,-8.98051 -28.9719,-8.98051 -14.0044,0 -49.9785,0 -86.9417,3.98266 8.98051,-15.9827 15.9827,-39.9567 16.9719,-57.9698 37.9784,-1.97831 75.9569,-1.97831 96.9634,0 23.974,2.00434 39.9567,7.00219 54.9503,24.0001 21.9957,23.974 31.9914,89.9352 41.9871,262.855 0.989157,8.98051 2.00434,27.9827 2.00434,27.9827l-357.789 0 0 -429.763c0,-81.9439 28.9719,-101.935 120.911,-101.935l189.892 0c85.9525,0 105.944,36.9893 114.924,174.899 -18.9762,3.98266 -43.9654,14.9935 -59.9481,24.9892 -4.99785,-118.933 -12,-141.918 -58.985,-141.918l-180.886 0zm45.9698 835.499c-53.9611,-128.929 -158.89,-266.838 -285.814,-358.778 14.9935,-11.0109 37.9784,-31.9914 48.9633,-44.9806 98.9417,76.946 185.883,178.907 247.862,288.834 81.9439,-84.9634 170.89,-190.881 214.855,-258.847l48.9893 43.9654c-48.9893,70.959 -150.925,183.905 -233.884,268.843 7.00219,14.9935 13.0152,27.9827 19.0022,42.9763l-59.9742 17.987zm391.784 -113.935l-62.9677 0 0 -548.67 62.9677 0 0 548.67zm131.922 100.946l0 -803.534c0,-18.9762 -7.99135,-24.9892 -25.9784,-25.9784 -19.0022,0 -81.9699,-0.989157 -152.929,0.989157 11.0109,-17.987 19.9914,-45.9698 24.0001,-62.9416 92.9287,-1.01519 145.901,0.989157 176.877,11.974 29.9871,11.0109 43.9915,28.9979 43.9915,76.972l0 802.519 -65.9612 0z"/>
|
||||
<glyph unicode="化" horiz-adv-x="999" d="M319.81 834.51c-61.9525,-153.918 -164.903,-303.827 -271.836,-400.765 12.9892,-14.0044 35.9741,-47.9741 43.9654,-61.9525 42.9763,39.9567 83.9482,88.9461 122.942,142.907l0 -590.657 68.9547 0 0 693.581c37.9784,61.9785 71.9482,128.929 99.9309,196.894l-63.9568 19.9914zm328.817 -825.504c-48.9893,0 -59.9742,10.9849 -59.9742,65.9612l0 234.847c128.929,93.9439 252.86,209.884 342.795,336.808l-63.9568 41.9611c-70.959,-108.911 -169.901,-209.857 -278.838,-294.821l0 422.761 -69.9699 0 0 -474.717c-62.9416,-43.9915 -127.914,-82.959 -190.881,-113.935 16.0087,-12.9892 37.9784,-35.9741 48.9893,-49.9785 45.9698,24.0001 93.9439,51.9828 141.892,83.9482l0 -184.894c0,-104.929 28.0088,-133.901 123.931,-133.901l181.901 0c102.95,0 121.927,63.9568 131.922,247.836 -19.9914,6.01303 -46.9589,19.9914 -64.972,32.9806 -7.99135,-171.905 -15.9827,-214.855 -69.9438,-214.855l-172.894 0z"/>
|
||||
<glyph unicode="店" horiz-adv-x="999" d="M791.534 36.9893l-434.735 0 0 188.877 434.735 0 0 -188.877zm-211.862 576.653l-66.9764 0 0 -325.823 -220.868 0 0 -349.771 64.972 0 0 38.9676 434.735 0 0 -36.9893 66.9503 0 0 347.793 -278.812 0 0 141.918 326.786 0 0 60.9633 -326.786 0 0 122.942zm19.9654 96.9374c-13.9784,36.9893 -40.9719,83.9482 -66.9503,120.937l-63.9568 -16.9979c20.9805,-29.9871 41.9611,-69.9438 55.9655,-103.94l-394.778 0 0 -259.836c0,-143.922 -8.98051,-345.815 -94.9331,-489.711 16.9719,-7.00219 44.9806,-26.0044 56.9546,-36.9893 90.9504,149.909 104.955,373.771 104.955,526.7l0 196.868 741.555 0 0 62.9677 -338.812 0z"/>
|
||||
<glyph unicode="技" horiz-adv-x="999" d="M370.778 334.804l-7.00219 60.9633 -113.935 -32.9806 0 206.89 112.946 0 0 61.9525 -112.946 0 0 202.881 -65.9612 0 0 -202.881 -129.918 0 0 -61.9525 129.918 0 0 -225.866c-53.9611,-14.9935 -102.924,-27.9827 -142.907,-37.9784l19.9914 -64.972 122.916 36.9893 0 -270.847c0,-14.9935 -4.97182,-19.9914 -18.9762,-19.9914 -12,-1.01519 -55.9655,-1.01519 -103.94,0 7.99135,-17.987 17.987,-43.9654 20.9805,-60.9633 67.9655,0 107.948,2.00434 132.938,12 23.974,10.9849 34.9589,28.9719 34.9589,68.9547l0 290.812 120.937 36.9893zm445.745 62.9677c-37.9784,-94.9591 -97.9526,-175.914 -169.901,-239.871 -65.9612,65.9612 -117.944,147.931 -151.914,239.871l321.814 0zm40.9719 63.9568l-12 -2.9935 -165.892 0 0 154.907 242.864 0 0 61.9525 -242.864 0 0 159.905 -64.972 0 0 -159.905 -238.855 0 0 -61.9525 238.855 0 0 -154.907 -216.86 0 0 -60.9633 29.9871 0c38.9676,-109.953 95.9222,-203.897 167.896,-281.832 -82.959,-60.9633 -178.907,-104.955 -276.834,-131.922 12.9892,-14.0044 29.9871,-40.9719 37.9784,-59.9742 101.935,31.9914 200.877,79.9655 287.819,145.927 74.9677,-64.972 164.903,-114.95 269.858,-146.916 9.96966,17.987 28.9719,43.9654 42.9502,57.9698 -101.935,26.9675 -189.866,71.9482 -262.829,132.911 90.9504,83.9482 162.899,191.896 204.886,328.817l-41.9871 18.9762z"/>
|
||||
<glyph unicode="新" horiz-adv-x="999" d="M502.7 729.581l-166.907 0c-12.9892,31.9654 -35.9741,74.9417 -55.9655,108.937l-58.959 -16.0087c14.9935,-27.9827 31.9914,-62.9677 44.9806,-92.9287l-200.877 0 0 -56.9807 437.728 0 0 56.9807zm-272.825 -208.894c-4.00869,38.9936 -21.9957,98.9417 -43.9915,143.922l-52.972 -12.9892c19.9914,-45.9698 36.0001,-106.933 39.9828,-146.916l56.9807 15.9827zm-87.9569 -282.821c-19.9914,-62.9677 -53.9611,-124.92 -94.9331,-168.912 12.9892,-7.99135 36.9632,-25.9784 46.9589,-34.9849 39.9828,47.9741 79.9655,120.937 102.95,189.892l-54.9763 14.0044zm365.78 39.9828l0 57.9438 -189.892 0 0 108.937 200.877 0 0 56.9807 -130.907 0c18.9762,43.9654 39.9828,100.946 56.9546,149.909l-60.9633 13.9784c-12.9892,-46.9589 -36.9632,-116.929 -56.9546,-163.888l-276.834 0 0 -56.9807 206.864 0 0 -108.937 -202.881 0 0 -57.9438 202.881 0 0 -260.851c0,-9.99569 -2.00434,-12.9892 -12.9892,-12.9892 -10.9849,-1.01519 -40.9719,-1.01519 -74.9417,0 8.98051,-16.9979 16.9719,-40.998 18.9762,-56.9807 46.985,0 80.9547,0 101.935,9.99569 21.0066,10.9849 27.9827,25.9784 27.9827,58.959l0 261.866 189.892 0zm-146.916 -59.9742c30.9762,-49.9785 67.9655,-118.933 82.959,-161.909l47.9741 25.9784c-14.9935,42.9763 -51.9828,109.953 -83.9482,159.905l-46.985 -23.974zm592.661 280.843l-338.812 0 0 195.879c105.944,16.9979 222.873,40.9719 304.817,72.9634l-53.9611 47.9741c-70.959,-28.9979 -199.888,-57.9698 -311.819,-76.972l0 -338.786c0,-133.927 -8.98051,-304.843 -94.9331,-425.754 14.9935,-7.00219 39.9828,-27.9827 50.9676,-40.9719 91.9396,130.907 104.929,323.793 104.929,466.726l0 36.9632 161.909 0 0 -507.698 63.9568 0 0 507.698 112.946 0 0 61.9785z"/>
|
||||
<glyph unicode="理" horiz-adv-x="999" d="M351.802 195.879c-36.9893,-12 -75.9569,-24.9892 -111.931,-36.9632l0 256.842 102.924 0 0 61.9525 -102.924 0 0 224.877 116.929 0 0 62.9677 -305.832 0 0 -62.9677 124.92 0 0 -224.877 -115.914 0 0 -61.9525 115.914 0 0 -276.834c-50.9676,-16.9979 -97.9266,-31.9914 -135.905,-41.9871l15.9827 -66.9503c86.9417,27.9827 200.877,66.9503 306.821,102.924l-10.9849 62.9677zm116.929 344.799l160.894 0 0 -135.905 -160.894 0 0 135.905zm0 188.903l160.894 0 0 -132.938 -160.894 0 0 132.938zm381.763 -132.938l-162.899 0 0 132.938 162.899 0 0 -132.938zm0 -191.87l-162.899 0 0 135.905 162.899 0 0 -135.905zm-157.901 -385.797l0 143.922 236.851 0 0 60.9633 -236.851 0 0 122.942 221.884 0 0 441.737 -506.709 0 0 -441.737 217.875 0 0 -122.942 -230.864 0 0 -60.9633 230.864 0 0 -143.922 -308.825 0 0 -60.9633 645.607 0 0 60.9633 -269.832 0z"/>
|
||||
<glyph unicode="科" horiz-adv-x="999" d="M712.584 628.635c-32.9806,41.9611 -103.94,97.9266 -163.914,135.905l-42.9763 -38.9676c60.9633,-39.9828 129.944,-97.9526 161.909,-139.914l44.9806 42.9763zm-22.9849 -262.855c-37.9784,42.9763 -116.929,101.935 -181.901,139.914l-40.9719 -37.9784c64.972,-40.9719 141.918,-101.935 178.907,-145.901l43.9654 43.9654zm-264.86 -69.9438c-21.9697,28.9719 -109.927,143.896 -140.903,177.892l0 18.9762 150.899 0 0 61.9785 -150.899 0 0 171.879c48.9633,12 94.9331,26.0044 132.911,41.9871l-41.9611 51.9568c-72.9634,-32.9806 -205.875,-61.9525 -316.817,-79.9395 7.00219,-14.9935 15.9827,-36.9893 18.9762,-51.9828 45.9698,6.01303 94.9591,14.9935 142.933,24.9892l0 -158.89 -171.905 0 0 -61.9785 161.909 0c-39.9828,-117.918 -111.931,-250.855 -175.914,-322.804 12,-14.9935 26.9936,-41.9871 33.9958,-58.959 53.9611,63.9568 109.927,167.896 151.914,272.825l0 -456.73 63.9568 0 0 474.717c35.9741,-52.9459 81.9439,-124.92 99.9309,-157.901l40.9719 51.9828zm534.691 -84.9634l-9.99569 60.9633 -119.922 -19.9914 0 583.655 -64.972 0 0 -593.65 -341.78 -54.9503 10.9849 -60.9633 330.795 52.972 0 -251.871 64.972 0 0 261.84 129.918 21.9957z"/>
|
||||
<glyph unicode="管" horiz-adv-x="999" d="M260.851 700.584c20.9805,-36.9632 42.9763,-80.9547 50.9676,-109.927l56.9546 18.9762c-7.99135,24.0001 -24.9632,58.985 -43.9654,90.9504l156.912 0 0 50.9676 -273.84 0c9.99569,24.0001 18.9762,48.9893 26.9936,72.9634l-64.972 12c-23.974,-86.9677 -66.9503,-169.901 -120.937,-226.881 16.0087,-6.97616 42.9763,-22.9849 55.9655,-30.9762 29.9871,32.9806 56.9807,74.9677 80.9547,121.927l74.9677 0zm512.696 -585.659l0 -102.924 -490.7 0 0 102.924 490.7 0zm-50.9676 269.858l0 -90.9504 -439.732 0 0 90.9504 439.732 0zm-439.732 -142.933l504.678 0 0 194.89 -571.655 0 0 -511.707 66.9764 0 0 33.9958 490.7 0 0 -31.9914 65.9612 0 0 240.86 -556.661 0 0 73.9525zm160.894 377.78c12,-19.9914 23.974,-42.9763 31.9914,-64.946l-366.795 0 0 -161.909 63.9568 0 0 108.937 669.607 0 0 -108.937 66.9764 0 0 161.909 -366.795 0c-9.00654,23.974 -22.9849,54.9503 -38.9676,76.946l-59.9742 -12zm183.879 130.933c9.99569,23.974 18.0131,48.9633 24.9892,73.9525l-63.9568 10.9849c-16.9979,-71.9482 -51.9568,-142.907 -95.9482,-190.881 16.0087,-7.00219 42.9763,-21.9957 53.9872,-30.9762 20.9805,22.9849 39.9567,53.9611 57.9438,85.9525l76.972 0c28.9719,-35.9741 57.9698,-81.9699 69.9438,-112.946l54.9763 24.9892c-10.9849,24.0001 -32.9806,57.9698 -55.9655,87.9569l183.879 0 0 50.9676 -306.821 0z"/>
|
||||
<glyph unicode="能" horiz-adv-x="999" d="M166.907 183.879l0 96.9634 222.873 0 0 -96.9634 -222.873 0zm222.873 240.86l0 -90.9244 -222.873 0 0 90.9244 222.873 0zm64.946 56.9807l-349.797 0 0 -556.687 61.9785 0 0 204.886 222.873 0 0 -124.92c0,-12.9892 -4.00869,-16.9979 -16.9979,-16.9979 -14.0044,-0.989157 -56.9546,-0.989157 -105.944,1.01519 9.00654,-17.987 19.0022,-43.9915 22.9849,-61.9785 61.9785,0 105.944,1.01519 131.922,12 26.0044,9.99569 32.9806,28.9719 32.9806,64.972l0 477.711zm-140.903 270.847c25.9784,-33.9958 52.972,-74.9677 75.9569,-115.94l-231.879 -12.9892c43.9915,53.9611 88.9461,121.927 124.946,190.881l-66.9764 20.9805c-33.9697,-76.946 -89.9352,-156.886 -106.933,-177.892 -16.9979,-22.9849 -31.9914,-35.9741 -45.9698,-38.9676 7.99135,-17.987 18.9762,-49.9785 21.9697,-63.9568 21.0066,7.99135 53.9872,11.974 332.825,30.9762 8.98051,-19.0022 17.987,-36.9893 23.974,-51.9828l56.9807 26.0044c-21.0066,58.959 -77.9612,148.894 -130.933,215.871l-53.9611 -22.9849zm529.694 -351.802c76.946,0 96.9374,30.9762 104.929,150.899 -19.0022,4.99785 -44.9806,14.9935 -58.959,26.9936 -4.99785,-100.946 -12,-117.918 -51.9828,-117.918l-165.892 0c-46.985,0 -54.9763,5.987 -54.9763,36.9632l0 108.937c97.9526,28.9979 205.875,65.9612 285.84,101.935l-45.9698 48.9893c-57.9698,-29.9871 -151.914,-67.9655 -239.871,-95.9482l0 170.89 -65.9612 0 0 -335.793c0,-75.9569 24.9892,-95.9482 115.94,-95.9482l176.903 0zm-168.912 -407.767c-47.9741,0 -57.9698,6.01303 -57.9698,37.9784l0 122.942c102.95,27.9827 219.879,66.9503 296.825,110.916l-42.9763 49.9785c-58.959,-36.9632 -159.905,-76.946 -253.849,-104.929l0 160.894 -64.972 0 0 -339.802c0,-76.946 24.9892,-96.9374 116.955,-96.9374l179.896 0c80.9287,0 100.92,33.9697 108.911,166.907 -18.9762,4.99785 -43.9654,13.9784 -58.959,24.9892 -4.99785,-112.946 -12.9892,-132.938 -54.9503,-132.938l-168.912 0z"/>
|
||||
<glyph unicode="营" horiz-adv-x="999" d="M778.545 141.918l0 -123.931 -540.679 0 0 123.931 540.679 0zm-603.646 -220.868l62.9677 0 0 39.9828 540.679 0 0 -37.9784 64.972 0 0 277.823 -668.618 0 0 -279.827zm530.683 396.756l-401.754 0 0 93.9439 401.754 0 0 -93.9439zm-464.722 142.933l0 -191.896 530.683 0 0 191.896 -530.683 0zm-145.927 -66.9764l60.9633 0 0 136.92 692.618 0 0 -136.92 64.946 0 0 190.881 -818.528 0 0 -190.881zm611.664 355.784l0 84.9634 -65.9612 0 0 -84.9634 -286.856 0 0 84.9634 -64.946 0 0 -84.9634 -223.862 0 0 -60.9633 223.862 0 0 -73.9525 64.946 0 0 73.9525 286.856 0 0 -73.9525 65.9612 0 0 73.9525 229.849 0 0 60.9633 -229.849 0z"/>
|
||||
<glyph unicode="赋" horiz-adv-x="999" d="M948.446 678.614c-15.9827,36.9632 -55.9655,92.9287 -94.9591,130.907l-45.9698 -21.9957c36.9893,-39.9567 75.9569,-96.9374 91.9656,-134.916l48.9633 26.0044zm-256.842 77.9352l-249.866 0 0 -56.9546 249.866 0 0 56.9546zm-554.683 -40.9719l178.907 0 0 -524.696 50.9676 0 0 585.659 -279.853 0 0 -587.663 49.9785 0 0 526.7zm117.918 -71.9482l-54.9503 0 0 -269.858c0,-120.911 -11.0109,-298.804 -156.912,-395.767 12.9892,-10.9849 29.9871,-29.961 36.9893,-41.9611 159.905,112.92 174.873,299.819 174.873,437.728l0 269.858zm-17.987 -500.722c34.9849,-49.9524 72.9634,-117.918 89.9612,-159.905l48.9633 31.0023c-17.987,39.9567 -56.9546,104.929 -90.9504,153.892l-47.9741 -24.9892zm390.769 -84.9374l0 213.866 96.9634 0 0 57.9698 -96.9634 0 0 164.903 -54.9503 0 0 -446.735 -79.9655 -14.9935 0 399.776 -52.972 0 0 -408.782 -55.9655 -9.96966 12.9892 -59.9742c96.9634,19.9914 230.864,46.9589 357.789,72.9634l-3.98266 53.9611 -122.942 -22.9849zm325.823 477.711l0 56.9807 -167.896 0c-2.9935,75.9569 -4.00869,155.896 -4.00869,239.845l-58.959 0c0.989157,-81.9439 2.9935,-162.899 5.987,-239.845l-330.795 0 0 -56.9807 333.788 0c16.9979,-344.799 58.985,-611.638 153.918,-611.638 54.9763,0 72.9634,47.9741 80.9547,195.879 -14.9935,6.01303 -33.9697,19.0022 -46.985,31.9914 -1.97831,-112.946 -10.9849,-167.896 -24.9632,-167.896 -48.9893,0 -90.9504,225.866 -106.959,551.663l165.918 0z"/>
|
||||
<glyph unicode="运" horiz-adv-x="999" d="M878.476 769.538l-498.691 0 0 -61.9525 498.691 0 0 61.9525zm-502.7 -648.601c27.9827,12.9892 69.9699,16.9719 448.739,49.9524 15.9827,-27.9827 29.9871,-53.9611 39.9828,-75.9569l58.959 31.0023c-38.9676,74.9417 -117.918,204.86 -181.901,302.812l-53.9611 -24.9892c32.9806,-52.972 71.9482,-115.94 105.944,-175.888l-343.81 -24.9892c54.9763,77.9612 108.937,177.892 150.925,275.845l349.797 0 0 62.9677 -635.638 0 0 -62.9677 205.875 0c-38.9676,-102.95 -96.9374,-203.897 -114.924,-231.879 -20.9805,-31.9654 -36.9893,-53.9611 -53.9611,-57.9698 7.99135,-18.9762 19.9914,-51.9568 21.9697,-67.9395 0,1.97831 1.01519,3.98266 2.00434,5.987l0 -5.987zm-80.9547 530.683c-39.9828,33.9697 -120.911,87.9569 -177.892,125.935l-43.9654 -41.9871c58.959,-40.9719 136.92,-97.9526 176.877,-131.922l44.9806 47.9741zm-44.9806 -165.918l-203.87 0 0 -61.9525 138.925 0 0 -323.819c-42.9763,-17.987 -92.9547,-62.9416 -142.907,-118.907l45.9698 -59.9742c50.9676,67.9655 100.92,125.935 133.901,125.935 24.0001,0 58.985,-32.9806 97.9526,-57.9698 70.959,-42.9763 152.903,-54.9763 275.845,-54.9763 106.933,0 277.823,4.99785 344.799,9.99569 0.989157,19.9914 11.974,52.972 19.9914,71.9482 -100.946,-9.99569 -248.851,-17.987 -363.802,-17.987 -110.942,0 -193.875,7.00219 -260.851,48.9893 -39.9567,24.9632 -63.9568,45.9698 -85.9525,55.9655l0 382.752z"/>
|
||||
<glyph unicode="酒" horiz-adv-x="999" d="M274.83 718.571c-36.9632,26.9936 -108.937,68.9547 -161.883,97.9526l-37.9784 -46.985c52.9459,-30.9762 124.92,-76.946 160.894,-104.929l38.9676 53.9611zm-29.961 -261.84c-38.9936,25.9784 -114.95,66.9503 -169.901,93.9439l-36.0001 -48.9633c55.9655,-28.9979 129.944,-71.9742 167.922,-99.9569l37.9784 54.9763zm-128.929 -516.704c50.9676,90.9504 113.935,218.89 159.905,323.819l-51.9828 38.9676c-49.9524,-112.92 -117.918,-245.858 -165.892,-324.808l57.9698 -37.9784zm545.676 636.627l-100.946 0 0 141.918 100.946 0 0 -141.918zm187.888 -205.875c-2.00434,-2.00434 -7.00219,-2.00434 -20.9805,-2.00434l-86.9677 0c-23.974,0 -27.9827,2.00434 -27.9827,19.0022l0 129.918 135.931 0 0 -146.916zm-458.735 -338.786l0 122.916 458.735 0 0 -122.916 -458.735 0zm117.944 485.702l0 -36.9632c0,-54.9763 -21.9957,-120.937 -117.944,-172.92l0 209.884 117.944 0zm328.791 -203.87c4.00869,0 7.99135,0 12,0l0 -100.946 -458.735 0 0 87.9569c12,-9.00654 27.9827,-24.9892 32.9806,-34.9849 110.942,58.959 138.925,143.922 138.925,214.881l0 36.9632 96.9374 0 0 -130.933c0,-58.959 16.9979,-72.9373 76.946,-72.9373l100.946 0zm113.935 404.747l0 60.9633 -659.612 0 0 -60.9633 208.868 0 0 -141.918 -171.879 0 0 -651.62 61.9525 0 0 47.9741 458.735 0 0 -43.9654 62.9677 0 0 647.612 -189.892 0 0 141.918 228.86 0z"/>
|
||||
</font>
|
||||
<font id="FontID0" horiz-adv-x="606" font-variant="normal" style="fill-rule:nonzero" font-style="normal" font-weight="400">
|
||||
<font-face
|
||||
font-family="思源黑体 Regular">
|
||||
<font-face-src>
|
||||
<font-face-name name="思源黑体 Regular"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<missing-glyph><path d="M0 0z"/></missing-glyph>
|
||||
<glyph unicode="A" horiz-adv-x="606" d="M190.873 297.795l35.9754 111.918c25.9835,82.9465 49.9594,161.901 72.9547,247.836l3.99208 0c23.9758,-84.9309 46.9711,-164.889 73.9585,-247.836l34.9715 -111.918 -221.852 0zm314.791 -297.795l97.9343 0 -248.84 732.512 -102.93 0 -248.84 -732.512 93.9423 0 70.947 223.86 267.819 0 69.9664 -223.86z"/>
|
||||
<glyph unicode="E" horiz-adv-x="587" d="M99.9421 0l433.689 0 0 78.9545 -340.751 0 0 266.816 277.811 0 0 78.9545 -277.811 0 0 229.836 329.778 0 0 77.9506 -422.717 0 0 -732.512z"/>
|
||||
<glyph unicode="H" horiz-adv-x="727" d="M99.9421 0l92.9384 0 0 345.77 341.755 0 0 -345.77 91.9345 0 0 732.512 -91.9345 0 0 -306.806 -341.755 0 0 306.806 -92.9384 0 0 -732.512z"/>
|
||||
<glyph unicode="L" horiz-adv-x="541" d="M99.9421 0l412.702 0 0 78.9545 -319.763 0 0 653.557 -92.9384 0 0 -732.512z"/>
|
||||
<glyph unicode="M" horiz-adv-x="811" d="M99.9421 0l83.927 0 0 405.721c0,62.9628 -6.9803,151.909 -10.9957,215.852l4.01542 0 57.9435 -166.874 138.906 -380.742 61.9589 0 138.906 380.742 57.9669 166.874 3.99208 0c-4.99594,-63.9433 -11.9762,-152.89 -11.9762,-215.852l0 -405.721 86.9386 0 0 732.512 -111.918 0 -139.91 -391.737c-16.9955,-50.9632 -32.9872,-101.926 -49.9827,-152.89l-4.99594 0c-17.976,50.9632 -34.9715,101.926 -51.9437,152.89l-140.913 391.737 -111.918 0 0 -732.512z"/>
|
||||
<glyph unicode="O" horiz-adv-x="741" d="M370.75 -12.9801c183.869,0 312.783,146.89 312.783,381.722 0,234.856 -128.914,377.753 -312.783,377.753 -183.869,0 -312.783,-142.898 -312.783,-377.753 0,-234.832 128.914,-381.722 312.783,-381.722zm0 80.9388c-131.902,0 -217.86,117.918 -217.86,300.783 0,183.892 85.9581,296.815 217.86,296.815 130.922,0 217.86,-112.922 217.86,-296.815 0,-182.865 -86.9386,-300.783 -217.86,-300.783z"/>
|
||||
<glyph unicode="R" horiz-adv-x="634" d="M192.88 657.549l122.914 0c114.907,0 177.869,-33.9677 177.869,-130.898 0,-94.9461 -62.9628,-140.913 -177.869,-140.913l-122.914 0 0 271.812zm414.709 -657.549l-187.861 320.79c99.9187,23.9758 165.87,91.9345 165.87,205.861 0,152.89 -106.922,205.861 -255.82,205.861l-229.836 0 0 -732.512 92.9384 0 0 310.799 131.902 0 177.869 -310.799 104.938 0z"/>
|
||||
<glyph unicode="S" horiz-adv-x="596" d="M303.932 -13.0016c152.962,0 248.934,91.9794 248.934,207.96 0,108.974 -65.9871,158.956 -150.96,195.948l-104.981 44.9887c-56.9784,23.9903 -120.964,50.9836 -120.964,121.976 0,65.9761 53.9865,107.973 136.968,107.973 67.9781,0 121.965,-26.9932 166.953,-68.99l48.9926 58.9913c-51.9845,53.9865 -128.971,90.9784 -215.946,90.9784 -132.975,0 -230.949,-81.9807 -230.949,-194.958 0,-106.972 80.9797,-158.956 148.969,-187.952l105.971 -45.9897c68.979,-30.9971 121.976,-54.9874 121.976,-129.972 0,-71.982 -57.9904,-119.963 -153.974,-119.963 -75.9748,0 -149.959,35.991 -202.944,90.9784l-54.9874 -62.9952c63.9852,-66.9771 152.962,-108.974 256.942,-108.974z"/>
|
||||
<glyph unicode="T" horiz-adv-x="598" d="M252.832 0l92.9384 0 0 654.561 221.852 0 0 77.9506 -536.643 0 0 -77.9506 221.852 0 0 -654.561z"/>
|
||||
<glyph unicode="客" horiz-adv-x="1000" d="M153.025 678.18l691.173 0 0 -119.034 75.0362 0 0 188.033 -356.086 0c-16.0112,31.0053 -38.0267,69.032 -58.0407,98.0359l-72.0177 -18.0126c15.0269,-24.0168 31.0381,-54.0051 45.0152,-80.0233l-398.082 0 0 -188.033 73.002 0 0 119.034zm125.038 -449.134c78.0219,25.0011 153.025,57.0236 223.042,95.0174 72.0177,-38.9781 151.057,-70.0163 236.067,-95.0174l-459.109 0zm27.0025 -208.047l0 145.052 395.097 0 0 -145.052 -395.097 0zm52.0365 507.142l302.048 0c-41.0124,-46.0323 -95.0174,-87.0446 -157.028,-125.038 -59.025,35.9924 -110.012,76.0205 -149.022,121.036l4.00281 4.00281zm366.06 62.0107l-12.9927 -3.01851 -297.061 0c15.9784,20.014 31.9896,39.0109 45.9995,59.025l-80.0233 14.0098c-50.0023,-76.0205 -147.021,-163.032 -284.068,-224.059 16.9955,-12.0084 39.0109,-36.0252 50.0023,-53.0208 59.025,29.0039 111.029,62.0107 156.044,97.0188 37.0095,-41.9966 81.0404,-80.0233 131.043,-115.031 -120.019,-58.9922 -260.051,-102.006 -393.095,-125.006 12.9927,-16.0112 29.0039,-46.0323 35.9924,-65.0292 52.0365,10.9913 105.024,22.9997 158.045,39.0109l0 -290.072 72.0177 0 0 33.0067 395.097 0 0 -31.9896 75.0362 0 0 294.042c45.0152,-11.9756 91.9989,-21.9826 139.015,-27.9868 11.0241,20.9983 30.021,53.0208 47.0166,70.0163 -142.034,18.0126 -276.062,54.0051 -387.091,106.009 81.0076,53.0208 150.04,117.033 199.058,191.052l-50.0351 32.0224z"/>
|
||||
<glyph unicode="店" horiz-adv-x="1000" d="M787.175 41.9966l-422.099 0 0 179.044 422.099 0 0 -179.044zm-201.026 568.136l-75.0362 0 0 -320.06 -218.054 0 0 -354.084 72.0177 0 0 39.9952 422.099 0 0 -37.9938 74.0191 0 0 352.083 -275.045 0 0 134.028 323.079 0 0 68.0149 -323.079 0 0 118.017zm16.0112 105.024c-14.0098,36.0252 -38.0267,83.0418 -64.0449,119.034l-71.0006 -17.9798c20.014,-30.021 37.9938,-68.0149 52.0037,-101.054l-390.077 0 0 -259.034c0,-144.035 -9.02272,-347.096 -94.0331,-491.131 18.0126,-8.00561 51.0194,-30.021 65.0292,-41.9966 89.0132,151.024 104.007,379.085 104.007,533.128l0 187.016 736.188 0 0 72.0177 -338.073 0z"/>
|
||||
<glyph unicode="房" horiz-adv-x="1000" d="M808.206 674.177l0 -106.042 -594.154 0 0 106.042 594.154 0zm-594.154 -170.054l667.156 0 0 234.066 -323.079 0c-10.9913,29.9882 -27.0025,68.9992 -43.0138,99.0202l-71.0006 -20.014c10.9913,-22.9997 21.9826,-53.0208 31.9896,-79.0062l-336.072 0 0 -238.068c0,-156.044 -8.98991,-380.102 -103.023,-538.115 18.9969,-7.02131 52.0037,-25.0339 66.0135,-37.0095 96.0345,167.035 111.029,411.075 111.029,575.124l0 4.00281zm701.18 -195.055l0 62.0107 -338.106 0 54.0379 22.0154c-13.0255,29.0039 -40.0281,73.002 -64.0121,107.026l-63.0278 -22.0154c20.9983,-33.0067 45.9995,-78.0219 59.025,-107.026l-318.092 0 0 -62.0107 189.051 0c-14.9941,-154.042 -58.0079,-267.072 -234.066,-328.066 14.9941,-13.0255 35.0081,-39.0109 43.0138,-56.0065 136.03,50.0023 202.043,130.026 235.05,235.05l298.078 0c-10.9913,-101.022 -22.0154,-145.052 -37.9938,-159.062 -8.00561,-6.9885 -18.0126,-8.98991 -38.0267,-8.98991 -18.9969,0 -74.0191,1.01711 -129.008,6.00421 10.9913,-16.9955 18.9969,-41.9966 20.9983,-61.0264 56.0065,-4.00281 110.012,-4.00281 138.031,-2.9857 29.9882,2.0014 50.0023,8.00561 68.0149,25.0011 27.0025,24.0168 39.0109,85.0104 53.0208,231.047 2.0014,9.02272 2.9857,29.0039 2.9857,29.0039l-53.0208 0 0 1.01711 -306.051 0c4.9871,28.0196 8.98991,58.0079 12.9927,89.0132l407.105 0z"/>
|
||||
<glyph unicode="理" horiz-adv-x="1000" d="M353.1 201.059l-109.027 -36.0252 0 247.058 101.022 0 0 70.0163 -101.022 0 0 217.07 114.999 0 0 70.0163 -310.053 0 0 -70.0163 124.021 0 0 -217.07 -114.014 0 0 -70.0163 114.014 0 0 -269.074c-51.0194,-16.9955 -97.0188,-31.0053 -134.028,-41.9966l16.9955 -75.0034c89.0132,29.0039 203.06,68.0149 310.086,104.007l-12.9927 71.0334zm123.004 338.073l152.041 0 0 -128.024 -152.041 0 0 128.024zm0 187.049l152.041 0 0 -126.023 -152.041 0 0 126.023zm369.111 -126.023l-153.058 0 0 126.023 153.058 0 0 -126.023zm0 -189.051l-153.058 0 0 128.024 153.058 0 0 -128.024zm-147.054 -387.091l0 137.014 233.049 0 0 68.0149 -233.049 0 0 117.033 218.054 0 0 445.099 -508.127 0 0 -445.099 215.069 0 0 -117.033 -227.077 0 0 -68.0149 227.077 0 0 -137.014 -304.082 0 0 -68.0149 644.156 0 0 68.0149 -265.071 0z"/>
|
||||
<glyph unicode="管" horiz-adv-x="1000" d="M260.051 699.179c21.0311,-37.0095 43.0138,-80.0233 52.0365,-110.044l62.995 22.9997c-8.00561,23.0325 -25.0011,56.0393 -43.9981,87.0446l152.041 0 0 56.0065 -267.072 0c10.007,24.0168 18.0126,47.0166 25.0011,72.0177l-72.0177 12.0084c-24.0168,-86.0275 -68.0149,-170.054 -122.02,-226.06 18.0126,-8.00561 49.018,-25.0011 62.995,-34.0238 30.021,32.0224 57.0236,73.0348 81.0404,120.051l68.9992 0zm509.144 -588.15l0 -96.0345 -481.124 0 0 96.0345 481.124 0zm-52.0365 269.074l0 -85.0432 -429.088 0 0 85.0432 429.088 0zm-429.088 -142.034l502.122 0 0 199.025 -576.142 0 0 -514.098 74.0191 0 0 33.991 481.124 0 0 -31.9896 73.002 0 0 244.04 -554.126 0 0 69.032zm153.025 382.071c11.0241,-18.9969 21.0311,-41.9966 30.021,-62.995l-367.077 0 0 -163.065 72.0177 0 0 104.04 661.152 0 0 -104.04 74.0191 0 0 163.065 -364.091 0c-9.02272,23.984 -26.0182,54.0051 -40.0281,77.0048l-66.0135 -14.0098zm196.072 134.028c8.98991,24.0168 16.9955,47.0166 23.984,72.0177l-72.0177 12.0084c-17.9798,-72.0177 -52.0037,-143.018 -97.0188,-190.035 18.0126,-8.00561 48.0009,-24.0168 61.0264,-35.0081 20.9983,22.9997 41.0124,53.0208 58.9922,86.0275l70.0163 0c29.0367,-37.0095 58.0407,-82.0247 71.0334,-113.03l60.0093 27.9868c-10.9913,23.0325 -31.9896,55.0222 -55.0222,85.0432l178.059 0 0 54.9894 -299.062 0z"/>
|
||||
<glyph unicode="系" horiz-adv-x="1000" d="M288.071 225.043c-52.0037,-71.0006 -134.028,-145.02 -214.052,-193.021 20.014,-10.007 50.0023,-35.0081 65.0292,-49.018 75.0034,52.988 163.032,136.03 223.042,216.053l-74.0191 25.9854zm506.125 82.0247c27.9868,-33.0067 53.0208,-64.9964 70.0163,-90.0303l59.025 36.0252c-41.0124,60.0093 -126.056,152.041 -204.077,220.056l-56.0065 -29.0039c26.0182,-25.0011 54.0051,-52.0037 80.0233,-81.0404l-437.093 -27.9868c150.04,72.0177 302.048,164.049 448.085,275.045l-56.9908 48.0337c-50.0351,-41.0124 -105.024,-81.0404 -159.062,-117.033l-242.038 -12.0084c71.0006,51.0194 144.035,116.016 209.032,184.063 130.058,12.9927 253.063,31.9896 348.113,54.9894l-53.0208 61.0264c-160.047,-40.0281 -449.102,-66.0135 -690.189,-79.0062 8.00561,-17.0283 17.0283,-46.0323 19.0297,-65.0292 87.0118,4.00281 180.028,10.007 273.044,18.0126 -64.9964,-68.0149 -138.031,-127.04 -164.017,-143.051 -29.0039,-22.9997 -52.0365,-37.9938 -73.0348,-39.9952 8.00561,-19.0297 18.0126,-53.0208 22.0154,-67.0306 18.9969,8.00561 51.0194,12.0084 254.047,24.0168 -85.9947,-52.0037 -159.029,-92.0317 -193.021,-108.043 -62.0435,-31.0053 -106.042,-50.0023 -139.048,-54.0051 8.98991,-20.014 20.014,-54.0051 22.9997,-68.9992 28.0196,10.9913 67.0306,16.9955 340.074,37.0095l0 -260.084c0,-12.0084 -2.9857,-16.0112 -19.9812,-16.9955 -16.0112,0 -70.0163,0 -130.058,2.0014 12.0084,-20.9983 25.0339,-51.0194 28.0196,-73.0348 73.0348,0 123.037,0 155.027,13.0255 33.0067,12.0084 42.0295,31.9896 42.0295,74.0191l0 267.04 247.058 18.0126zm-159.029 -115.031c83.009,-64.0121 185.048,-155.027 234.033,-211.033l63.0278 45.0152c-53.0208,56.0065 -156.044,144.035 -238.068,204.045l-58.9922 -38.0267z"/>
|
||||
<glyph unicode="统" horiz-adv-x="1000" d="M945.22 362.09c-29.0039,56.0065 -94.0003,149.022 -147.021,219.039l-58.0079 -29.0039c21.9826,-29.0039 45.0152,-62.0107 66.0135,-94.0003l-274.061 -23.0325c43.9981,54.0379 101.022,131.043 143.018,190.068l269.074 0 0 66.9978 -284.068 0 62.995 20.014c-11.9756,32.0224 -37.9938,87.0118 -60.0093,127.04l-68.0149 -18.9969c18.9969,-40.0281 44.0309,-94.0331 54.0051,-128.057l-241.054 0 0 -66.9978 180.061 0c-44.0309,-62.0107 -115.031,-153.058 -138.031,-174.056 -18.0126,-18.9969 -44.0309,-25.9854 -62.0107,-31.0053 6.9885,-14.9941 20.9983,-54.0051 25.0011,-72.0177 27.0025,12.0084 68.9992,16.9955 430.105,51.0194 15.9784,-27.0025 29.9882,-52.0037 39.9952,-73.0348l62.0107 36.0252zm-763.191 -73.0348c75.0362,87.0446 150.04,193.053 212.05,301.096l-66.0135 39.0109c-18.9969,-36.0252 -39.9952,-74.0191 -62.995,-109.027l-121.036 -13.0255c61.0264,86.0275 121.036,194.07 168.052,298.078l-76.0205 35.0081c-43.0138,-120.019 -117.033,-248.043 -141.05,-281.049 -20.9983,-33.0067 -39.9952,-56.0393 -58.0079,-60.0093 8.98991,-22.0154 22.0154,-60.0421 26.0182,-77.0376 14.9941,8.00561 37.9938,12.9927 157.028,30.021 -41.9966,-62.0107 -81.0076,-112.046 -99.0202,-131.043 -31.0053,-37.0095 -55.0222,-61.0264 -75.0362,-66.0135 8.00561,-20.014 20.014,-56.0065 24.0168,-71.0334 20.9983,13.0255 54.0051,23.0325 301.063,77.0376 -2.9857,14.9941 -4.00281,45.0152 -2.0014,64.9964l-187.049 -37.0095zm186.065 -140.033c-120.019,-35.9924 -242.071,-72.0177 -322.095,-93.016l17.0283 -74.0191c89.0132,29.0039 206.046,66.0135 317.075,102.039l-12.0084 64.9964zm143.018 202.076c-6.9885,-197.056 -29.9882,-304.082 -192.036,-365.108 16.9955,-12.0084 37.0095,-41.0124 45.0152,-58.9922 181.045,73.002 212.05,200.042 220.056,424.101l-73.0348 0zm284.068 -343.093c-21.9826,0 -25.0011,4.00281 -25.0011,29.9882l0 314.089 -73.002 0 0 -314.089c0,-72.0177 16.9955,-94.0003 87.0118,-94.0003l87.0118 0c61.0264,0 78.0219,35.9924 84.0261,172.022 -18.9969,5.01991 -49.018,16.0112 -64.0121,30.021 -2.9857,-119.034 -6.9885,-138.031 -28.0196,-138.031l-68.0149 0z"/>
|
||||
<glyph unicode="酒" horiz-adv-x="1000" d="M122.02 -61.0264c50.0351,92.0317 111.029,218.054 156.044,324.096l-58.0079 41.9966c-50.0023,-113.03 -116.016,-245.057 -164.049,-323.079l66.0135 -43.0138zm126.056 521.152c-40.0281,25.9854 -115.031,66.0135 -169.069,93.016l-41.0124 -55.0222c55.0222,-29.0039 129.041,-72.0177 167.068,-99.0202l43.0138 61.0264zm-175.074 305.066c53.0208,-30.021 125.038,-76.0205 161.064,-104.04l43.9981 60.0093c-37.0095,26.0182 -110.012,69.032 -162.048,97.0516l-43.0138 -53.0208zm587.166 -186.065l-96.0345 0 0 134.061 96.0345 0 0 -134.061zm184.031 -205.029c-2.9857,-1.01711 -6.9885,-2.0014 -18.9969,-2.0014l-81.0076 0c-23.0325,0 -27.0353,2.0014 -27.0353,18.9969l0 122.02 127.04 0 0 -139.015zm-448.117 -337.089l0 115.031 448.117 0 0 -115.031 -448.117 0zm111.029 476.104l0 -33.991c0,-53.0208 -20.9983,-117.033 -111.029,-166.051l0 200.042 111.029 0zm326.097 -202.043l10.9913 0 0 -95.0174 -448.117 0 0 85.0104c13.0255,-10.007 28.0196,-25.0011 35.0081,-35.0081 108.043,57.0236 136.063,141.05 136.063,212.05l0 35.0081 91.0146 0 0 -123.004c0,-63.0278 16.9955,-79.039 80.0233,-79.039l95.0174 0zm119.034 402.118l0 68.0149 -660.168 0 0 -68.0149 206.046 0 0 -134.061 -170.054 0 0 -655.148 68.0149 0 0 47.0166 448.117 0 0 -43.9981 71.0334 0 0 652.129 -187.049 0 0 134.061 224.059 0z"/>
|
||||
</font>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
@font-face { font-family:"思源黑体 CN Normal";font-variant:normal;font-weight:300;src:url("#FontID1") format(svg)}
|
||||
@font-face { font-family:"思源黑体 Regular";font-variant:normal;font-style:normal;font-weight:normal;src:url("#FontID0") format(svg)}
|
||||
.fil0 {fill:#008C8C}
|
||||
.fil1 {fill:#008C8C}
|
||||
.fil2 {fill:#4D4D4D}
|
||||
.fnt2 {font-weight:normal;font-size:4.07px;font-family:'思源黑体 Regular'}
|
||||
.fnt3 {font-weight:300;font-size:5.13px;font-family:'思源黑体 CN Normal'}
|
||||
.fnt1 {font-weight:normal;font-size:5.72px;font-family:'思源黑体 Regular'}
|
||||
.fnt0 {font-weight:normal;font-size:12.14px;font-family:'思源黑体 Regular'}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="图层_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_2137283472080">
|
||||
<g transform="matrix(0.918858 0 0 1 174.059 100.154)">
|
||||
<text x="-190" y="-91.09" class="fil0 fnt0">S</text>
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 196.862 100.237)">
|
||||
<text x="-190" y="-91.09" class="fil1 fnt1">MART HOTEL</text>
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 197.243 94.5275)">
|
||||
<text x="-190" y="-91.09" class="fil2 fnt2">酒店客房管理系统</text>
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 189.826 106.261)">
|
||||
<text x="-190" y="-91.09" class="fil1 fnt3">科技创新赋能酒店</text>
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 189.826 106.261)">
|
||||
<text x="-190" y="-84.05" class="fil1 fnt3">优化酒店运营管理</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 32 KiB |
19
public/image/logo.svg
Normal file
19
public/image/logo.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW 2020 (64-Bit) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="10.8373mm" height="10.8373mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 17.27 17.27"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.fil0 {fill:#008C8C}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="图层_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<path class="fil0" d="M15.51 13.37c0.46,-0.85 0.72,-1.83 0.72,-2.87 0,-3.34 -2.71,-6.05 -6.05,-6.05 -1.05,0 -2.04,0.27 -2.9,0.74l0 2.5c0.73,-0.75 1.76,-1.22 2.9,-1.22 2.23,0 4.04,1.81 4.04,4.04 0,2.23 -1.81,4.04 -4.04,4.04 -1.11,0 -2.12,-0.45 -2.85,-1.18 -0.73,-0.71 -0.89,-1.79 -0.93,-2.87l0 -6.65 0 -3.25 0 -0.07 0 -0 0 -0.22c0.71,-0.19 1.46,-0.29 2.23,-0.29 4.77,0 8.63,3.87 8.63,8.63 0,4.77 -3.87,8.63 -8.63,8.63 -4.77,0 -8.63,-3.87 -8.63,-8.63 0,-3.18 1.72,-5.95 4.27,-7.45l0 0.25 0 0 0 0.08 0 2.32 0 6.23c0,0.99 0.04,1.49 0.25,2.25 0.48,1.72 1.65,3.02 3.26,3.73 0.74,0.32 1.55,0.5 2.41,0.5 0.64,0 1.27,-0.1 1.85,-0.29 1.41,-0.63 2.61,-1.63 3.48,-2.89z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
37
public/image/logobig.svg
Normal file
37
public/image/logobig.svg
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW 2020 (64-Bit) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="34.0028mm" height="5.4187mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 183.31 29.21"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.fil1 {fill:#008C8C}
|
||||
.fil0 {fill:#008C8C;fill-rule:nonzero}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="图层_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_1914568022976">
|
||||
<path class="fil0" d="M112.71 17.12l7.7 -4.25c-0.43,-0.45 -0.89,-0.8 -1.36,-1.06 -0.47,-0.26 -1.22,-0.39 -2.24,-0.39 -1,0 -1.88,0.25 -2.63,0.75 -0.75,0.5 -1.33,1.18 -1.73,2.03 -0.4,0.85 -0.62,1.8 -0.6,2.83 0.02,0.86 0.27,1.69 0.67,2.47 0.4,0.77 0.99,1.42 1.73,1.89 0.75,0.48 1.66,0.73 2.68,0.72 1.56,-0.02 2.74,-0.46 3.51,-1.26 0.77,-0.8 1.32,-2.01 1.64,-3.61l2.84 0.4c-0.02,0.75 -0.2,1.53 -0.55,2.36 -0.35,0.82 -0.87,1.62 -1.56,2.36 -0.69,0.74 -1.56,1.36 -2.58,1.81 -1.02,0.46 -2.19,0.71 -3.49,0.71 -1.36,0 -2.65,-0.35 -3.86,-1.05 -1.21,-0.7 -2.19,-1.66 -2.91,-2.85 -0.72,-1.19 -1.08,-2.48 -1.08,-3.86 0,-1.4 0.24,-2.64 0.71,-3.71 0.47,-1.06 1.11,-1.95 1.89,-2.65 0.78,-0.69 1.65,-1.21 2.58,-1.55 0.93,-0.33 1.85,-0.5 2.75,-0.5 1.77,0 3.25,0.4 4.45,1.2 1.2,0.8 2.24,2.03 3.11,3.7l-10.43 5.79 -1.23 -2.29z"/>
|
||||
<path class="fil0" d="M92.27 9.1l3.09 0 4.53 12.01 4.51 -12.01 3.03 0 -5.41 14.33c-0.17,0.45 -0.48,0.82 -0.88,1.07 -0.4,0.25 -0.84,0.38 -1.31,0.38 -0.49,0 -0.95,-0.14 -1.36,-0.43 -0.41,-0.28 -0.67,-0.7 -0.86,-1.21l-5.35 -14.14z"/>
|
||||
<polygon class="fil0" points="86.8,24.88 86.8,9.12 89.64,9.12 89.64,24.88 "/>
|
||||
<path class="fil0" d="M86.53 5.65c0.01,-0.46 0.21,-0.85 0.54,-1.17 0.33,-0.31 0.72,-0.47 1.16,-0.47 0.45,0 0.84,0.17 1.17,0.49 0.33,0.32 0.5,0.73 0.5,1.22 0,0.52 -0.16,0.94 -0.47,1.24 -0.31,0.3 -0.69,0.46 -1.14,0.46 -0.48,0 -0.89,-0.17 -1.25,-0.49 -0.35,-0.32 -0.54,-0.76 -0.53,-1.28z"/>
|
||||
<polygon class="fil0" points="80.15,2.31 82.98,2.31 82.98,24.88 80.15,24.88 "/>
|
||||
<path class="fil0" d="M63.47 24.88l0 -9.43c0,-1.14 0.29,-2.2 0.87,-3.17 0.59,-0.97 1.39,-1.75 2.42,-2.32 1.02,-0.57 2.15,-0.9 3.37,-0.92 0.87,-0.02 1.83,0.22 2.86,0.67 1.03,0.45 1.91,1.18 2.64,2.18 0.74,1 1.11,2.28 1.11,3.82l0 9.18 -2.83 0 0 -9.11c0,-1.07 -0.35,-2.01 -1.06,-2.8 -0.71,-0.79 -1.61,-1.21 -2.71,-1.23 -1.05,-0.02 -1.94,0.37 -2.67,1.11 -0.73,0.74 -1.09,1.63 -1.09,2.66l0 9.37 -2.9 0z"/>
|
||||
<path class="fil1" d="M52.44 8.9c4.41,0 7.99,3.58 7.99,7.99 0,4.41 -3.58,7.99 -7.99,7.99 -2.8,0 -5.26,-1.44 -6.69,-3.61 -1.43,2.18 -3.89,3.61 -6.69,3.61 -4.41,0 -7.99,-3.58 -7.99,-7.99 0,-4.41 3.58,-7.99 7.99,-7.99 2.8,0 5.26,1.44 6.69,3.61 1.43,-2.18 3.89,-3.61 6.69,-3.61zm0 2.77c2.89,0 5.22,2.34 5.22,5.22 0,2.89 -2.34,5.22 -5.22,5.22 -2.89,0 -5.22,-2.34 -5.22,-5.22 0,-2.89 2.34,-5.22 5.22,-5.22zm-13.37 0c2.89,0 5.22,2.34 5.22,5.22 0,2.89 -2.34,5.22 -5.22,5.22 -2.89,0 -5.22,-2.34 -5.22,-5.22 0,-2.89 2.34,-5.22 5.22,-5.22z"/>
|
||||
<g>
|
||||
<path class="fil1" d="M140.49 19.22l1.82 0c0.16,0 0.31,0.13 0.34,0.29l0.49 2.63c0.03,0.16 -0.07,0.29 -0.23,0.29l-1.82 0c-0.16,0 -0.31,-0.13 -0.34,-0.29l-0.5 -2.63c-0.03,-0.16 0.08,-0.29 0.23,-0.29z"/>
|
||||
<path class="fil1" d="M129.14 9.06l6.05 0 0 -1.3c0,-0.16 0.13,-0.29 0.29,-0.29l2.55 0c0.16,0 0.29,0.13 0.29,0.29l0 1.3 6.05 0c0.16,0 0.29,0.13 0.29,0.29l0 2.61 -2.79 0 0 -1.12 -10.22 0 0 1.12 -2.79 0 0 -2.61c0,-0.16 0.13,-0.29 0.29,-0.29z"/>
|
||||
<path class="fil1" d="M128.71 23.12l6.48 0 0 -4.68 -6.44 0 0 -1.47c0,-0.16 0.13,-0.29 0.29,-0.29l6.15 0 0 -2.16 -6.44 0 0 -1.47c0,-0.16 0.13,-0.29 0.29,-0.29l15.43 0c0.16,0 0.29,0.13 0.29,0.29l0 1.47 -6.44 0 0 2.16 6.15 0c0.16,0 0.29,0.13 0.29,0.29l0 1.47 -6.44 0 0 4.68 6.48 0c0.16,0 0.29,0.13 0.29,0.29l0 1.47 -16.66 0 0 -1.47c0,-0.16 0.13,-0.29 0.29,-0.29z"/>
|
||||
<path class="fil1" d="M148.4 9.02l5.99 0 0 -1.25c0,-0.16 0.13,-0.29 0.29,-0.29l2.55 0c0.16,0 0.29,0.13 0.29,0.29l0 1.25 5.99 0c0.16,0 0.29,0.13 0.29,0.29l0 1.61 -6.27 0 0 4.6 6.36 0c0.19,0 0.34,0.15 0.34,0.34l0 1.89 -2.49 0 2.49 7.11 -2.86 0 -2.49 -7.11 -1.35 0 0 7.03 -3.12 0 0 -7.03 -1.35 0 -2.49 7.11 -2.85 0 2.49 -7.11 -2.49 0 0 -1.89c0,-0.19 0.15,-0.34 0.34,-0.34l6.36 0 0 -4.6 -6.27 0 0 -1.61c0,-0.16 0.13,-0.29 0.29,-0.29zm13.68 2.38l-2.28 0c-0.16,0 -0.33,0.13 -0.38,0.29l-1.09 3.31c-0.05,0.16 0.04,0.29 0.19,0.29l2.28 0c0.16,0 0.33,-0.13 0.38,-0.29l1.09 -3.31c0.05,-0.16 -0.03,-0.29 -0.19,-0.29zm-12.45 0l2.28 0c0.16,0 0.33,0.13 0.38,0.29l1.09 3.31c0.05,0.16 -0.04,0.29 -0.19,0.29l-2.28 0c-0.16,0 -0.33,-0.13 -0.38,-0.29l-1.09 -3.31c-0.05,-0.16 0.03,-0.29 0.19,-0.29z"/>
|
||||
<path class="fil1" d="M170.46 12.11l6.72 0c0.16,0 0.29,0.13 0.29,0.29l0 0.84c0,0.16 -0.13,0.29 -0.29,0.29l-6.81 0 -0.72 11.34 -2.88 0 0.98 -15.56c0.01,-0.16 0.15,-0.29 0.31,-0.29l0.1 0 2.49 0 6.75 0 -0.25 -1.25c-0.03,-0.16 0.07,-0.29 0.23,-0.29l2.13 0c0.16,0 0.31,0.13 0.35,0.29l0.25 1.25 2.76 0c0.16,0 0.29,0.13 0.29,0.29l0 1.61 -2.67 0 0.45 2.22 0.24 -0.67c0.06,-0.16 0.23,-0.29 0.39,-0.29l1.61 0 -1.54 4.4 1.67 8.29 -2.41 0c-0.16,0 -0.31,-0.13 -0.35,-0.29l-0.63 -3.11 -1.09 3.11c-0.06,0.16 -0.23,0.29 -0.39,0.29l-1.61 0 2.39 -6.83 -1.44 -7.12 -7.25 0 -0.08 1.19zm10.53 -4.67l1.54 0c0.16,0 0.29,0.13 0.29,0.29l0 0.68c0,0.16 -0.13,0.29 -0.29,0.29l-1.54 0c-0.16,0 -0.29,-0.13 -0.29,-0.29l0 -0.68c0,-0.16 0.13,-0.29 0.29,-0.29z"/>
|
||||
<path class="fil1" d="M172.98 19.71l0.99 0 1.09 -2.68 -1.11 0 -0.98 2.68zm2.64 -4.05l0 -0 1.96 0 -0 0 0.01 0 -0.49 1.36 -0.02 0c-0.34,0.98 -0.55,1.65 -1.06,3.03l-1.23 -0.06 -0 0.01 2.06 4.86 -2.44 0 -0.84 -1.99 -0.84 1.99 -2.44 0 2.06 -4.86 -0.01 -0.02 -1.17 0c-0.16,0 -0.24,-0.13 -0.18,-0.29l0.97 -2.67 -0.72 0c-0.16,0 -0.29,-0.13 -0.29,-0.29l0 -0.79c0,-0.16 0.13,-0.29 0.29,-0.29l1.21 0 0.44 -1.2c0.06,-0.16 0.23,-0.29 0.39,-0.29l1.42 0c0.16,0 0.24,0.13 0.18,0.29l-0.44 1.2 1.17 0z"/>
|
||||
</g>
|
||||
<path class="fil1" d="M26.23 22.62c0.78,-1.45 1.22,-3.1 1.22,-4.86 0,-5.65 -4.58,-10.23 -10.23,-10.23 -1.78,0 -3.44,0.45 -4.9,1.25l0 4.22c1.24,-1.28 2.98,-2.07 4.9,-2.07 3.77,0 6.83,3.06 6.83,6.83 0,3.77 -3.06,6.83 -6.83,6.83 -1.88,0 -3.58,-0.76 -4.82,-1.99 -1.23,-1.21 -1.51,-3.04 -1.57,-4.86l0 -11.24 0 -5.5 0 -0.12 0 -0 0 -0.38c1.2,-0.32 2.47,-0.49 3.78,-0.49 8.07,0 14.61,6.54 14.61,14.61 0,8.07 -6.54,14.61 -14.61,14.61 -8.07,0 -14.61,-6.54 -14.61,-14.61 0,-5.37 2.9,-10.07 7.22,-12.61l0 0.42 0 0 0 0.14 0 3.93 0 10.54c0,1.68 0.06,2.52 0.42,3.8 0.81,2.9 2.79,5.1 5.51,6.31 1.25,0.54 2.62,0.84 4.07,0.84 1.09,0 2.14,-0.17 3.13,-0.49 2.38,-1.06 4.42,-2.76 5.88,-4.89z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
67
public/image/logocomplete.svg
Normal file
67
public/image/logocomplete.svg
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW 2020 (64-Bit) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="325px" height="74px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 37.78 8.6"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<font id="FontID0" horiz-adv-x="499" font-variant="normal" style="fill-rule:nonzero" font-weight="400">
|
||||
<font-face
|
||||
font-family="幼圆字体">
|
||||
<font-face-src>
|
||||
<font-face-name name="幼圆"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<missing-glyph><path d="M0 0z"/></missing-glyph>
|
||||
<glyph unicode="优" horiz-adv-x="999" d="M242.121 765.559c-5.12727,-62.4957 -23.3006,-148.463 -54.6339,-257.788l0 -617.096c-15.6667,-25.9782 -31.1624,-25.9782 -46.8291,0l0 523.267c-25.9782,-62.4957 -52.1842,-109.325 -78.1624,-140.487 -25.9782,-10.4824 -39.0242,-2.67758 -39.0242,23.3576 93.6582,140.658 151.027,296.926 171.821,468.747 15.6667,26.0351 31.1624,26.0351 46.8291,0zm265.65 0c15.6667,20.8509 31.1624,20.8509 46.8291,0l-7.86182 -187.487 382.836 0c25.9782,-15.6667 25.9782,-31.3333 0,-46.8291l-382.836 0c-25.9782,-286.444 -122.314,-507.771 -288.95,-664.039 -25.9782,0 -33.84,12.9891 -23.4715,38.9673 151.141,151.141 239.615,359.479 265.65,625.071l-226.511 0c-26.1491,15.4958 -26.1491,31.1624 0,46.8291l226.511 0 7.80485 187.487zm132.796 0c72.8642,-31.3333 140.658,-65.1733 203.154,-101.634 10.3115,-25.9782 2.50667,-39.0242 -23.4715,-39.0242 -78.1624,41.7018 -145.842,73.0351 -203.154,93.8291 -10.3115,31.1624 -2.50667,46.8291 23.4715,46.8291zm-46.8291 -281.259c15.4958,26.1491 31.1624,26.1491 46.8291,0l0 -492.104c0,-41.7018 18.1733,-59.8751 54.6909,-54.6909l101.463 0c67.8509,-10.3115 99.0133,46.8291 93.8291,171.821 15.6667,31.3333 31.1624,31.3333 46.8291,0 5.18424,-150.97 -36.5176,-223.834 -124.991,-218.65l-124.991 0c-62.4957,-5.18424 -93.6582,28.6558 -93.6582,101.52l0 492.104z"/>
|
||||
<glyph unicode="创" horiz-adv-x="999" d="M288.95 749.892c20.8509,20.8509 41.7018,20.8509 62.4957,0 83.3467,-72.8073 171.991,-161.452 265.65,-265.593 5.18424,-36.3467 -7.86182,-46.8291 -39.0242,-31.1624 -83.2897,98.9563 -161.452,179.625 -234.259,242.121 -10.5394,15.6667 -23.5285,15.6667 -39.1951,0 -72.8073,-104.141 -158.775,-190.165 -257.788,-257.788 -31.1624,0 -39.0242,12.9891 -23.3576,38.9673 98.8424,67.8509 187.487,159.002 265.479,273.455zm624.957 0l0 -796.721c0,-88.4739 -67.68,-109.325 -202.983,-62.4957 -20.8509,25.9782 -15.6667,41.6448 15.4958,46.8291 93.8291,-41.6448 140.658,-33.84 140.658,23.5285l0 788.859c15.6667,20.8509 31.3333,20.8509 46.8291,0zm-187.487 -46.8291l0 -609.234c-15.4958,-26.1491 -31.1624,-26.1491 -46.8291,0l0 609.234c15.6667,20.8509 31.3333,20.8509 46.8291,0zm-523.267 -234.316l234.316 0c57.3115,0 83.2897,-26.1491 78.1054,-78.1054l-7.80485 -179.682c-10.4824,-83.2897 -78.1624,-98.9563 -203.154,-47 -20.7939,26.2061 -15.6667,41.7018 15.6667,47 88.4739,-41.6448 135.303,-39.1382 140.658,7.86182l7.80485 156.154c5.18424,31.3333 -10.4824,46.8291 -46.943,46.8291l-202.983 0c-31.3333,0 -47,-15.4958 -47,-46.8291l0 -359.308c5.29818,-57.3115 28.6558,-83.3467 70.3006,-78.1624l249.983 0c52.1842,-10.3115 75.4848,36.5176 70.3006,140.658 15.6667,25.9782 31.3333,25.9782 46.8291,0 5.35515,-130.176 -31.1624,-192.671 -109.268,-187.487l-281.145 0c-62.4957,5.18424 -93.8291,46.8291 -93.8291,124.991l0 374.974c0,51.9564 25.9782,78.1054 78.1624,78.1054z"/>
|
||||
<glyph unicode="化" horiz-adv-x="999" d="M578.071 765.559l0 -359.251c130.176,88.4739 221.327,169.143 273.341,242.121 26.1491,10.3115 39.1382,0 39.1382,-31.3333 -78.1624,-99.0133 -182.303,-187.487 -312.479,-265.65l0 -382.779c0,-36.3467 20.8509,-52.0133 62.4957,-46.8291l195.349 0c46.8291,-10.3115 67.623,72.9782 62.4957,249.983 15.4958,20.7939 31.1624,20.7939 46.8291,0 10.3115,-202.983 -23.5285,-301.996 -101.52,-296.812l-210.959 0c-67.68,-5.18424 -101.52,20.8509 -101.52,78.1624l0 374.974c-98.9563,-57.3685 -171.935,-93.8291 -218.764,-109.325 -26.0351,0 -31.1624,15.4958 -15.6667,46.8291 83.2897,31.1624 161.452,70.3006 234.43,117.13l0 382.779c15.4958,26.0351 31.1624,26.0351 46.8291,0zm-320.284 0c15.6667,26.0351 31.1624,26.0351 46.8291,0 -20.7939,-104.141 -49.5067,-195.292 -85.7964,-273.455l0 -609.234c-15.6667,-31.3333 -31.3333,-31.3333 -47,0l0 531.071c-36.3467,-57.1406 -72.8073,-101.463 -109.325,-132.625 -25.9782,-5.35515 -36.5176,5.12727 -31.1624,31.1624 114.509,119.807 189.994,270.777 226.455,453.08z"/>
|
||||
<glyph unicode="店" horiz-adv-x="999" d="M515.576 788.916c15.6667,-26.0351 28.7127,-54.6909 39.0242,-85.8533l343.812 0c25.9782,-15.6667 25.9782,-31.3333 0,-46.8291l-687.453 0c-31.3333,0 -47,-15.6667 -47,-47l0 -265.422c5.35515,-203.154 -23.3006,-361.985 -85.7964,-476.608 -31.3333,-10.3685 -44.3224,0 -39.1951,31.3333 57.3685,109.268 83.3467,257.788 78.1624,445.275l0 281.088c0,52.1842 26.0351,78.1624 78.1624,78.1624l312.479 0c-10.4824,26.0351 -20.8509,49.5067 -31.3333,70.3576 0,20.7939 13.16,25.9782 39.1382,15.4958zm39.0242 -164.016l0 -124.935 382.779 0c25.9782,-15.6667 25.9782,-31.2194 0,-46.8291l-382.779 0 0 -156.325 218.821 0c67.623,0 98.7854,-26.0351 93.6582,-77.9915l0 -250.154c5.12727,-57.1406 -20.8509,-83.1757 -78.1624,-77.9915l-452.966 0c-52.1273,-5.18424 -78.1624,20.8509 -78.1624,77.9915l0 250.154c0,51.9564 26.0351,77.9915 78.1624,77.9915l171.821 0 0 328.088c15.6667,20.8509 31.1624,20.8509 46.8291,0zm203.154 -374.918l-406.308 0c-31.1624,0 -46.8291,-15.6667 -46.8291,-46.8291l0 -218.821c0,-36.3467 15.6667,-52.0133 46.8291,-46.8291l421.974 0c36.2897,-5.18424 51.9564,10.4824 46.8291,46.8291l0 218.821c5.12727,31.1624 -15.6667,46.8291 -62.4957,46.8291z"/>
|
||||
<glyph unicode="技" horiz-adv-x="999" d="M648.429 765.559l0 -109.325 265.479 0c26.1491,-15.6667 26.1491,-31.3333 0,-47l-265.479 0 0 -156.097 156.154 0c67.623,0 91.1515,-31.3333 70.3006,-93.8291 -36.4606,-98.8424 -101.463,-192.671 -195.292,-281.145 88.4739,-72.9782 171.821,-127.669 249.983,-164.13 25.9782,-26.0351 20.7939,-41.7018 -15.6667,-46.8291 -93.6582,41.6448 -184.81,101.634 -273.341,179.625 -119.807,-83.3467 -239.615,-140.487 -359.251,-171.821 -31.3333,10.4824 -34.0109,25.9782 -7.86182,46.8291 124.991,36.5176 234.316,88.6448 327.974,156.325 -77.9915,88.4739 -140.487,197.799 -187.487,328.145l-31.1624 0c-20.8509,15.4958 -20.8509,31.1624 0,46.8291l218.65 0 0 156.097 -249.983 0c-20.7939,15.6667 -20.7939,31.3333 0,47l249.983 0 0 109.325c15.6667,20.8509 31.3333,20.8509 47,0zm-421.974 -15.6667l0 -187.487 124.991 0c20.8509,-15.6667 20.8509,-31.1624 0,-46.8291l-124.991 0 0 -234.259c26.2061,15.4958 59.9891,36.2897 101.691,62.4957 25.9782,0 33.783,-13.16 23.3006,-39.1951 -36.3467,-25.9782 -77.9915,-51.9564 -124.991,-78.1624l0 -296.755c0,-57.3685 -57.1406,-72.8642 -171.821,-46.8291 -15.6667,25.9782 -10.3115,41.6448 15.6667,46.8291 78.1624,-20.8509 114.509,-18.1733 109.325,7.80485l0 265.65c-36.4606,-20.8509 -75.4848,-39.1951 -117.13,-54.6909 -25.9782,10.3685 -31.1624,26.0351 -15.6667,46.8291 41.6448,15.6667 85.9673,36.5176 132.796,62.4957l0 257.788 -124.991 0c-25.9782,15.6667 -25.9782,31.1624 0,46.8291l124.991 0 0 187.487c15.6667,26.0351 31.3333,26.0351 46.8291,0zm234.487 -343.584c46.8291,-119.864 106.647,-218.821 179.625,-296.983 88.5309,83.2897 151.027,171.991 187.487,265.65 5.18424,20.7939 -5.18424,31.3333 -31.3333,31.3333l-335.779 0z"/>
|
||||
<glyph unicode="新" horiz-adv-x="999" d="M62.4957 453.137l140.658 0c-15.6667,46.8291 -31.3333,85.7964 -46.8291,117.13 0,25.9782 12.9891,33.84 38.9673,23.4715 26.0351,-47 46.8291,-93.7721 62.4957,-140.601l86.0242 0c41.6448,62.4388 67.623,109.268 77.9915,140.601 20.7939,10.3685 33.783,2.50667 39.1382,-23.4715 -20.8509,-46.8291 -41.6448,-85.9673 -62.4957,-117.13l163.959 0c20.8509,-15.6667 20.8509,-31.3333 0,-46.8291l-234.259 0 0 -109.496 187.43 0c20.8509,-15.4958 20.8509,-31.1624 0,-46.8291l-187.43 0 0 -312.479c10.3115,-67.68 -52.1842,-83.3467 -187.487,-46.8291 -10.4824,25.9782 -2.67758,41.6448 23.3006,46.8291 88.7018,-31.1624 127.669,-28.6558 117.358,7.86182l0 304.617 -218.821 0c-20.8509,15.6667 -20.8509,31.3333 0,46.8291l218.821 0 0 109.496 -218.821 0c-25.9782,15.4958 -25.9782,31.1624 0,46.8291zm851.412 296.755c26.1491,-5.12727 31.3333,-20.7939 15.6667,-46.8291 -78.1624,-25.9782 -164.016,-41.6448 -257.845,-46.8291 -20.7939,0 -31.1624,-10.4824 -31.1624,-31.3333l0 -171.764 312.479 0c20.8509,-15.6667 20.8509,-31.3333 0,-46.8291l-93.8291 0 0 -531.299c-15.4958,-20.8509 -31.1624,-20.8509 -46.8291,0l0 531.299 -171.821 0 0 -132.853c5.18424,-171.991 -31.3333,-304.617 -109.325,-398.446 -31.2764,-10.3115 -44.3224,0 -39.1382,31.1624 72.9782,83.5176 106.818,210.959 101.634,382.779l0 351.617c0,41.7018 23.3576,62.4957 70.1867,62.4957 72.9782,0 156.325,15.6667 249.983,46.8291zm-624.957 -70.3006c-5.12727,36.4606 -12.9891,62.4957 -23.3006,78.1624 5.12727,31.1624 20.7939,38.9673 46.8291,23.4715 10.4824,-20.7939 20.7939,-54.8048 31.3333,-101.634l187.43 0c20.8509,-15.6667 20.8509,-31.1624 0,-46.8291l-453.08 0c-20.8509,15.6667 -20.8509,31.1624 0,46.8291l210.788 0zm-109.325 -492.104c20.8509,15.6667 36.5176,10.4824 46.8291,-15.6667 -31.1624,-72.8073 -70.1297,-145.842 -117.13,-218.65 -36.3467,-10.4824 -49.5067,0 -39.0242,31.1624 41.7018,62.4957 78.1624,130.347 109.325,203.154zm187.487 -15.6667c-5.18424,26.1491 7.86182,33.84 39.1951,23.4715 31.1624,-62.4957 59.8182,-132.796 85.7964,-210.959 -10.3115,-25.9782 -25.9782,-31.1624 -46.8291,-15.6667 -20.8509,67.8509 -46.8291,135.474 -78.1624,203.154z"/>
|
||||
<glyph unicode="理" horiz-adv-x="999" d="M468.747 749.892l359.308 0c57.3115,0 83.3467,-25.9782 78.1624,-78.1624l0 -327.918c5.18424,-57.3685 -20.8509,-83.3467 -78.1624,-78.1624l-156.325 0 0 -124.991 234.487 0c20.8509,-15.6667 20.8509,-31.3333 0,-46.8291l-234.487 0 0 -140.658 281.316 0c20.8509,-15.6667 20.8509,-31.3333 0,-47l-609.234 0c-20.8509,10.4824 -20.8509,26.1491 0,47l281.088 0 0 140.658 -218.593 0c-20.8509,10.3115 -20.8509,25.9782 0,46.8291l218.593 0 0 124.991 -156.154 0c-52.1273,-5.18424 -78.1054,23.3006 -78.1054,85.7964l0 320.284c0,52.1842 25.9782,78.1624 78.1054,78.1624zm156.154 -46.8291l-148.463 0c-25.9782,0 -38.9673,-15.6667 -38.9673,-46.8291l0 -124.991 187.43 0 0 171.821zm187.487 0l-140.658 0 0 -171.821 187.487 0 0 124.991c5.35515,31.1624 -10.3115,46.8291 -46.8291,46.8291zm-187.487 -218.764l-187.43 0 0 -132.853c0,-31.1624 15.6667,-44.1515 46.8291,-38.9673l140.601 0 0 171.821zm234.316 0l-187.487 0 0 -171.821 140.658 0c36.5176,-5.18424 52.1842,10.4824 46.8291,46.8291l0 124.991zm-804.583 249.926l296.812 0c20.8509,-15.4958 20.8509,-31.1624 0,-46.8291l-124.991 0 0 -312.422 109.496 0c20.8509,-15.6667 20.8509,-31.1624 0,-46.8291l-109.496 0 0 -320.341c47,20.8509 86.0242,41.7018 117.358,62.4957 31.1624,-5.12727 36.2897,-20.7939 15.4958,-46.8291 -109.325,-62.4388 -213.465,-106.818 -312.479,-132.796 -25.9782,10.3115 -28.6558,25.9782 -7.86182,46.8291 31.3333,5.18424 78.1624,20.8509 140.658,46.8291l0 343.812 -109.325 0c-20.7939,15.6667 -20.7939,31.1624 0,46.8291l109.325 0 0 312.422 -124.991 0c-20.7939,15.6667 -20.7939,31.3333 0,46.8291z"/>
|
||||
<glyph unicode="科" horiz-adv-x="999" d="M382.779 773.42c25.9782,-5.35515 31.1624,-20.8509 15.6667,-47 -41.6448,-10.3685 -85.9673,-18.1733 -132.796,-23.3576l0 -195.292 140.658 0c20.7939,-15.6667 20.7939,-31.3333 0,-46.8291l-124.991 0c62.4957,-83.3467 114.452,-161.452 156.154,-234.487 5.12727,-31.1624 -7.86182,-41.6448 -39.0242,-31.1624 -41.6448,72.8642 -85.9673,140.658 -132.796,203.154l0 -531.242c-15.6667,-20.8509 -31.3333,-20.8509 -46.8291,0l0 460.942c-36.5176,-83.3467 -86.0242,-164.187 -148.52,-242.178 -25.9782,-5.29818 -36.4606,5.18424 -31.3333,31.1624 88.7018,119.864 145.842,234.316 171.991,343.812l-156.325 0c-20.7939,15.4958 -20.7939,31.1624 0,46.8291l164.187 0 0 187.487 -124.991 0c-20.8509,15.6667 -20.8509,31.1624 0,46.8291 109.325,-5.18424 205.661,5.12727 288.95,31.3333zm476.438 -15.6667l0 -585.933 93.8291 15.6667c20.8509,-15.6667 20.8509,-31.1624 0,-46.8291l-93.8291 -15.6667 0 -257.788c-15.4958,-20.8509 -31.1624,-20.8509 -46.8291,0l0 249.926 -406.08 -46.8291c-20.8509,15.6667 -20.8509,31.1624 0,46.8291l406.08 46.8291 0 593.795c15.6667,25.9782 31.3333,25.9782 46.8291,0zm-304.617 -7.86182c67.68,-67.623 143.336,-150.97 226.625,-249.926 10.3685,-31.2194 0,-44.3794 -31.3333,-39.0242 -88.4739,104.141 -163.959,187.487 -226.455,249.983 -5.35515,31.1624 5.18424,44.1515 31.1624,38.9673zm-62.4957 -257.788c88.4739,-83.3467 166.636,-161.452 234.316,-234.316 10.4824,-31.3333 -2.50667,-41.6448 -39.0242,-31.3333 -83.2897,88.6448 -158.775,164.187 -226.455,226.682 -5.35515,25.9782 5.18424,38.9673 31.1624,38.9673z"/>
|
||||
<glyph unicode="管" horiz-adv-x="999" d="M187.487 788.916c31.3333,15.6667 44.3224,7.80485 38.9673,-23.3576l-15.4958 -23.4715 281.145 0c25.9782,-15.6667 25.9782,-31.1624 0,-46.8291l-179.625 0c15.6667,-36.5176 25.9782,-67.68 31.3333,-93.8291 -10.5394,-25.9782 -26.2061,-28.4848 -47,-7.69091 -5.18424,20.8509 -15.4958,54.6909 -31.1624,101.52l-78.1624 0c-26.0351,-36.5176 -54.6909,-70.3576 -86.0242,-101.52 -31.1624,-15.6667 -44.1515,-7.80485 -38.9673,23.3576 52.1842,57.3115 93.8291,114.623 124.991,171.821zm390.584 0c26.0351,15.6667 39.0242,7.80485 39.0242,-23.3576l-15.6667 -23.4715 312.479 0c26.1491,-15.6667 26.1491,-31.1624 0,-46.8291l-179.682 0c10.5394,-26.0351 20.8509,-59.8182 31.3333,-101.52 -10.4824,-26.1491 -25.9782,-28.6558 -46.8291,-7.80485 -10.4824,41.6448 -23.4715,77.9915 -39.1382,109.325l-101.52 0c-15.6667,-26.0351 -33.783,-52.1842 -54.6339,-78.1624 -26.1491,-15.6667 -39.1382,-7.86182 -39.1382,23.4715 36.4606,52.0133 67.7939,101.52 93.7721,148.349zm-187.43 -164.016c0,26.0351 12.9891,33.84 38.9673,23.5285 25.9782,-36.5176 46.8291,-67.8509 62.4957,-93.8291l367.113 0c67.8509,0 96.3357,-33.84 86.0242,-101.463 -5.18424,-36.5176 -15.6667,-73.0351 -31.3333,-109.325 -26.0351,-20.8509 -41.7018,-15.6667 -46.8291,15.4958 41.6448,98.9563 36.4606,148.463 -15.6667,148.463l-702.949 0c-31.3333,0 -47,-15.6667 -47,-46.8291l0 -109.496c-15.4958,-25.9782 -31.1624,-25.9782 -46.8291,0l0 117.301c0,57.1976 26.0351,85.8533 78.1624,85.8533l304.674 0c-10.3685,15.6667 -26.0351,39.1382 -46.8291,70.3006zm-132.853 -179.625l468.633 0c57.3115,0 83.2897,-25.9782 78.1624,-78.1624l0 -78.1624c5.12727,-57.1406 -20.8509,-83.2897 -78.1624,-77.9915l-499.966 0 0 -78.1624 523.437 0c62.4957,0 91.1515,-25.9782 86.0242,-78.1624l0 -109.268c5.12727,-57.3685 -23.5285,-83.3467 -86.0242,-78.1624l-492.104 0c-52.1273,-5.18424 -78.1624,23.4715 -78.1624,85.9673l0 413.942c0,52.1842 26.0351,78.1624 78.1624,78.1624zm460.942 -46.8291l-445.275 0c-31.3333,0 -47,-12.9891 -47,-39.1382l0 -101.52 484.47 0c36.2897,-5.12727 51.9564,7.86182 46.8291,39.0242l0 62.4957c5.12727,26.1491 -7.86182,39.1382 -39.0242,39.1382zm23.3576 -312.479l-515.633 0 0 -124.935c0,-36.5176 15.6667,-52.1842 47,-47l468.633 0c36.4606,-5.18424 52.1273,7.80485 46.8291,39.1382l0 85.7964c5.29818,31.3333 -10.3685,47 -46.8291,47z"/>
|
||||
<glyph unicode="营" horiz-adv-x="999" d="M343.812 765.559l0 -93.8291 296.755 0 0 93.8291c15.6667,20.8509 31.1624,20.8509 46.8291,0l0 -93.8291 218.821 0c20.8509,-15.4958 20.8509,-31.1624 0,-46.8291l-218.821 0 0 -78.1624c-15.6667,-20.7939 -31.1624,-20.7939 -46.8291,0l0 78.1624 -296.755 0 0 -78.1624c-15.6667,-25.9782 -31.3333,-25.9782 -47,0l0 78.1624 -218.65 0c-20.8509,15.6667 -20.8509,31.3333 0,46.8291l218.65 0 0 93.8291c15.6667,26.0351 31.3333,26.0351 47,0zm-164.187 -265.593l695.258 0c57.3115,0 83.3467,-26.0351 78.1624,-78.1624 -5.18424,-46.8291 -20.8509,-88.5309 -46.8291,-124.991 -31.3333,-15.4958 -47,-7.86182 -47,23.4715 57.3115,88.4739 57.3115,132.853 0,132.853l-687.396 0c-31.1624,0 -46.8291,-15.6667 -46.8291,-46.8291l0 -109.496c-15.6667,-20.8509 -31.1624,-20.8509 -46.8291,0l0 124.991c0,52.1273 33.84,78.1624 101.463,78.1624zm86.0242 -124.991l476.438 0c57.3115,0 83.2897,-26.0351 78.1624,-78.1624l0 -46.8291c5.12727,-57.3685 -20.8509,-83.3467 -78.1624,-78.1624l-476.438 0c-52.1842,-5.18424 -78.1624,20.7939 -78.1624,78.1624l0 46.8291c0,52.1273 25.9782,78.1624 78.1624,78.1624zm507.771 -93.6582c5.12727,31.1624 -10.5394,46.8291 -47,46.8291l-445.104 0c-31.3333,0 -47,-15.6667 -47,-46.8291l0 -15.6667c0,-36.5176 15.6667,-52.1842 47,-46.8291l445.104 0c36.4606,-5.35515 52.1273,10.3115 47,46.8291l0 15.6667zm-570.267 -171.991l585.762 0c57.3115,0 83.2897,-25.9782 78.1624,-77.9915l0 -62.6667c5.12727,-57.1406 -23.3576,-83.1757 -85.8533,-77.9915l-578.071 0c-41.7018,-5.18424 -62.4957,20.8509 -62.4957,77.9915l0 62.6667c0,52.0133 20.7939,77.9915 62.4957,77.9915zm570.267 -46.8291l-546.966 0c-25.9782,0 -38.9673,-15.6667 -38.9673,-46.8291l0 -31.3333c0,-36.3467 12.9891,-52.0133 38.9673,-46.8291l546.966 0c36.2897,-5.18424 51.9564,10.4824 46.8291,46.8291l0 31.3333c5.12727,31.1624 -10.5394,46.8291 -46.8291,46.8291z"/>
|
||||
<glyph unicode="运" horiz-adv-x="999" d="M93.8291 773.42c52.0133,-36.5176 101.463,-75.4848 148.292,-117.187 15.6667,-26.1491 7.86182,-41.6448 -23.3006,-47 -62.4957,52.1842 -112.002,91.1515 -148.52,117.187 -20.7939,26.1491 -12.9891,41.6448 23.5285,47zm257.617 -23.5285l492.275 0c20.8509,-15.6667 20.8509,-31.1624 0,-46.8291l-492.275 0c-20.7939,15.6667 -20.7939,31.1624 0,46.8291zm-54.6339 -265.593l617.096 0c20.7939,-15.5527 20.7939,-31.1624 0,-46.8291l-320.17 0c-57.3115,-156.154 -119.807,-273.511 -187.43,-351.503l421.747 23.3576c-46.8291,104.141 -83.2897,174.498 -109.325,210.959 5.18424,31.1624 18.1733,41.6448 39.0242,31.1624 72.8073,-130.119 130.119,-249.983 171.821,-359.251 -5.18424,-26.0351 -20.8509,-31.1624 -46.8291,-15.6667l-31.3333 85.9673 -484.299 -31.1624c-31.1624,0 -36.4606,20.8509 -15.6667,62.4957 93.8291,114.452 156.325,229.132 187.487,343.641l-242.121 0c-20.8509,15.6667 -20.8509,31.2764 0,46.8291zm-249.983 -31.1624l101.634 0c52.0133,0 75.4848,-28.7127 70.3576,-86.0242l0 -265.65c83.2897,-124.935 187.487,-184.81 312.422,-179.625l406.137 0c25.9782,-15.4958 25.9782,-31.1624 0,-46.8291l-398.446 0c-135.303,-5.18424 -242.121,41.6448 -320.113,140.658 -36.5176,-57.3115 -83.3467,-101.634 -140.658,-132.796 -25.9782,-5.18424 -36.5176,5.12727 -31.3333,31.1624 93.8291,67.7939 135.474,124.935 124.991,171.935l0 273.341c5.29818,31.3333 -7.86182,47 -39.0242,47l-85.9673 0c-20.8509,15.4958 -20.8509,31.1624 0,46.8291z"/>
|
||||
<glyph unicode="酒" horiz-adv-x="999" d="M109.325 742.087c-10.3115,31.3333 0,44.3224 31.3333,39.1382 51.9564,-41.6448 98.9563,-85.9673 140.658,-132.796 10.3115,-31.3333 0,-41.6448 -31.3333,-31.3333 -46.8291,46.8291 -93.6582,88.4739 -140.658,124.991zm187.487 23.4715l624.901 0c15.6667,-15.6667 15.6667,-31.3333 0,-46.8291l-187.487 0 0 -124.991 117.187 0c62.4957,0 91.1515,-26.1491 85.9673,-78.1624l0 -562.405c5.18424,-57.3115 -25.9782,-83.3467 -93.6582,-78.1624l-453.08 0c-52.1842,-5.18424 -78.1624,20.8509 -78.1624,78.1624l0 554.6c5.12727,57.3115 31.3333,85.9673 78.1624,85.9673l109.325 0 0 124.991 -203.154 0c-20.8509,15.4958 -20.8509,31.1624 0,46.8291zm390.584 -46.8291l-140.658 0 0 -124.991 140.658 0 0 124.991zm-187.43 -171.991l-93.6582 0c-31.3333,0 -47,-15.4958 -47,-46.7721l0 -390.641 531.242 0 0 117.13 -109.325 0c-62.4957,-5.12727 -93.8291,26.2061 -93.8291,93.8291l0 226.455 -140.658 0c5.35515,-150.97 -33.783,-265.422 -117.13,-343.584 -31.1624,0 -38.9673,12.9891 -23.3006,38.9673 72.8073,78.1624 104.141,179.682 93.6582,304.617zm343.755 0l-109.496 0 0 -234.259c0,-31.1624 15.6667,-44.3224 47,-39.0242l109.325 0 0 226.511c5.18424,31.2764 -10.4824,46.7721 -46.8291,46.7721zm-757.754 -46.7721c57.1976,-46.8291 106.647,-91.2085 148.349,-132.853 10.4824,-31.1624 0,-41.6448 -31.1624,-31.1624 -46.8291,41.6448 -96.3357,83.3467 -148.52,124.991 -10.3115,31.1624 0,44.1515 31.3333,39.0242zm124.991 -265.65c26.0351,26.1491 41.7018,23.4715 46.8291,-7.86182 -36.4606,-98.7854 -91.1515,-200.476 -163.959,-304.617 -31.3333,-15.4958 -44.3224,-7.80485 -39.1951,23.5285 73.0351,109.268 124.991,205.604 156.325,288.95zm679.591 -171.821l-531.242 0 0 -93.8291c0,-36.3467 15.6667,-52.0133 47,-46.8291l437.413 0c36.3467,-5.18424 52.0133,10.4824 46.8291,46.8291l0 93.8291z"/>
|
||||
</font>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
@font-face { font-family:"幼圆字体";font-variant:normal;font-weight:normal;src:url("#FontID0") format(svg)}
|
||||
.fil2 {fill:#332C2B}
|
||||
.fil1 {fill:#008C8C}
|
||||
.fil0 {fill:#008C8C;fill-rule:nonzero}
|
||||
.fnt0 {font-weight:normal;font-size:2.41px;font-family:'幼圆字体'}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="图层_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_2138846559120">
|
||||
<g>
|
||||
<path class="fil0" d="M23.23 3.53l1.59 -0.88c-0.09,-0.09 -0.19,-0.16 -0.28,-0.22 -0.1,-0.05 -0.26,-0.08 -0.46,-0.08 -0.21,0 -0.39,0.06 -0.55,0.16 -0.15,0.1 -0.27,0.24 -0.35,0.42 -0.09,0.17 -0.13,0.37 -0.13,0.58 0.01,0.18 0.06,0.35 0.14,0.51 0.08,0.16 0.2,0.29 0.36,0.39 0.15,0.1 0.34,0.15 0.55,0.15 0.32,-0.01 0.57,-0.1 0.72,-0.26 0.16,-0.17 0.28,-0.42 0.34,-0.75l0.59 0.09c-0.01,0.15 -0.04,0.31 -0.12,0.48 -0.07,0.17 -0.17,0.33 -0.32,0.49 -0.14,0.15 -0.32,0.28 -0.53,0.37 -0.21,0.1 -0.45,0.15 -0.72,0.15 -0.28,0 -0.55,-0.07 -0.8,-0.22 -0.25,-0.14 -0.45,-0.34 -0.59,-0.59 -0.15,-0.24 -0.23,-0.51 -0.23,-0.79 0,-0.29 0.05,-0.55 0.15,-0.77 0.1,-0.21 0.23,-0.4 0.39,-0.54 0.16,-0.14 0.34,-0.25 0.53,-0.32 0.19,-0.07 0.38,-0.1 0.57,-0.1 0.36,0 0.67,0.08 0.91,0.24 0.25,0.17 0.46,0.42 0.64,0.77l-2.15 1.19 -0.25 -0.47z"/>
|
||||
<path class="fil0" d="M19.02 1.88l0.63 0 0.94 2.47 0.93 -2.47 0.62 0 -1.11 2.95c-0.04,0.09 -0.1,0.17 -0.18,0.22 -0.09,0.05 -0.18,0.08 -0.28,0.08 -0.1,0 -0.19,-0.03 -0.27,-0.09 -0.09,-0.06 -0.14,-0.14 -0.18,-0.25l-1.1 -2.91z"/>
|
||||
<polygon class="fil0" points="17.89,5.13 17.89,1.88 18.47,1.88 18.47,5.13 "/>
|
||||
<path class="fil0" d="M17.83 1.16c0.01,-0.09 0.05,-0.17 0.12,-0.24 0.06,-0.06 0.14,-0.09 0.24,-0.09 0.09,0 0.17,0.03 0.24,0.1 0.07,0.06 0.1,0.15 0.1,0.25 0,0.11 -0.03,0.19 -0.1,0.25 -0.06,0.07 -0.14,0.1 -0.23,0.1 -0.1,0 -0.18,-0.03 -0.26,-0.1 -0.07,-0.07 -0.11,-0.16 -0.11,-0.27z"/>
|
||||
<polygon class="fil0" points="16.52,0.48 17.1,0.48 17.1,5.13 16.52,5.13 "/>
|
||||
<path class="fil0" d="M13.08 5.13l0 -1.95c0,-0.23 0.06,-0.45 0.18,-0.65 0.12,-0.2 0.29,-0.36 0.5,-0.48 0.21,-0.12 0.44,-0.18 0.69,-0.19 0.18,0 0.38,0.05 0.59,0.14 0.21,0.09 0.4,0.24 0.55,0.45 0.15,0.21 0.23,0.47 0.23,0.79l0 1.89 -0.59 0 0 -1.88c0,-0.22 -0.07,-0.41 -0.22,-0.58 -0.14,-0.16 -0.33,-0.25 -0.56,-0.25 -0.21,0 -0.4,0.08 -0.55,0.23 -0.15,0.15 -0.22,0.33 -0.22,0.55l0 1.93 -0.6 0z"/>
|
||||
<path class="fil1" d="M10.81 1.83c0.91,0 1.64,0.74 1.64,1.65 0,0.91 -0.73,1.65 -1.64,1.65 -0.58,0 -1.09,-0.3 -1.38,-0.75 -0.29,0.45 -0.8,0.75 -1.38,0.75 -0.91,0 -1.64,-0.74 -1.64,-1.65 0,-0.91 0.73,-1.65 1.64,-1.65 0.58,0 1.09,0.3 1.38,0.75 0.29,-0.45 0.8,-0.75 1.38,-0.75zm0 0.57c0.59,0 1.07,0.49 1.07,1.08 0,0.6 -0.48,1.08 -1.07,1.08 -0.6,0 -1.08,-0.48 -1.08,-1.08 0,-0.59 0.48,-1.08 1.08,-1.08zm-2.76 0c0.6,0 1.08,0.49 1.08,1.08 0,0.6 -0.48,1.08 -1.08,1.08 -0.59,0 -1.07,-0.48 -1.07,-1.08 0,-0.59 0.48,-1.08 1.07,-1.08z"/>
|
||||
<g>
|
||||
<path class="fil1" d="M28.96 3.96l0.37 0c0.03,0 0.07,0.03 0.07,0.06l0.1 0.54c0.01,0.03 -0.01,0.06 -0.04,0.06l-0.38 0c-0.03,0 -0.06,-0.03 -0.07,-0.06l-0.1 -0.54c-0.01,-0.03 0.01,-0.06 0.05,-0.06z"/>
|
||||
<path class="fil1" d="M26.62 1.87l1.24 0 0 -0.27c0,-0.03 0.03,-0.06 0.06,-0.06l0.53 0c0.03,0 0.06,0.03 0.06,0.06l0 0.27 1.24 0c0.04,0 0.06,0.02 0.06,0.06l0 0.54 -0.57 0 0 -0.24 -2.11 0 0 0.24 -0.57 0 0 -0.54c0,-0.04 0.02,-0.06 0.06,-0.06z"/>
|
||||
<path class="fil1" d="M26.53 4.77l1.33 0 0 -0.97 -1.32 0 0 -0.3c0,-0.04 0.02,-0.06 0.05,-0.06l1.27 0 0 -0.45 -1.32 0 0 -0.3c0,-0.03 0.02,-0.06 0.05,-0.06l3.18 0c0.04,0 0.06,0.03 0.06,0.06l0 0.3 -1.32 0 0 0.45 1.26 0c0.04,0 0.06,0.02 0.06,0.06l0 0.3 -1.32 0 0 0.97 1.33 0c0.03,0 0.06,0.02 0.06,0.05l0 0.31 -3.43 0 0 -0.31c0,-0.03 0.02,-0.05 0.06,-0.05z"/>
|
||||
<path class="fil1" d="M30.59 1.86l1.23 0 0 -0.26c0,-0.03 0.03,-0.06 0.06,-0.06l0.52 0c0.04,0 0.06,0.03 0.06,0.06l0 0.26 1.24 0c0.03,0 0.06,0.03 0.06,0.06l0 0.33 -1.3 0 0 0.95 1.31 0c0.04,0 0.07,0.03 0.07,0.07l0 0.39 -0.51 0 0.51 1.46 -0.58 0 -0.52 -1.46 -0.28 0 0 1.45 -0.64 0 0 -1.45 -0.28 0 -0.51 1.46 -0.59 0 0.51 -1.46 -0.51 0 0 -0.39c0,-0.04 0.03,-0.07 0.07,-0.07l1.31 0 0 -0.95 -1.29 0 0 -0.33c0,-0.03 0.02,-0.06 0.06,-0.06zm2.81 0.49l-0.46 0c-0.04,0 -0.07,0.03 -0.08,0.06l-0.23 0.68c-0.01,0.03 0.01,0.06 0.04,0.06l0.47 0c0.03,0 0.07,-0.03 0.08,-0.06l0.22 -0.68c0.02,-0.03 0,-0.06 -0.04,-0.06zm-2.56 0l0.47 0c0.03,0 0.07,0.03 0.08,0.06l0.22 0.68c0.01,0.03 -0.01,0.06 -0.04,0.06l-0.47 0c-0.03,0 -0.07,-0.03 -0.08,-0.06l-0.22 -0.68c-0.01,-0.03 0.01,-0.06 0.04,-0.06z"/>
|
||||
<path class="fil1" d="M35.13 2.5l1.39 0c0.03,0 0.06,0.02 0.06,0.05l0 0.18c0,0.03 -0.03,0.06 -0.06,0.06l-1.41 0 -0.14 2.33 -0.6 0 0.21 -3.2c0,-0.03 0.03,-0.06 0.06,-0.06l0.02 0 0.51 0 1.39 0 -0.05 -0.26c-0.01,-0.03 0.02,-0.06 0.05,-0.06l0.44 0c0.03,0 0.06,0.03 0.07,0.06l0.05 0.26 0.57 0c0.03,0 0.06,0.03 0.06,0.06l0 0.33 -0.55 0 0.09 0.46 0.05 -0.14c0.01,-0.03 0.05,-0.06 0.08,-0.06l0.33 0 -0.32 0.91 0.35 1.7 -0.5 0c-0.03,0 -0.06,-0.02 -0.07,-0.05l-0.13 -0.64 -0.22 0.64c-0.01,0.03 -0.05,0.05 -0.08,0.05l-0.33 0 0.49 -1.4 -0.3 -1.47 -1.49 0 -0.02 0.25zm2.17 -0.97l0.32 0c0.03,0 0.06,0.03 0.06,0.06l0 0.14c0,0.04 -0.03,0.06 -0.06,0.06l-0.32 0c-0.03,0 -0.06,-0.02 -0.06,-0.06l0 -0.14c0,-0.03 0.03,-0.06 0.06,-0.06z"/>
|
||||
<path class="fil1" d="M35.65 4.06l0.2 0 0.23 -0.55 -0.23 0 -0.2 0.55zm0.54 -0.83l0 0 0.41 0 0 0 0 0 -0.1 0.28 0 0c-0.07,0.2 -0.12,0.34 -0.22,0.62l-0.26 -0.01 0 0 0.43 1 -0.5 0 -0.18 -0.4 -0.17 0.4 -0.5 0 0.42 -1 0 0 -0.24 0c-0.03,0 -0.05,-0.03 -0.04,-0.06l0.2 -0.55 -0.15 0c-0.03,0 -0.06,-0.03 -0.06,-0.06l0 -0.16c0,-0.04 0.03,-0.06 0.06,-0.06l0.25 0 0.09 -0.25c0.01,-0.03 0.05,-0.06 0.08,-0.06l0.3 0c0.03,0 0.05,0.03 0.03,0.06l-0.09 0.25 0.24 0z"/>
|
||||
</g>
|
||||
<path class="fil1" d="M5.41 4.66c0.16,-0.3 0.25,-0.64 0.25,-1 0,-1.16 -0.95,-2.11 -2.11,-2.11 -0.37,0 -0.71,0.09 -1.01,0.26l0 0.87c0.26,-0.26 0.61,-0.43 1.01,-0.43 0.78,0 1.41,0.63 1.41,1.41 0,0.78 -0.63,1.41 -1.41,1.41 -0.39,0 -0.74,-0.16 -0.99,-0.41 -0.26,-0.25 -0.32,-0.63 -0.33,-1l0 -2.32 0 -1.13 0 -0.03 0 0 0 -0.08c0.25,-0.06 0.51,-0.1 0.78,-0.1 1.66,0 3.01,1.35 3.01,3.01 0,1.66 -1.35,3.01 -3.01,3.01 -1.66,0 -3.01,-1.35 -3.01,-3.01 0,-1.11 0.6,-2.08 1.49,-2.6l0 0.09 0 0 0 0.03 0 0.81 0 2.17c0,0.35 0.01,0.52 0.09,0.78 0.16,0.6 0.57,1.06 1.13,1.31 0.26,0.11 0.54,0.17 0.84,0.17 0.22,0 0.44,-0.04 0.64,-0.1 0.5,-0.22 0.91,-0.57 1.22,-1.01z"/>
|
||||
</g>
|
||||
<polygon class="fil0" points="1.16,7.84 1.16,7.26 4.87,7.26 4.87,7.84 "/>
|
||||
<g transform="matrix(1 0 0 1 168.774 72.7779)">
|
||||
<text x="-162.5" y="-64.56" class="fil2 fnt0">科技创新优化酒店运营管理</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 26 KiB |
11
rcu_web_vue.esproj
Normal file
11
rcu_web_vue.esproj
Normal file
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/1.0.2752196">
|
||||
<PropertyGroup>
|
||||
<StartupCommand>npm run dev</StartupCommand>
|
||||
<JavaScriptTestRoot>.\</JavaScriptTestRoot>
|
||||
<JavaScriptTestFramework>Vitest</JavaScriptTestFramework>
|
||||
<!-- Allows the build (or compile) script located on package.json to run on Build -->
|
||||
<ShouldRunBuildScript>false</ShouldRunBuildScript>
|
||||
<!-- Folder where production build objects will be placed -->
|
||||
<BuildOutputFolder>$(MSBuildProjectDirectory)\dist</BuildOutputFolder>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
1108
src/App.vue
Normal file
1108
src/App.vue
Normal file
File diff suppressed because it is too large
Load Diff
86
src/assets/base.css
Normal file
86
src/assets/base.css
Normal file
@@ -0,0 +1,86 @@
|
||||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
--color-background-mute: var(--vt-c-white-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition:
|
||||
color 0.5s,
|
||||
background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family:
|
||||
Inter,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
1
src/assets/logo.svg
Normal file
1
src/assets/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||
|
After Width: | Height: | Size: 276 B |
37
src/assets/main.css
Normal file
37
src/assets/main.css
Normal file
@@ -0,0 +1,37 @@
|
||||
@import './base.css';
|
||||
|
||||
#app {
|
||||
/*max-width: 1440px;*/
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
body {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: grid;
|
||||
/*grid-template-columns: 1fr 1fr;*/
|
||||
padding: 0 ;
|
||||
}
|
||||
}
|
||||
BIN
src/assets/sos.wav
Normal file
BIN
src/assets/sos.wav
Normal file
Binary file not shown.
42
src/axios.js
Normal file
42
src/axios.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import axios from 'axios';
|
||||
import config from '../public/config.js';
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: config.Api, // 设置基础URL
|
||||
timeout: 150000,
|
||||
});
|
||||
|
||||
// 添加请求拦截器
|
||||
instance.interceptors.request.use(config => {
|
||||
// 设置默认的 Content-Type
|
||||
if (config.headers['Content-Type'] == undefined) {
|
||||
config.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
// 如果发送的数据是对象,则使用JSON库进行序列化
|
||||
if (config.data && typeof config.data === 'object') {
|
||||
config.data = JSON.stringify(config.data);
|
||||
}
|
||||
|
||||
|
||||
return config;
|
||||
}, error => {
|
||||
// 请求错误处理
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
// 添加响应拦截器
|
||||
instance.interceptors.response.use(response => {
|
||||
// 对响应数据处理
|
||||
|
||||
return response;
|
||||
}, error => {
|
||||
// 对响应错误处理
|
||||
// 可以在这里添加例如token过期后的处理逻辑
|
||||
console.log(error)
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
export default instance;
|
||||
44
src/components/HelloWorld.vue
Normal file
44
src/components/HelloWorld.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
msg: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="greetings">
|
||||
<h1 class="green">{{ msg }}</h1>
|
||||
<h3>
|
||||
You’ve successfully created a project with
|
||||
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-size: 2.6rem;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
94
src/components/TheWelcome.vue
Normal file
94
src/components/TheWelcome.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<script setup>
|
||||
import WelcomeItem from './WelcomeItem.vue'
|
||||
import DocumentationIcon from './icons/IconDocumentation.vue'
|
||||
import ToolingIcon from './icons/IconTooling.vue'
|
||||
import EcosystemIcon from './icons/IconEcosystem.vue'
|
||||
import CommunityIcon from './icons/IconCommunity.vue'
|
||||
import SupportIcon from './icons/IconSupport.vue'
|
||||
|
||||
const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<DocumentationIcon />
|
||||
</template>
|
||||
<template #heading>Documentation</template>
|
||||
|
||||
Vue’s
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
|
||||
provides you with all information you need to get started.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<ToolingIcon />
|
||||
</template>
|
||||
<template #heading>Tooling</template>
|
||||
|
||||
This project is served and bundled with
|
||||
<a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
|
||||
recommended IDE setup is
|
||||
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
|
||||
+
|
||||
<a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener">Vue - Official</a>. If
|
||||
you need to test your components and web pages, check out
|
||||
<a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
|
||||
and
|
||||
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
|
||||
/
|
||||
<a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
|
||||
|
||||
<br />
|
||||
|
||||
More instructions are available in
|
||||
<a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
|
||||
>.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<EcosystemIcon />
|
||||
</template>
|
||||
<template #heading>Ecosystem</template>
|
||||
|
||||
Get official tools and libraries for your project:
|
||||
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
|
||||
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
|
||||
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
|
||||
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
|
||||
you need more resources, we suggest paying
|
||||
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
|
||||
a visit.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<CommunityIcon />
|
||||
</template>
|
||||
<template #heading>Community</template>
|
||||
|
||||
Got stuck? Ask your question on
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
|
||||
(our official Discord server), or
|
||||
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
|
||||
>StackOverflow</a
|
||||
>. You should also follow the official
|
||||
<a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
|
||||
Bluesky account or the
|
||||
<a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
|
||||
X account for latest news in the Vue world.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<SupportIcon />
|
||||
</template>
|
||||
<template #heading>Support Vue</template>
|
||||
|
||||
As an independent project, Vue relies on community backing for its sustainability. You can help
|
||||
us by
|
||||
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
|
||||
</WelcomeItem>
|
||||
</template>
|
||||
87
src/components/WelcomeItem.vue
Normal file
87
src/components/WelcomeItem.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="item">
|
||||
<i>
|
||||
<slot name="icon"></slot>
|
||||
</i>
|
||||
<div class="details">
|
||||
<h3>
|
||||
<slot name="heading"></slot>
|
||||
</h3>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.item {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.details {
|
||||
flex: 1;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.4rem;
|
||||
color: var(--color-heading);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.item {
|
||||
margin-top: 0;
|
||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
i {
|
||||
top: calc(50% - 25px);
|
||||
left: -26px;
|
||||
position: absolute;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-background);
|
||||
border-radius: 8px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.item:before {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:after {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:first-of-type:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item:last-of-type:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
26
src/components/i18n.js
Normal file
26
src/components/i18n.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||
import en from 'element-plus/es/locale/lang/en';
|
||||
|
||||
const messages = {
|
||||
en: {
|
||||
message: {
|
||||
hello: 'hello world'
|
||||
},
|
||||
el: en // Element Plus的英文翻译
|
||||
},
|
||||
zh: {
|
||||
message: {
|
||||
hello: '你好,世界'
|
||||
},
|
||||
el: zhCn // Element Plus的中文翻译
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = createI18n({
|
||||
locale: 'zh', // 设置默认语言
|
||||
fallbackLocale: 'en', // 设置备用语言
|
||||
messages, // 设置翻译信息
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
7
src/components/icons/IconCommunity.vue
Normal file
7
src/components/icons/IconCommunity.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
src/components/icons/IconDocumentation.vue
Normal file
7
src/components/icons/IconDocumentation.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
||||
<path
|
||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
src/components/icons/IconEcosystem.vue
Normal file
7
src/components/icons/IconEcosystem.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
src/components/icons/IconSupport.vue
Normal file
7
src/components/icons/IconSupport.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
19
src/components/icons/IconTooling.vue
Normal file
19
src/components/icons/IconTooling.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="24"
|
||||
height="24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
56
src/components/utils/authUtils.js
Normal file
56
src/components/utils/authUtils.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// authUtils.js
|
||||
|
||||
// 登录检查
|
||||
export const checkLoginStatus = (localStorage, router, fetchHotelList, getByCharWidth) => {
|
||||
const alreadyLogin = localStorage.getItem('login') == 'true'
|
||||
|
||||
if (localStorage.getItem("TokenT")) {
|
||||
// 这里需要访问 calculateTimeDiff 函数,但为了避免循环依赖,我们暂时注释掉这部分逻辑
|
||||
// if (calculateTimeDiff(localStorage.getItem("TokenT")) > 666666) { // 7天内不获取酒店列表
|
||||
// localStorage.setItem("TokenT", new Date())
|
||||
// $http.post('LeiDa/Login', {
|
||||
// username: localStorage.getItem('username'),
|
||||
// password: localStorage.getItem('password'),
|
||||
// })
|
||||
// .then(rs => {
|
||||
// console.log(JSON.parse(rs.data.response).response)
|
||||
// localStorage.setItem("AccessibleHotels", JSON.stringify(JSON.parse(rs.data.response).response))
|
||||
// })
|
||||
// }
|
||||
} else {
|
||||
console.log("TokenT不存在")
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
if (localStorage.getItem('login') == 'true') {
|
||||
// 获取酒店列表的逻辑需要在组件中处理,因为涉及响应式数据
|
||||
// fetchHotelList() // 获取酒店列表
|
||||
|
||||
// userAvatar 和 userName 的处理也需要在组件中进行
|
||||
// userAvatar.value = getByCharWidth(localStorage.getItem('username'))
|
||||
// userName.value = localStorage.getItem('username')
|
||||
|
||||
// 权限处理逻辑
|
||||
/*const permissionString = "/全选"
|
||||
//const permissionString = localStorage.getItem('permission') || '[]'
|
||||
if (permissionString == "/全选") {
|
||||
permissions.value = ["全选"]
|
||||
} else if (permissionString) {
|
||||
permissions.value = permissionString.split('/').filter(s => s).map(s => `${s}`);
|
||||
} else {
|
||||
permissions.value = []
|
||||
}*/
|
||||
}
|
||||
|
||||
return alreadyLogin;
|
||||
}
|
||||
|
||||
// 权限检查方法
|
||||
export const hasPermission = (label, permissions) => {
|
||||
return permissions.includes('全选') || permissions.includes(label)
|
||||
}
|
||||
|
||||
// 获取用户头像
|
||||
export const getUserAvatar = (username, getByCharWidth) => {
|
||||
return getByCharWidth(username);
|
||||
}
|
||||
76
src/components/utils/hotelUtils.js
Normal file
76
src/components/utils/hotelUtils.js
Normal file
@@ -0,0 +1,76 @@
|
||||
// hotelUtils.js
|
||||
|
||||
// 获取酒店列表
|
||||
export const fetchHotelList = async () => {
|
||||
if (!localStorage.getItem('AccessibleHotels')) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const hotelList = JSON.parse(localStorage.getItem('AccessibleHotels')).sort((a, b) => a.Code - b.Code)
|
||||
if (!localStorage.getItem('currentHotelCode')) {
|
||||
localStorage.setItem('currentHotelCode', hotelList[0].Code)
|
||||
}
|
||||
if (!localStorage.getItem('currentHotelName')) {
|
||||
localStorage.setItem('currentHotelName', hotelList[0].Name)
|
||||
}
|
||||
if (!localStorage.getItem('currentHotelCreateDate')) {
|
||||
localStorage.setItem('currentHotelCreateDate', hotelList[0].CreateDate)
|
||||
}
|
||||
// 设置当前酒店
|
||||
const currentHotelCode = localStorage.getItem('currentHotelCode')
|
||||
return { hotelList, currentHotelCode }
|
||||
} catch (error) {
|
||||
console.error('获取酒店列表失败', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 切换酒店
|
||||
export const switchHotel = (hotel, hotelList, currentHotelCode, ElMessage) => {
|
||||
if (hotelList.length === 1) return
|
||||
if (hotel.Code === currentHotelCode) {
|
||||
ElMessage.warning('当前已是目标酒店')
|
||||
return
|
||||
}
|
||||
//console.log('切换到酒店:', hotel)
|
||||
localStorage.setItem('currentHotelCode', hotel.Code)
|
||||
localStorage.setItem('currentHotelName', hotel.Name)
|
||||
localStorage.setItem('currentHotelCreateDate', hotel.CreateDate)
|
||||
localStorage.setItem('strictMode', JSON.stringify(false));
|
||||
localStorage.setItem('showSOS1', JSON.stringify(false));
|
||||
localStorage.setItem('showOnline', JSON.stringify(false));
|
||||
|
||||
ElMessage.success(`已切换到酒店: ${hotel.Name}`)
|
||||
// 刷新页面
|
||||
setTimeout(() => {
|
||||
location.reload()
|
||||
}, 6)
|
||||
}
|
||||
|
||||
// 计算当前酒店信息
|
||||
export const getCurrentHotelInfo = (hotelList, currentHotelCode) => {
|
||||
const hotel = hotelList.find(h => h.Code === currentHotelCode);
|
||||
return hotel ? `${hotel.Code} | ${hotel.Name}` : "未选择酒店";
|
||||
}
|
||||
|
||||
// 截断过长的酒店信息
|
||||
export const truncateHotelInfo = (hotelInfo) => {
|
||||
const maxLength = 25;
|
||||
if (hotelInfo.length <= maxLength) {
|
||||
return hotelInfo;
|
||||
}
|
||||
return hotelInfo.substring(0, maxLength - 3) + "...";
|
||||
}
|
||||
|
||||
// 计算时间差
|
||||
export const calculateTimeDiff = (targetTimeStr) => {
|
||||
const targetDate = new Date(targetTimeStr);
|
||||
|
||||
// 检查日期是否有效
|
||||
if (isNaN(targetDate.getTime())) {
|
||||
throw new Error("无效的时间格式");
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
return Math.floor((now - targetDate) / 1000);
|
||||
}
|
||||
37
src/components/utils/mqttUtils.js
Normal file
37
src/components/utils/mqttUtils.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// mqttUtils.js
|
||||
import mqtt from 'mqtt'
|
||||
|
||||
// 初始化MQTT连接
|
||||
export const initMqttClient = (localStorage) => {
|
||||
const client = mqtt.connect("ws://gua.blv-oa.com:8083/mqtt", {
|
||||
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
|
||||
username: "blwsos",
|
||||
password: "96y9Tb9*",
|
||||
protocolVersion: 5
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
// MQTT连接成功回调
|
||||
export const onMqttConnect = (client, localStorage, mqttlink) => {
|
||||
console.log("mqtt链接成功" + localStorage.getItem("currentHotelCode"))
|
||||
mqttlink(localStorage.getItem("currentHotelCode"), 0)
|
||||
}
|
||||
|
||||
// MQTT消息接收回调
|
||||
export const onMqttMessage = (topic, message, mqttmsg) => {
|
||||
mqttmsg.value = message;
|
||||
}
|
||||
|
||||
// MQTT链接管理
|
||||
export const mqttlink = (linkNew, linkOld, client) => {
|
||||
if (linkNew == linkOld) {
|
||||
return
|
||||
}
|
||||
if (linkOld != 1) {
|
||||
client.unsubscribe("blw/sos/report/" + linkOld, (err) => { });
|
||||
}
|
||||
client.unsubscribe("blw/sos/report/" + linkNew, (err) => { });
|
||||
client.subscribe("blw/sos/report/" + linkNew, (err) => { });
|
||||
}
|
||||
60
src/components/utils/searchUtils.js
Normal file
60
src/components/utils/searchUtils.js
Normal file
@@ -0,0 +1,60 @@
|
||||
// searchUtils.js
|
||||
|
||||
// 初始化搜索历史
|
||||
export const initSearchHistory = () => {
|
||||
const savedHistory = localStorage.getItem('hotelSearchHistory');
|
||||
if (savedHistory) {
|
||||
try {
|
||||
return JSON.parse(savedHistory);
|
||||
} catch (e) {
|
||||
console.error('Error parsing search history:', e);
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// 添加搜索记录到历史
|
||||
export const addToHistory = (query, searchHistory) => {
|
||||
if (!query) return searchHistory;
|
||||
|
||||
// 创建新的历史记录数组
|
||||
let newHistory = [...searchHistory];
|
||||
|
||||
// 移除重复项
|
||||
const index = newHistory.indexOf(query);
|
||||
if (index !== -1) {
|
||||
newHistory.splice(index, 1);
|
||||
}
|
||||
|
||||
// 添加到历史记录开头
|
||||
newHistory.unshift(query);
|
||||
|
||||
// 限制最多10条记录
|
||||
if (newHistory.length > 10) {
|
||||
newHistory.pop();
|
||||
}
|
||||
|
||||
// 保存到localStorage
|
||||
localStorage.setItem('hotelSearchHistory', JSON.stringify(newHistory));
|
||||
|
||||
return newHistory;
|
||||
};
|
||||
|
||||
// 删除历史记录项
|
||||
export const removeHistoryItem = (index, searchHistory) => {
|
||||
// 从数组中移除指定项
|
||||
const newHistory = [...searchHistory];
|
||||
newHistory.splice(index, 1);
|
||||
|
||||
// 更新localStorage
|
||||
localStorage.setItem('hotelSearchHistory', JSON.stringify(newHistory));
|
||||
|
||||
return newHistory;
|
||||
};
|
||||
|
||||
// 清空全部历史记录
|
||||
export const clearAllHistory = () => {
|
||||
localStorage.removeItem('hotelSearchHistory');
|
||||
};
|
||||
65
src/components/utils/themeUtils.js
Normal file
65
src/components/utils/themeUtils.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// themeUtils.js
|
||||
import { useDark, useToggle } from '@vueuse/core'
|
||||
|
||||
// 初始化主题
|
||||
export const initTheme = () => {
|
||||
const isDark = useDark()
|
||||
const toggleDark = useToggle(isDark)
|
||||
return { isDark, toggleDark }
|
||||
}
|
||||
|
||||
// 控制深色模式
|
||||
export const webToDark = (dark, toggleDark) => {
|
||||
// 获取 <html> 元素的类名
|
||||
let ishtmldark = null;
|
||||
if (document.documentElement.className.indexOf('dark') !== -1) {
|
||||
ishtmldark = false
|
||||
} else {
|
||||
ishtmldark = true
|
||||
}
|
||||
if (dark) {
|
||||
document.documentElement.setAttribute('theme-mode', 'dark')
|
||||
if (ishtmldark) {
|
||||
toggleDark()
|
||||
}
|
||||
} else {
|
||||
document.documentElement.removeAttribute('theme-mode')
|
||||
if (!ishtmldark) {
|
||||
toggleDark()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 切换主题
|
||||
export const toggleTheme = (isDarkMode, toggleDark) => {
|
||||
isDarkMode.value = !isDarkMode.value
|
||||
let root = document.documentElement;
|
||||
toggleDark()
|
||||
if (!isDarkMode.value) {
|
||||
// 如果当前是暗色主题,切换到亮色主题
|
||||
root.style.setProperty('--color-background', '#ffffff');
|
||||
root.style.setProperty('--color-background-soft', '#f8f8f8');
|
||||
root.style.setProperty('--color-background-mute', '#f2f2f2');
|
||||
root.style.setProperty('--color-border', 'rgba(60, 60, 60, 0.12)');
|
||||
root.style.setProperty('--color-border-hover', 'rgba(60, 60, 60, 0.29)');
|
||||
root.style.setProperty('--color-heading', '#2c3e50');
|
||||
root.style.setProperty('--color-text', '#2c3e50');
|
||||
root.setAttribute('data-theme', 'light');
|
||||
setTimeout(() => {
|
||||
root.removeAttribute('theme-mode');
|
||||
}, 20);
|
||||
} else {
|
||||
// 如果当前是亮色主题,切换到暗色主题
|
||||
root.style.setProperty('--color-background', '#242424');
|
||||
root.style.setProperty('--color-background-soft', '#222222');
|
||||
root.style.setProperty('--color-background-mute', '#282828');
|
||||
root.style.setProperty('--color-border', 'rgba(84, 84, 84, 0.48)');
|
||||
root.style.setProperty('--color-border-hover', 'rgba(84, 84, 84, 0.65)');
|
||||
root.style.setProperty('--color-heading', '#ffffff');
|
||||
root.style.setProperty('--color-text', 'rgba(235, 235, 235, 0.64)');
|
||||
root.setAttribute('data-theme', 'dark');
|
||||
setTimeout(() => {
|
||||
root.setAttribute('theme-mode', 'dark');
|
||||
}, 20);
|
||||
}
|
||||
}
|
||||
43
src/components/utils/timeUtils.js
Normal file
43
src/components/utils/timeUtils.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// timeUtils.js
|
||||
|
||||
// 每秒更新时间
|
||||
export const updateTime = (formattedTime) => {
|
||||
const now = new Date();
|
||||
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
formattedTime.value = `${month}/${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
// 获取指定宽度的字符
|
||||
export const getByCharWidth = (str, maxWidth = 2) => {
|
||||
// 非空判断
|
||||
if (typeof str !== 'string' || !str) return ''
|
||||
|
||||
let width = 0;
|
||||
let result = '';
|
||||
|
||||
for (const char of str) {
|
||||
// 先转换字符为大写
|
||||
const upperChar = char.toUpperCase();
|
||||
// 判断字符宽度(基于原始字符)
|
||||
const isWideChar = /[\u4E00-\u9FA5\u3000-\u303F\uFF00-\uFFEF]/.test(char);
|
||||
const charWidth = isWideChar ? 2 : 1;
|
||||
|
||||
// 超出宽度限制则停止
|
||||
if (width + charWidth > maxWidth) break;
|
||||
|
||||
// 拼接处理后的字符
|
||||
result += upperChar;
|
||||
width += charWidth;
|
||||
|
||||
// 达到最大宽度则停止
|
||||
if (width >= maxWidth) break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
29
src/main.js
Normal file
29
src/main.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import config from '../public/config.js';
|
||||
import axios from './axios'
|
||||
import i18n from './components/i18n.js' // 导入i18n
|
||||
import './assets/main.css'
|
||||
import ElementPlus from 'element-plus'
|
||||
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||
import 'element-plus/dist/index.css'
|
||||
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
|
||||
|
||||
const app = createApp(App)
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
// axios挂载到全局属性
|
||||
app.config.globalProperties.$http = axios
|
||||
|
||||
// 提供依赖注入
|
||||
app.provide('config', config)
|
||||
app.provide('$http', axios)
|
||||
|
||||
app.use(router)
|
||||
app.use(ElementPlus, { locale: zhCn })
|
||||
app.use(i18n)
|
||||
app.mount('#app')
|
||||
110
src/pages/404/index.vue
Normal file
110
src/pages/404/index.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="interactive-container">
|
||||
<div class="error-card">
|
||||
<div class="liquid"></div>
|
||||
<div class="content">
|
||||
<h1>404</h1>
|
||||
<p>错误(404):当前页面未找到</p>
|
||||
<p>SYSTEM ERROR: PAGE NOT FOUND</p>
|
||||
<el-button type="success" plain round
|
||||
class="magnetic-btn" :icon="HomeFilled"
|
||||
@mouseenter="playHoverSound"
|
||||
@click="goHome">
|
||||
返回主页
|
||||
<span class="hover-effect"></span>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
import { HomeFilled } from '@element-plus/icons-vue'
|
||||
const router = useRouter();
|
||||
|
||||
const goHome = () => {
|
||||
router.push('home');
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.interactive-container {
|
||||
height: 80%;
|
||||
width: 90%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.error-card {
|
||||
position: relative;
|
||||
width: 400px;
|
||||
height: 500px;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 25px 45px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.liquid {
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
animation: rotate 10s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
position: absolute;
|
||||
inset: 2px;
|
||||
border-radius: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 8rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1rem 0 3rem;
|
||||
}
|
||||
|
||||
.magnetic-btn {
|
||||
position: relative;
|
||||
padding: 1rem 2rem;
|
||||
border: 2px solid rgba(255,255,255,0.5);
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.magnetic-btn:hover {
|
||||
}
|
||||
|
||||
.hover-effect {
|
||||
position: absolute;
|
||||
background: radial-gradient(circle at center, rgba(255,255,255,0.4) 0%, transparent 70%);
|
||||
transform: scale(0);
|
||||
transition: transform 0.3s ease;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.magnetic-btn:hover .hover-effect {
|
||||
transform: scale(2);
|
||||
}
|
||||
</style>
|
||||
498
src/pages/dicmanage/index.vue
Normal file
498
src/pages/dicmanage/index.vue
Normal file
@@ -0,0 +1,498 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div>字典名称</div>
|
||||
<el-select v-model="currentVarName"
|
||||
placeholder="请选择字典项"
|
||||
@change="handleDictChange">
|
||||
<el-option v-for="item in dictList"
|
||||
:key="item.varName"
|
||||
:label="item.varName"
|
||||
:value="item.varName" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div>字典修改</div>
|
||||
|
||||
<!-- 区域字典特殊表格 -->
|
||||
<el-table v-if="isRegionDict"
|
||||
:data="regionData"
|
||||
stripe
|
||||
style="width: 777px">
|
||||
<el-table-column prop="key" label="大区名称">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.key"
|
||||
placeholder="请输入大区名称" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="value" label="包含省份(点击修改省份/地区)" width="521">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" @click="showProvinceDialog(row)"
|
||||
link style="width: 100%; padding: 0; height: auto; min-height: 32px; white-space: normal; word-break: break-all; line-height: 1.5; display: inline-flex; align-items: center;">
|
||||
<span style="text-align: left;">
|
||||
{{ row.value.join(',') || '点击选择省份' }}
|
||||
</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
||||
<el-table-column label="操作" width="63">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
@click="deleteRegion($index)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 普通字典表格 -->
|
||||
<el-table v-else
|
||||
:data="currentValues"
|
||||
stripe
|
||||
style="width: 777px">
|
||||
<el-table-column prop="value" label="字典值">
|
||||
<template #default="{ $index }">
|
||||
<el-input v-model="currentValues[$index]" placeholder="请输入" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="63">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
@click="handleDelete($index)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
<div class="footer">
|
||||
<template v-if="isRegionDict">
|
||||
<el-button type="primary"
|
||||
:icon="Plus"
|
||||
plain
|
||||
round
|
||||
@click="addNewRegion">
|
||||
添加大区
|
||||
</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button type="primary"
|
||||
:icon="Plus"
|
||||
plain
|
||||
round
|
||||
@click="handleAdd">
|
||||
添加值
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<el-button type="success"
|
||||
:icon="FolderChecked"
|
||||
@click="handleSave">
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 省份选择对话框 -->
|
||||
<el-dialog v-model="provinceDialogVisible"
|
||||
title="选择省份/地区"
|
||||
width="50%">
|
||||
<el-checkbox-group v-model="selectedProvinces">
|
||||
<el-row :gutter="20">
|
||||
<el-col v-for="province in allProvinces"
|
||||
:key="province"
|
||||
:span="8"
|
||||
style="margin-bottom: 15px;">
|
||||
<el-checkbox :label="province"
|
||||
:value="province" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-checkbox-group>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="provinceDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmProvinceSelection">
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, inject, computed } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Plus, Delete, Edit, UploadFilled, RefreshLeft, Upload, EditPen, FolderChecked } from '@element-plus/icons-vue';
|
||||
|
||||
const $http = inject('$http')
|
||||
const config = inject('config');
|
||||
|
||||
// 初始字典数据
|
||||
const dictList = reactive([]);
|
||||
// 新增响应式数据
|
||||
const provinceDialogVisible = ref(false);
|
||||
const selectedProvinces = ref([]);
|
||||
const currentEditingRegion = ref(null);
|
||||
const allProvinces = computed(() => {
|
||||
const provinceDict = dictList.find(d => d.varName == '省份地区');
|
||||
return provinceDict?.varValue || [];
|
||||
});
|
||||
// 获取字典
|
||||
const getDic = async () => {
|
||||
try {
|
||||
const response = await $http.post('ConfigPY/GetConfigString');
|
||||
const serverData = response.data.response || [];
|
||||
|
||||
//console.log(response);
|
||||
// 清空原有数据
|
||||
dictList.length = 0;
|
||||
|
||||
// 转换数据格式
|
||||
serverData.forEach(item => {
|
||||
dictList.push({
|
||||
varName: item.varName,
|
||||
varValue: tryParseJson(item.varValue) || []
|
||||
});
|
||||
});
|
||||
//console.log(dictList);
|
||||
// 默认选中第一个(如果存在)
|
||||
if (dictList.length > 0) {
|
||||
currentVarName.value = dictList[0].varName;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取字典失败:', error);
|
||||
ElMessage.error('字典数据加载失败');
|
||||
}
|
||||
};
|
||||
|
||||
// JSON安全解析方法
|
||||
const tryParseJson = (str) => {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const currentVarName = ref('');
|
||||
const currentDict = computed(() =>
|
||||
dictList.find(item => item.varName === currentVarName.value)
|
||||
);
|
||||
const currentValues = computed({
|
||||
get: () => currentDict.value?.varValue || [],
|
||||
set: (val) => {
|
||||
if (currentDict.value) {
|
||||
currentDict.value.varValue = val;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 处理字典项变化
|
||||
const handleDictChange = (val) => {
|
||||
if (!val) return;
|
||||
};
|
||||
// 判断是否是区域字典
|
||||
const isRegionDict = computed(() => currentVarName.value === '区域');
|
||||
|
||||
// 修改区域数据计算属性(移除setter)
|
||||
const regionData = computed(() => {
|
||||
if (!isRegionDict.value) return [];
|
||||
const regionDict = dictList.find(d => d.varName === '区域');
|
||||
return Object.entries(regionDict?.varValue || {}).map(([key, value]) => ({
|
||||
key,
|
||||
value: Array.isArray(value) ? value : [value]
|
||||
}));
|
||||
});
|
||||
|
||||
// 显示省份选择对话框
|
||||
const showProvinceDialog = (row) => {
|
||||
currentEditingRegion.value = row;
|
||||
selectedProvinces.value = [...row.value];
|
||||
provinceDialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 修改省份选择确认方法
|
||||
const confirmProvinceSelection = async () => {
|
||||
try {
|
||||
if (!currentEditingRegion.value) return;
|
||||
|
||||
// 获取当前编辑的大区信息
|
||||
const currentKey = currentEditingRegion.value.key;
|
||||
const selectedProvincesList = selectedProvinces.value;
|
||||
|
||||
// 获取区域字典数据
|
||||
const regionDict = dictList.find(d => d.varName === '区域');
|
||||
if (!regionDict) return;
|
||||
|
||||
// 收集所有其他大区的省份映射
|
||||
const provinceMap = new Map();
|
||||
Object.entries(regionDict.varValue).forEach(([region, provinces]) => {
|
||||
if (region !== currentKey) {
|
||||
provinces.forEach(province => {
|
||||
provinceMap.set(province, region);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 检查重复省份
|
||||
const duplicates = [];
|
||||
selectedProvincesList.forEach(province => {
|
||||
if (provinceMap.has(province)) {
|
||||
duplicates.push({
|
||||
province,
|
||||
region: provinceMap.get(province)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 如果有重复则提示
|
||||
if (duplicates.length > 0) {
|
||||
const confirmMessage = `
|
||||
以下省份已在其他大区存在:<br>
|
||||
${duplicates.map(d => `${d.province} → ${d.region}`).join('<br>')}<br>
|
||||
是否确认继续保存?
|
||||
`;
|
||||
|
||||
await ElMessageBox.confirm(confirmMessage, '重复省份警告', {
|
||||
confirmButtonText: '强制保存',
|
||||
cancelButtonText: '返回修改',
|
||||
type: 'warning',
|
||||
dangerouslyUseHTMLString: true
|
||||
});
|
||||
}
|
||||
|
||||
// 执行保存操作
|
||||
regionDict.varValue = {
|
||||
...regionDict.varValue,
|
||||
[currentKey]: selectedProvincesList
|
||||
};
|
||||
provinceDialogVisible.value = false;
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error(error);
|
||||
}
|
||||
return; // 用户取消则中断流程
|
||||
}
|
||||
};
|
||||
/* const confirmProvinceSelection = () => {
|
||||
if (currentEditingRegion.value) {
|
||||
const regionDict = dictList.find(d => d.varName === '区域');
|
||||
if (regionDict) {
|
||||
regionDict.varValue = {
|
||||
...regionDict.varValue,
|
||||
[currentEditingRegion.value.key]: selectedProvinces.value
|
||||
};
|
||||
}
|
||||
}
|
||||
provinceDialogVisible.value = false;
|
||||
};*/
|
||||
|
||||
// 修改添加大区方法
|
||||
const addNewRegion = () => {
|
||||
const regionDict = dictList.find(d => d.varName === '区域');
|
||||
if (!regionDict) return;
|
||||
|
||||
// 生成唯一键名
|
||||
let newKey = "新增大区";
|
||||
let counter = 1;
|
||||
while (regionDict.varValue[newKey]) {
|
||||
newKey = `新增大区${counter++}`;
|
||||
}
|
||||
|
||||
// 直接修改原始数据
|
||||
regionDict.varValue = {
|
||||
...regionDict.varValue,
|
||||
[newKey]: []
|
||||
};
|
||||
};
|
||||
|
||||
// 修改删除大区方法
|
||||
const deleteRegion = (index) => {
|
||||
ElMessageBox.confirm('确定要删除该大区吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const regionDict = dictList.find(d => d.varName === '区域');
|
||||
if (!regionDict) return;
|
||||
|
||||
const keyToDelete = regionData.value[index].key;
|
||||
const newValue = { ...regionDict.varValue };
|
||||
delete newValue[keyToDelete];
|
||||
regionDict.varValue = newValue;
|
||||
});
|
||||
};
|
||||
|
||||
// 添加行
|
||||
const handleAdd = () => {
|
||||
if (!currentDict.value) return;
|
||||
currentDict.value.varValue.push('');
|
||||
};
|
||||
|
||||
// 删除行
|
||||
const handleDelete = (index) => {
|
||||
ElMessageBox.confirm('确定要删除该行吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
currentDict.value.varValue.splice(index, 1);
|
||||
});
|
||||
};
|
||||
|
||||
// 保存字典
|
||||
const saveDic = async (name, value) => {
|
||||
try {
|
||||
let filteredValue;
|
||||
|
||||
// 根据数据类型处理
|
||||
if (Array.isArray(value)) {
|
||||
// 处理普通数组格式
|
||||
filteredValue = value
|
||||
.map(item => String(item).trim())
|
||||
.filter(item => item !== "");
|
||||
|
||||
if (filteredValue.length === 0) {
|
||||
throw new Error("不能保存空字典项");
|
||||
}
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
// 处理区域字典的对象格式
|
||||
filteredValue = Object.entries(value).reduce((acc, [key, values]) => {
|
||||
const filtered = values
|
||||
.map(item => String(item).trim())
|
||||
.filter(item => item !== "");
|
||||
|
||||
// 保留key即使值为空数组(如"其他")
|
||||
if (key === '其他' || filtered.length > 0) {
|
||||
acc[key] = filtered;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// 检查是否为空对象
|
||||
if (Object.keys(filteredValue).length === 0) {
|
||||
throw new Error("至少需要保留一个有效区域");
|
||||
}
|
||||
} else {
|
||||
throw new Error("无效的字典格式");
|
||||
}
|
||||
|
||||
const valueJs = JSON.stringify(filteredValue);
|
||||
const rs = await $http.post('ConfigPY/SaveOrAddConfigString', {
|
||||
VarName: name,
|
||||
VarValue: valueJs
|
||||
});
|
||||
|
||||
return filteredValue;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 保存处理
|
||||
const handleSave = async () => {
|
||||
if (!currentDict.value) {
|
||||
ElMessage.warning('请先选择要修改的字典项');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'此操作将永久修改字典数据,是否继续?',
|
||||
'警告',
|
||||
{
|
||||
confirmButtonText: '确认保存',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
center: true,
|
||||
dangerouslyUseHTMLString: true,
|
||||
beforeClose: (action, instance, done) => {
|
||||
if (action === 'confirm') {
|
||||
instance.confirmButtonLoading = true;
|
||||
saveDic(currentDict.value.varName, currentDict.value.varValue)
|
||||
.then(() => {
|
||||
done();
|
||||
ElMessage.success('保存成功');
|
||||
})
|
||||
.catch(() => {
|
||||
instance.confirmButtonLoading = false;
|
||||
ElMessage.error('保存失败');
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
// 处理区域字典的特殊结构
|
||||
let saveData = currentDict.value.varValue;
|
||||
|
||||
if (isRegionDict.value) {
|
||||
// 转换回原始对象格式
|
||||
saveData = regionData.value.reduce((acc, cur) => {
|
||||
acc[cur.key] = cur.value;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
// 保存并获取处理后的数据
|
||||
const filteredData = await saveDic(
|
||||
currentDict.value.varName,
|
||||
saveData
|
||||
);
|
||||
|
||||
// 更新前端数据
|
||||
currentDict.value.varValue = isRegionDict.value
|
||||
? { ...filteredData } // 对象格式
|
||||
: [...filteredData]; // 数组格式
|
||||
|
||||
} catch (error) {
|
||||
if (error === 'cancel') {
|
||||
//console.log('用户取消保存');
|
||||
} else if (error.message === '不能保存空字典项') {
|
||||
ElMessage.warning('字典项至少需要包含一个有效值');
|
||||
} else {
|
||||
ElMessage.error('保存失败: ' + error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDic()
|
||||
// 初始化选择第一个
|
||||
if (dictList.length > 0) {
|
||||
currentVarName.value = dictList[0].varName;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 333px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 777px;
|
||||
display: flex;
|
||||
justify-content: space-between; /* 推荐方案 */
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.el-message-box {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
872
src/pages/home/index.vue
Normal file
872
src/pages/home/index.vue
Normal file
@@ -0,0 +1,872 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 顶部标题行 -->
|
||||
<div class="header-container">
|
||||
<!-- 标题 -->
|
||||
<h2 class="header">{{ hotelName || '房间列表' }} <span v-if="username == 'admin'" style="font-size:12px"> 上次推送:{{ lastMQTTtime || '暂无' }} | 上次更新:<span :style="getTimeStyle(lastHTTPtime)" :class="{ timeUpdate: timeUpdateFlag }">{{ lastHTTPtime || '暂无' }}</span></span></h2>
|
||||
|
||||
<!-- 原有统计标签组 -->
|
||||
<div class="stats-group">
|
||||
<el-tag type="info" effect="dark">总房间: {{ totalRoomCount }}</el-tag>
|
||||
<el-tag type="success" effect="dark">在线: {{ onlineRoomCount }}</el-tag>
|
||||
<el-tag type="danger" effect="dark">SOS: {{ sosRoomCount }}</el-tag>
|
||||
|
||||
|
||||
<!-- 添加音频权限按钮 -->
|
||||
|
||||
<el-button v-if="permissionGranted"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="showPermissionDialog = true">
|
||||
<el-icon><Bell /></el-icon> 音频开
|
||||
</el-button>
|
||||
<el-button v-if="!permissionGranted"
|
||||
type="info"
|
||||
size="small"
|
||||
@click="showPermissionDialog = true">
|
||||
<el-icon><MuteNotification /></el-icon> 音频关
|
||||
</el-button>
|
||||
|
||||
<!-- 新增严格模式开关 -->
|
||||
<div>
|
||||
<el-checkbox v-model="strictMode">仅播放在线房间警报</el-checkbox>
|
||||
<el-checkbox v-model="showSOS1">仅显示SOS状态房间</el-checkbox>
|
||||
<el-checkbox v-model="showOnline">仅显示在线房间</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主机盒子容器 -->
|
||||
<div class="room-container">
|
||||
<div v-for="(host, index) in sortedRooms" :key="index" class="room-box">
|
||||
<!-- 第一行:房间号 -->
|
||||
<div class="room-number">
|
||||
{{ host.roomno || "-"}}
|
||||
</div>
|
||||
<div class="hotel-code">
|
||||
<div v-if="host.status">
|
||||
<el-tag type="success">在线</el-tag>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-tag type="danger">离线</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- sos操作 -->
|
||||
<div class="actions">
|
||||
<el-tag type="danger" effect="dark" v-if="host.sos_status == 1">SOS</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 音频权限申请对话框 -->
|
||||
<el-dialog v-model="showPermissionDialog"
|
||||
title="音频播放权限申请"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
:width="isMobile ? 330 : 700">
|
||||
<div class="permission-dialog">
|
||||
<p>是否同意本站播放音频?<br />包括但不限于SOS警报等服务信息提示音。</p>
|
||||
<div class="permission-agree">
|
||||
<el-checkbox v-model="permissionGranted">
|
||||
我同意该本站播放上述音频
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div v-if="permissionGranted">
|
||||
<div class="audio-settings-container">
|
||||
<div class="settings-row">
|
||||
<span class="settings-label">音量设置:{{ (volumeValue * 100).toFixed(0) }}%</span>
|
||||
</div>
|
||||
<div class="settings-controls">
|
||||
<div class="volume-control">
|
||||
<el-slider v-model="volumeValue"
|
||||
size="small"
|
||||
:min="0.1"
|
||||
:max="1"
|
||||
:step="0.05"
|
||||
:show-tooltip="false"
|
||||
@change="handleVolumeChange" />
|
||||
</div>
|
||||
<div class="preview-container">
|
||||
<el-button type="info"
|
||||
size="small"
|
||||
:loading="isPreviewLoading"
|
||||
:disabled="isPreviewPlaying"
|
||||
@click="previewSosSound"
|
||||
class="preview-btn">
|
||||
<el-icon><VideoPlay /></el-icon>
|
||||
{{ isPreviewPlaying ? "试听中…" : "点击试听" }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="handleCancelDialog" v-if="permissionCon">取消</el-button>
|
||||
<el-button type="primary" @click="confirmPermission">
|
||||
确定
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
<div style="visibility: hidden; height: 0; width: 0">
|
||||
<audio id="sosAudio" ref="sosAudioRef" controls="controls" type="audio/wav" loop>
|
||||
<source src="../../assets/sos.wav" />
|
||||
</audio>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, inject, onMounted, onUnmounted, computed, watch } from 'vue';
|
||||
import { ElMessage, ElIcon, ElButton, ElMessageBox, ElDialog, ElCheckbox, ElSlider } from 'element-plus'
|
||||
import { House, OfficeBuilding, Select, View, Checked, Connection, Bell, VideoPlay, MuteNotification } from '@element-plus/icons-vue'
|
||||
import qs from 'qs'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const $http = inject('$http')
|
||||
const isMobile = inject('isMobile')
|
||||
// MQTT
|
||||
const client = inject('client')
|
||||
const mqttlink = inject('mqttlink')
|
||||
const mqttmsg = inject('mqttmsg')
|
||||
|
||||
const username = localStorage.getItem('username')
|
||||
|
||||
// 注入方法
|
||||
const checkLoginStatus = inject('checkLoginStatus');
|
||||
|
||||
const allRooms = ref([]);
|
||||
const audioPermissionGranted = ref(false);
|
||||
const showPermissionDialog = ref(false); // 控制权限对话框显示
|
||||
const permissionGranted = ref(false); // 对话框内的勾选框状态
|
||||
const sosAudioRef = ref(null);
|
||||
const timer = ref(null);
|
||||
const permissionCon = ref(true);
|
||||
// 最后时间
|
||||
const lastMQTTtime = ref(null);
|
||||
const lastHTTPtime = ref(null);
|
||||
const timeUpdateFlag = ref(false)
|
||||
const timeUpdateInterval = ref(null)
|
||||
|
||||
const audio = ref(null);
|
||||
const isPlaying = ref(false);
|
||||
const playInterval = ref(null);
|
||||
// 新增音频控制相关的变量
|
||||
const volumeValue = ref(1.0); // 默认音量最大值 (0.0 - 1.0)
|
||||
const previewAudio = ref(null); // 试听音频对象
|
||||
const isPreviewPlaying = ref(false); // 试听是否正在播放
|
||||
const isPreviewLoading = ref(false); // 试听加载状态
|
||||
const previewPlayCount = ref(0); // 试听播放计数
|
||||
const previewInterval = ref(null); // 试听定时器
|
||||
const oldVolume = ref(1.0); // 旧音量值用于取消恢复
|
||||
|
||||
// 新增严格模式开关
|
||||
const strictMode = ref(JSON.parse(localStorage.getItem('strictMode') || 'false'));
|
||||
const showSOS1 = ref(JSON.parse(localStorage.getItem('showSOS1') || 'false'));
|
||||
const showOnline = ref(JSON.parse(localStorage.getItem('showOnline') || 'false'));
|
||||
|
||||
// 总房间数
|
||||
const totalRoomCount = computed(() => allRooms.value.length);
|
||||
const onlineRoomCount = computed(() => allRooms.value.filter(room => room.status).length);
|
||||
const sosRoomCount = computed(() => allRooms.value.filter(room => room.sos_status == 1).length);
|
||||
|
||||
const sortedRooms = computed(() => {
|
||||
return [...allRooms.value]
|
||||
.filter(room => {
|
||||
return (!showSOS1.value || room.sos_status == 1) &&
|
||||
(!showOnline.value || room.status === true)
|
||||
/*(!showSOS1.value && !showOnline.value) ||
|
||||
((showSOS1.value && room.sos_status == 1) || (showOnline.value && room.status === true))*/
|
||||
})
|
||||
.sort((a, b) => {
|
||||
// 使用缓存值避免重复计算权重
|
||||
const weightA = calculateWeight(a);
|
||||
const weightB = calculateWeight(b);
|
||||
|
||||
return weightA - weightB;
|
||||
});
|
||||
});
|
||||
|
||||
// 将权重计算提取为单独函数
|
||||
const calculateWeight = (room) => {
|
||||
if (room.sos_status == 1 && room.status) return 1; // SOS在线
|
||||
if (room.sos_status == 1 && !room.status) return 2; // SOS离线
|
||||
if (room.status) return 3; // 普通在线
|
||||
return 4; // 普通离线
|
||||
};
|
||||
|
||||
const hotelName = computed(() => localStorage.getItem('currentHotelName') || '房间列表');
|
||||
|
||||
|
||||
|
||||
// 播放SOS音频(根据模式)
|
||||
const playSosSound = () => {
|
||||
if (sosAudioRef.value) {
|
||||
sosAudioRef.value.currentTime = 0; // 重置播放位置
|
||||
isPlaying.value = false; // 重置播放状态
|
||||
}
|
||||
/*if (isPlaying.value || !sosAudioRef.value) return;*/
|
||||
|
||||
// 根据模式检查是否有需要播放的 SOS
|
||||
let shouldPlay = false;
|
||||
if (strictMode.value) {
|
||||
// 严格模式:只播放在线房间的 SOS
|
||||
shouldPlay = allRooms.value.some(room =>
|
||||
room.sos_status == 1 && room.status
|
||||
);
|
||||
} else {
|
||||
// 普通模式:播放所有 SOS
|
||||
shouldPlay = allRooms.value.some(room =>
|
||||
room.sos_status == 1
|
||||
);
|
||||
}
|
||||
if (shouldPlay) {
|
||||
// 设置音量
|
||||
sosAudioRef.value.volume = volumeValue.value;
|
||||
|
||||
isPlaying.value = true;
|
||||
sosAudioRef.value.play().catch(error => {
|
||||
console.error('音频播放失败:', error);
|
||||
isPlaying.value = false;
|
||||
});
|
||||
//console.log(`${strictMode.value ? '严格模式' : '普通模式'}下播放SOS警报`);
|
||||
}
|
||||
};
|
||||
const getTimeStyle = (timeStr) => {
|
||||
if (!timeStr || timeStr === '暂无') return {}
|
||||
|
||||
// 解析时间字符串 (格式: MM/DD HH:mm:ss)
|
||||
const [datePart, timePart] = timeStr.split(' ')
|
||||
const [month, day] = datePart.split('/').map(Number)
|
||||
const [hours, minutes, seconds] = timePart.split(':').map(Number)
|
||||
|
||||
// 创建日期对象(当前年份)
|
||||
const currentYear = new Date().getFullYear()
|
||||
const lastTime = new Date(currentYear, month - 1, day, hours, minutes, seconds)
|
||||
const now = new Date()
|
||||
|
||||
// 处理跨年情况(如果更新时间大于当前时间)
|
||||
if (lastTime > now) {
|
||||
lastTime.setFullYear(currentYear - 1)
|
||||
}
|
||||
|
||||
// 计算时间差(毫秒)
|
||||
const timeDiff = now - lastTime
|
||||
const fiveMinutesMs = 300000
|
||||
const tenMinutesMs = 600000
|
||||
|
||||
// 动态计算颜色(随时间变化)
|
||||
if (timeDiff <= fiveMinutesMs) {
|
||||
// 5分钟内:无显示颜色
|
||||
return {}
|
||||
} else if (timeDiff <= tenMinutesMs) {
|
||||
// 5-10分钟:橙色 -> 红色渐变
|
||||
const ratio = (timeDiff - fiveMinutesMs) / fiveMinutesMs
|
||||
const redValue = 255
|
||||
const greenValue = 165 - Math.floor(165 * ratio)
|
||||
return { color: `rgb(${redValue}, ${greenValue}, 0)` }
|
||||
} else {
|
||||
// 超过10分钟:红色
|
||||
return { color: `rgba(255, 0, 0)` }
|
||||
}
|
||||
}
|
||||
|
||||
// 停止SOS音频
|
||||
const stopSosSound = () => {
|
||||
if (!sosAudioRef.value) return;
|
||||
isPlaying.value = false;
|
||||
sosAudioRef.value.pause();
|
||||
if (playInterval.value) {
|
||||
clearInterval(playInterval.value);
|
||||
playInterval.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 获取所有房间
|
||||
const getRoomsWithStatus = async () => {
|
||||
try {
|
||||
const getdate = {
|
||||
hotel_code: localStorage.getItem('currentHotelCode'),
|
||||
createDate: localStorage.getItem('currentHotelCreateDate'),
|
||||
}
|
||||
const header = {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||
}
|
||||
const rs = await $http.post('LowerMachineLog/GetHostList', qs.stringify(getdate), header);
|
||||
lastHTTPtime.value = nowTime();
|
||||
if (rs.data.isok) {
|
||||
// 获取楼层权限
|
||||
const floorPermissionStr = localStorage.getItem('FloorPermission');
|
||||
const floorPermission = floorPermissionStr ? JSON.parse(floorPermissionStr) : [];
|
||||
if (floorPermission.length === 0) {
|
||||
allRooms.value = rs.data.response;
|
||||
} else {
|
||||
// 递归获取所有允许的楼层ID
|
||||
const allowedGroupIds = getAllowedGroupIds(floorPermission);
|
||||
// 更新房间列表,并过滤出在权限内的房间
|
||||
allRooms.value = rs.data.response.filter(room =>
|
||||
allowedGroupIds.includes(room.groupid)
|
||||
);
|
||||
}
|
||||
//console.log('allRooms', allRooms.value)
|
||||
} else {
|
||||
ElMessage.error(rs.data.message)
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取主机列表失败')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
// 递归获取所有楼层ID(包括子节点)
|
||||
const getAllowedGroupIds = (nodes) => {
|
||||
let ids = [];
|
||||
nodes.forEach(node => {
|
||||
ids.push(node.id);
|
||||
if (node.children && node.children.length > 0) {
|
||||
ids = ids.concat(getAllowedGroupIds(node.children));
|
||||
}
|
||||
});
|
||||
return ids;
|
||||
};
|
||||
// 确认音频权限
|
||||
const confirmPermission = () => {
|
||||
audioPermissionGranted.value = permissionGranted.value;
|
||||
showPermissionDialog.value = false;
|
||||
permissionCon.value = true;
|
||||
if (audioPermissionGranted.value) {
|
||||
// 不再调用 checkOfflineHosts()
|
||||
ElMessage.success('音频权限已启用');
|
||||
|
||||
// 只有在有 SOS 房间时才播放
|
||||
if (strictMode.value) {
|
||||
// 严格模式:检查在线房间的 SOS
|
||||
if (allRooms.value.some(room => room.sos_status == 1 && room.status)) {
|
||||
playSosSound();
|
||||
}
|
||||
} else {
|
||||
// 普通模式:检查所有 SOS
|
||||
if (allRooms.value.some(room => room.sos_status == 1)) {
|
||||
playSosSound();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stopSosSound();
|
||||
ElMessage.info('音频权限已禁用');
|
||||
}
|
||||
};
|
||||
|
||||
// 设置音量并播放测试音频
|
||||
const handleVolumeChange = () => {
|
||||
// 设置SOS报警音量为新的值
|
||||
if (sosAudioRef.value) {
|
||||
sosAudioRef.value.volume = volumeValue.value;
|
||||
}
|
||||
|
||||
// 播放一次试听音频
|
||||
previewSosSound(1);
|
||||
};
|
||||
// 播放试听音频
|
||||
const previewSosSound = (count = 3) => {
|
||||
if (!sosAudioRef.value) {
|
||||
ElMessage.warning('音频文件未加载,无法试听');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPreviewPlaying.value) return;
|
||||
|
||||
// 停止可能正在播放的试听
|
||||
if (previewInterval.value) {
|
||||
clearInterval(previewInterval.value);
|
||||
previewInterval.value = null;
|
||||
}
|
||||
|
||||
// 获取音频源
|
||||
const src = sosAudioRef.value.children[0].src;
|
||||
|
||||
// 创建一个新的Audio对象用于试听
|
||||
if (!previewAudio.value) {
|
||||
previewAudio.value = new Audio(src);
|
||||
}
|
||||
|
||||
// 设置音量
|
||||
previewAudio.value.volume = volumeValue.value;
|
||||
|
||||
// 设置播放次数
|
||||
previewPlayCount.value = count;
|
||||
let playCounter = 0;
|
||||
|
||||
// 准备播放
|
||||
isPreviewLoading.value = true;
|
||||
previewAudio.value.pause();
|
||||
previewAudio.value.currentTime = 0;
|
||||
|
||||
// 处理播放结束逻辑
|
||||
const playEndedHandler = () => {
|
||||
playCounter++;
|
||||
|
||||
if (playCounter < count) {
|
||||
// 播放下一遍
|
||||
previewAudio.value.currentTime = 0;
|
||||
previewPlayCount.value = count - playCounter;
|
||||
previewAudio.value.play().catch(err => {
|
||||
console.error('试听播放失败:', err);
|
||||
stopPreview();
|
||||
ElMessage.error('试听播放失败,请检查音频权限');
|
||||
});
|
||||
} else {
|
||||
// 播放完成
|
||||
stopPreview();
|
||||
}
|
||||
};
|
||||
// 添加事件监听
|
||||
previewAudio.value.addEventListener('ended', playEndedHandler);
|
||||
|
||||
// 开始播放
|
||||
previewAudio.value.play()
|
||||
.then(() => {
|
||||
isPreviewLoading.value = false;
|
||||
isPreviewPlaying.value = true;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('试听播放失败:', err);
|
||||
isPreviewLoading.value = false;
|
||||
previewAudio.value.removeEventListener('ended', playEndedHandler);
|
||||
ElMessage.error('试听播放失败,请检查音频权限');
|
||||
});
|
||||
};
|
||||
// 停止试听播放
|
||||
const stopPreview = () => {
|
||||
if (previewAudio.value) {
|
||||
previewAudio.value.pause();
|
||||
previewAudio.value.currentTime = 0;
|
||||
}
|
||||
isPreviewPlaying.value = false;
|
||||
isPreviewLoading.value = false;
|
||||
previewPlayCount.value = 0;
|
||||
|
||||
if (previewInterval.value) {
|
||||
clearInterval(previewInterval.value);
|
||||
previewInterval.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 打开弹窗时保存当前设置
|
||||
const handleOpenDialog = () => {
|
||||
showPermissionDialog.value = true;
|
||||
// 保存当前的音量值
|
||||
oldVolume.value = volumeValue.value;
|
||||
// 停止可能正在播放的试听
|
||||
stopPreview();
|
||||
};
|
||||
// 处理取消操作
|
||||
const handleCancelDialog = () => {
|
||||
// 恢复之前的音量设置
|
||||
volumeValue.value = oldVolume.value;
|
||||
// 关闭弹窗
|
||||
showPermissionDialog.value = false;
|
||||
// 停止试听
|
||||
stopPreview();
|
||||
};
|
||||
|
||||
// 更新时间
|
||||
const nowTime = () => {
|
||||
const now = new Date();
|
||||
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
return `${month}/${day} ${hours}:${minutes}:${seconds}`;
|
||||
};
|
||||
|
||||
|
||||
// 监听 strictMode 变化
|
||||
watch(strictMode, (newValue, oldValue) => {
|
||||
//console.log(`严格模式已${newValue ? '启用' : '禁用'}`);
|
||||
|
||||
// 当前有SOS警报在播放
|
||||
if (isPlaying.value) {
|
||||
// 禁用严格模式 -> 继续播放
|
||||
// 启用严格模式 -> 检查是否只播放在线房间警报
|
||||
if (newValue) {
|
||||
// 如果严格模式下无在线房间需要警报,则停止播放
|
||||
if (!allRooms.value.some(room => room.sos_status == 1 && room.status)) {
|
||||
stopSosSound();
|
||||
//console.log('严格模式启用:停止所有离线房间警报');
|
||||
}
|
||||
} else {
|
||||
// 重新播放所有SOS房间警报
|
||||
playSosSound();
|
||||
}
|
||||
} else {
|
||||
// 没有警报在播放时
|
||||
// 如果禁用严格模式且存在SOS房间,则开始播放
|
||||
if (!newValue && allRooms.value.some(room => room.sos_status == 1)) {
|
||||
playSosSound();
|
||||
//console.log('严格模式禁用:开始播放所有SOS房间警报');
|
||||
}
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
// 监听 allRooms 变化
|
||||
watch(allRooms, (newRooms, oldRooms) => {
|
||||
//console.log('allRooms 已更新');
|
||||
|
||||
// 确保 newRooms 和 oldRooms 是数组
|
||||
const safeNewRooms = Array.isArray(newRooms) ? newRooms : [];
|
||||
const safeOldRooms = Array.isArray(oldRooms) ? oldRooms : [];
|
||||
|
||||
// 计算 SOS 房间数量(根据当前模式)
|
||||
const getSosCount = (rooms) => {
|
||||
if (strictMode.value) {
|
||||
// 严格模式:只计算在线房间的 SOS
|
||||
return rooms.filter(r => r.sos_status == 1 && r.status).length;
|
||||
} else {
|
||||
// 普通模式:计算所有 SOS
|
||||
return rooms.filter(r => r.sos_status == 1).length;
|
||||
}
|
||||
};
|
||||
|
||||
const newSosCount = getSosCount(safeNewRooms);
|
||||
const oldSosCount = getSosCount(safeOldRooms);
|
||||
|
||||
// SOS 状态变化处理
|
||||
if (!audioPermissionGranted.value) return;
|
||||
// 当出现SOS警报时
|
||||
if (newSosCount > 0) {
|
||||
playSosSound();
|
||||
}
|
||||
// 当所有SOS警报都解除时
|
||||
else {
|
||||
stopSosSound();
|
||||
}
|
||||
}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
});
|
||||
|
||||
watch(permissionGranted, (newVal, oldVal) => {
|
||||
permissionCon.value = !permissionCon.value;
|
||||
})
|
||||
|
||||
watch(mqttmsg, (newVal, oldVal) => {
|
||||
lastMQTTtime.value = nowTime();
|
||||
|
||||
try {
|
||||
const n = JSON.parse(newVal);
|
||||
lastMQTTtime.value = nowTime(); // 更新最后推送时间
|
||||
|
||||
// 验证消息格式和内容
|
||||
if (!n || !n.roomnum || n.status === undefined) {
|
||||
console.warn('无效的MQTT消息格式:', n);
|
||||
return;
|
||||
}
|
||||
|
||||
// 只处理当前酒店的消息
|
||||
const currentHotelCode = localStorage.getItem('currentHotelCode');
|
||||
if (n.hotelcode !== currentHotelCode) {
|
||||
console.log('忽略非当前酒店的MQTT消息');
|
||||
return;
|
||||
}
|
||||
|
||||
// 房间号类型处理函数
|
||||
const fixRoomNumberType = (roomno) => {
|
||||
return typeof roomno === 'number' ? String(roomno) : roomno;
|
||||
};
|
||||
|
||||
// 查找并更新对应房间的SOS状态
|
||||
const roomnumNormalized = fixRoomNumberType(n.roomnum);
|
||||
const roomIndex = allRooms.value.findIndex(
|
||||
room => fixRoomNumberType(room.roomno) === roomnumNormalized
|
||||
);
|
||||
|
||||
if (roomIndex !== -1) {
|
||||
// 创建新数组确保响应式更新
|
||||
const updatedRooms = [...allRooms.value];
|
||||
updatedRooms[roomIndex] = {
|
||||
...updatedRooms[roomIndex],
|
||||
sos_status: n.status
|
||||
};
|
||||
//console.log(updatedRooms, n)
|
||||
allRooms.value = updatedRooms;
|
||||
|
||||
console.log(`更新房间 ${n.roomnum} 的SOS状态为: ${n.status}`);
|
||||
} else {
|
||||
console.warn(`未找到房间号: ${n.roomnum}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析MQTT消息失败:', error);
|
||||
}
|
||||
})
|
||||
|
||||
// 监听开关变化并保存到本地存储
|
||||
watch(strictMode, (newVal) => {
|
||||
localStorage.setItem('strictMode', JSON.stringify(newVal));
|
||||
});
|
||||
|
||||
watch(showSOS1, (newVal) => {
|
||||
localStorage.setItem('showSOS1', JSON.stringify(newVal));
|
||||
});
|
||||
|
||||
watch(showOnline, (newVal) => {
|
||||
localStorage.setItem('showOnline', JSON.stringify(newVal));
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
localStorage.setItem('url', '/home')
|
||||
checkLoginStatus()
|
||||
|
||||
// 初始加载房间数据
|
||||
await getRoomsWithStatus()
|
||||
|
||||
// 初始权限请求
|
||||
handleOpenDialog()
|
||||
|
||||
// 设置定时刷新房间状态(每5分钟)
|
||||
timer.value = setInterval(async () => {
|
||||
await getRoomsWithStatus()
|
||||
//ElMessage.success('房间状态已自动更新');
|
||||
}, 300000); // 5分钟
|
||||
timeUpdateInterval.value = setInterval(() => {
|
||||
timeUpdateFlag.value = !timeUpdateFlag.value
|
||||
}, 20000)
|
||||
})
|
||||
|
||||
|
||||
// 组件卸载时的清理
|
||||
onUnmounted(() => {
|
||||
// 清除定时器
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
if (timeUpdateInterval.value) clearInterval(timeUpdateInterval.value)
|
||||
// 停止SOS音频
|
||||
stopSosSound();
|
||||
|
||||
// 停止试听音频
|
||||
stopPreview();
|
||||
|
||||
// 清理试听音频
|
||||
if (previewAudio.value) {
|
||||
previewAudio.value.pause();
|
||||
previewAudio.value = null;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 添加开关间距 */
|
||||
.strict-mode-switch {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: left;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.room-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 5px 2px; /* 上下5px,左右2px */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.room-box {
|
||||
width: 110px;
|
||||
min-height: 110px;
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--el-border-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.room-box:hover {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.room-number {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.hotel-code {
|
||||
font-size: 12px;
|
||||
margin: 4px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 3px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
/* 新增头部容器样式 */
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 10px;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
/* 头部操作区 */
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
/* 权限申请对话框样式 */
|
||||
.permission-dialog {
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.permission-agree {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.audio-icon {
|
||||
font-size: 24px;
|
||||
color: var(--el-color-warning);
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
/* 房间信息 */
|
||||
.hotel-code {
|
||||
font-size: 12px;
|
||||
margin: 4px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 按钮组 */
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 统计标签组 */
|
||||
.stats-group {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 响应式调整列数 */
|
||||
@media (max-width: 600px) {
|
||||
.room-container {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.room-box {
|
||||
height: auto;
|
||||
width: 100px;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.stats-group {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.settings-row {
|
||||
align-items: center;
|
||||
width: 230px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
border-left: 1px solid var(--el-border-color);
|
||||
height: 20px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
|
||||
.settings-label {
|
||||
font-weight: bold;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.audio-settings-container {
|
||||
margin: 0 auto;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.settings-controls {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.volume-control {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.controls-container {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.volume-control {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.room-container {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色模式样式调整 */
|
||||
.dark .room-box {
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
|
||||
border-color: var(--el-border-color-lighter);
|
||||
}
|
||||
|
||||
.dark .room-box:hover {
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
</style>
|
||||
401
src/pages/log/index.vue
Normal file
401
src/pages/log/index.vue
Normal file
@@ -0,0 +1,401 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 顶部标题行 -->
|
||||
<div class="header-container">
|
||||
<!-- 标题 -->
|
||||
<h1 class="header">房间列表</h1>
|
||||
|
||||
<!-- 功能按钮组 -->
|
||||
<div class="header-actions">
|
||||
<!-- 第一组:全部加入/取消监控按钮 -->
|
||||
<div class="button-group">
|
||||
<el-button v-if="showAddAllButton"
|
||||
type="primary"
|
||||
plain
|
||||
size="small"
|
||||
@click="addAllMonitor"
|
||||
class="action-btn">
|
||||
<el-icon><Checked /></el-icon>
|
||||
全部加入监控
|
||||
</el-button>
|
||||
|
||||
<el-button v-if="showCancelAllButton"
|
||||
type="warning"
|
||||
plain
|
||||
size="small"
|
||||
@click="cancelAllMonitor"
|
||||
class="action-btn">
|
||||
<el-icon><Close /></el-icon>
|
||||
全部取消监控
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 第二组:统计标签 -->
|
||||
<div class="stats-group">
|
||||
<el-tag type="info">总房间: {{ totalRoomCount }}</el-tag>
|
||||
<el-tag type="success" v-if="monitoredRoomCount > 0">
|
||||
监控中: {{ monitoredRoomCount }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主机盒子容器 -->
|
||||
<div class="room-container">
|
||||
<div v-for="(host, index) in mergedRooms" :key="index" class="room-box" @click="viewDetail(host)">
|
||||
<!-- 第一行:房间号 -->
|
||||
<div class="room-number">
|
||||
<el-icon><House /></el-icon>
|
||||
{{ host.roomno || host.roomNumber }}
|
||||
</div>
|
||||
<!-- 第二行:酒店代码 -->
|
||||
<div class="hotel-code">
|
||||
<el-icon><OfficeBuilding /></el-icon>
|
||||
{{ host.hotelCode }}
|
||||
</div>
|
||||
<!-- 第三行:操作按钮 -->
|
||||
<div class="actions">
|
||||
<!-- 已监控的显示取消按钮 -->
|
||||
<el-button v-if="host.isMonitored"
|
||||
size="small"
|
||||
type="warning"
|
||||
plain
|
||||
@click.stop="cancelMonitor(host)"
|
||||
class="action-btn">
|
||||
<el-icon><Close /></el-icon>
|
||||
取消监控
|
||||
</el-button>
|
||||
<!-- 未监控的显示加入按钮 -->
|
||||
<el-button v-else
|
||||
size="small"
|
||||
type="success"
|
||||
plain
|
||||
@click.stop="addMonitor(host)"
|
||||
class="action-btn">
|
||||
<el-icon><Checked /></el-icon>
|
||||
加入监控
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, inject, onMounted, watch, computed } from 'vue';
|
||||
import { ElMessage, ElIcon, ElButton } from 'element-plus'
|
||||
import { House, OfficeBuilding, Close, View, Checked, Connection } from '@element-plus/icons-vue'
|
||||
import qs from 'qs'
|
||||
|
||||
const $http = inject('$http')
|
||||
// 注入方法
|
||||
const checkLoginStatus = inject('checkLoginStatus');
|
||||
|
||||
const allRooms = ref([])
|
||||
const allHostRooms = ref([])
|
||||
|
||||
const totalRoomCount = computed(() => allRooms.value.length);
|
||||
const monitoredRoomCount = computed(() => allHostRooms.value.length);
|
||||
|
||||
// 控制按钮显示的条件计算属性
|
||||
const showAddAllButton = computed(() => {
|
||||
return totalRoomCount.value > 0 && monitoredRoomCount.value < totalRoomCount.value;
|
||||
});
|
||||
|
||||
const showCancelAllButton = computed(() => {
|
||||
return monitoredRoomCount.value > 0;
|
||||
});
|
||||
|
||||
// 创建合并后的房间列表
|
||||
const mergedRooms = computed(() => {
|
||||
// 创建映射表,key为roomNumber(用于查找)
|
||||
const monitoredMap = new Map();
|
||||
allHostRooms.value.forEach(hostRoom => {
|
||||
// 使用roomNumber作为键
|
||||
monitoredMap.set(hostRoom.roomNumber, hostRoom);
|
||||
});
|
||||
console.log(allRooms.value)
|
||||
return allRooms.value.map(room => {
|
||||
// 查找对应的监控房间(通过房间号匹配)
|
||||
const matchedHostRoom = monitoredMap.get(room.roomno);
|
||||
|
||||
// 创建合并对象
|
||||
const merged = {
|
||||
// 首先添加房间的基础字段(allRooms)
|
||||
...room,
|
||||
// 添加监控状态
|
||||
isMonitored: !!matchedHostRoom,
|
||||
|
||||
// 然后添加监控房间中的唯一字段
|
||||
...(matchedHostRoom ? {
|
||||
tx: matchedHostRoom.tx,
|
||||
rx: matchedHostRoom.rx,
|
||||
lastData: matchedHostRoom.lastData,
|
||||
hostID: matchedHostRoom.hostID,
|
||||
hotelCode: matchedHostRoom.hotelCode,
|
||||
key_HostNumber: matchedHostRoom.key_HostNumber,
|
||||
createDateTime: matchedHostRoom.createDateTime,
|
||||
} : {
|
||||
hotelCode: localStorage.getItem('currentHotelCode'),
|
||||
})
|
||||
};
|
||||
return merged;
|
||||
});
|
||||
});
|
||||
|
||||
// 获取所有房间
|
||||
const getRooms = async () => {
|
||||
try {
|
||||
const getdate = {
|
||||
hotel_code: localStorage.getItem('currentHotelCode'),
|
||||
createDate: localStorage.getItem('currentHotelCreateDate'),
|
||||
}
|
||||
const header = {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
const rs = await $http.post('LowerMachineLog/GetHostList', qs.stringify(getdate), header);
|
||||
if (rs.data.isok) {
|
||||
allRooms.value = rs.data.response
|
||||
} else {
|
||||
ElMessage.error(rs.data.message)
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取主机列表失败')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取已经监控的房间
|
||||
const getHostRooms = async () => {
|
||||
try {
|
||||
const getdate = {
|
||||
hotelcode: localStorage.getItem('currentHotelCode'),
|
||||
}
|
||||
|
||||
const rs = await $http.post('LowerMachineLog/GetSpe_MonitorHost', getdate);
|
||||
if (rs.data.isok) {
|
||||
allHostRooms.value = rs.data.response.data || []
|
||||
} else {
|
||||
ElMessage.error(rs.data.message)
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取监控列表失败')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 取消监控
|
||||
const cancelMonitor = async (host) => {
|
||||
try {
|
||||
// 构造数据时使用正确的房间标识
|
||||
const data = {
|
||||
roomNumber: host.roomno || host.roomNumber, // 使用allRooms中的roomno作为标识
|
||||
hotelCode: host.hotelCode
|
||||
}
|
||||
|
||||
const rs = await $http.post('LowerMachineLog/CancelMonitorHost', data);
|
||||
if (rs.data.isok) {
|
||||
ElMessage.success('取消监控成功')
|
||||
// 刷新监控列表
|
||||
await getHostRooms()
|
||||
} else {
|
||||
ElMessage.error(rs.data.message)
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('取消监控操作失败')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 加入监控
|
||||
const addMonitor = async (host) => {
|
||||
try {
|
||||
return await true
|
||||
} catch (error) {
|
||||
ElMessage.error('加入监控操作失败')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
// 需要实现的方法(只需提供方法注释)
|
||||
const addAllMonitor = async () => {
|
||||
/**
|
||||
* 全部加入监控实现步骤:
|
||||
* 1. 从mergedRooms中筛选出所有isMonitored为false的房间
|
||||
* 2. 遍历这些未监控的房间,调用addMonitor方法(需修改现有的addMonitor方法支持批量操作)
|
||||
* 3. 所有操作完成后刷新监控列表
|
||||
* 4. 操作成功/失败提示
|
||||
*/
|
||||
};
|
||||
|
||||
const cancelAllMonitor = async () => {
|
||||
/**
|
||||
* 全部取消监控实现步骤:
|
||||
* 1. 从allHostRooms中获取所有已监控的房间
|
||||
* 2. 遍历这些已监控的房间,调用cancelMonitor方法(需修改现有的cancelMonitor方法支持批量操作)
|
||||
* 3. 所有操作完成后刷新监控列表
|
||||
* 4. 操作成功/失败提示
|
||||
*/
|
||||
};
|
||||
// 查看详情
|
||||
const viewDetail = (host) => {
|
||||
console.log('查看详情:', host)
|
||||
// 这里实现跳转到详情页或其他操作
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
localStorage.setItem('url', '/home')
|
||||
checkLoginStatus()
|
||||
// 同时获取所有房间和监控列表
|
||||
Promise.all([getRooms(), getHostRooms()])
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: left;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.room-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 6px 10px; /* 上下6px,左右10px */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.room-box {
|
||||
width: 122px;
|
||||
height: 135px;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--el-border-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.room-box:hover {
|
||||
transform: translateY(-3px);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.room-box::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #409eff, #67c23a, #e6a23c);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.room-number {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.hotel-code {
|
||||
font-size: 12px;
|
||||
margin: 4px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 3px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 100%;
|
||||
padding: 0 5px;
|
||||
margin: 0;
|
||||
font-size: 13px !important;
|
||||
height: 24px;
|
||||
--el-button-size: 24px;
|
||||
}
|
||||
|
||||
/* 新增头部容器样式 */
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 20px;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
/* 头部操作区 */
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* 按钮组 */
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 统计标签组 */
|
||||
.stats-group {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 响应式调整列数 */
|
||||
@media (max-width: 600px) {
|
||||
.room-container {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.room-box {
|
||||
height: auto;
|
||||
min-height: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.room-container {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 深色模式样式调整 */
|
||||
.dark .room-box {
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
|
||||
border-color: var(--el-border-color-lighter);
|
||||
}
|
||||
|
||||
.dark .room-box:hover {
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/* 减少深色模式下的亮度变化 */
|
||||
.dark .room-box::before {
|
||||
opacity: 0.4;
|
||||
}
|
||||
</style>
|
||||
549
src/pages/login/index.vue
Normal file
549
src/pages/login/index.vue
Normal file
@@ -0,0 +1,549 @@
|
||||
<template>
|
||||
<div style="height:100vh">
|
||||
<div class="container">
|
||||
|
||||
<div class="login-container">
|
||||
|
||||
<el-form :model="form"
|
||||
status-icon
|
||||
:disabled="isLocked"
|
||||
class="login-form"
|
||||
@submit.prevent="handleSubmit">
|
||||
<!-- 账号输入 -->
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="form.username"
|
||||
placeholder="请输入账号"
|
||||
clearable
|
||||
@focus="scrollToFormBottom"
|
||||
:prefix-icon="User" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 密码输入 -->
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="form.password"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
show-password
|
||||
@focus="scrollToFormBottom"
|
||||
:prefix-icon="Lock" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 验证码区域 -->
|
||||
<el-form-item prop="code" class="captcha-container">
|
||||
<div class="captcha-input">
|
||||
<el-input v-model="form.code"
|
||||
@focus="scrollToFormBottom"
|
||||
placeholder="请输入验证码"
|
||||
:prefix-icon="Key"
|
||||
maxlength="4" />
|
||||
<img :src="captchaSrc"
|
||||
class="captcha-image"
|
||||
alt="验证码"
|
||||
@click="generateCaptcha" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 记住我 & 操作按钮 -->
|
||||
<el-form-item>
|
||||
<div class="form-actions">
|
||||
<el-checkbox v-model="form.remember">记住我</el-checkbox>
|
||||
<el-button type="primary"
|
||||
native-type="submit"
|
||||
:loading="loading"
|
||||
:disabled="submitDisabled">
|
||||
{{ isLocked ? `请等待${lockRemainTime}后重试` : '立即登录' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 错误提示 -->
|
||||
<div v-if="errorAttempts > 0" class="error-tip">
|
||||
已错误尝试 {{ errorAttempts }} 次(5次后将锁定账号)
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="logo-container">
|
||||
<img src="../../../public/image/advertisement.svg" class="log-img" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import { ref, inject, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { User, Lock, Key } from '@element-plus/icons-vue'
|
||||
import { useNow } from '@vueuse/core';
|
||||
|
||||
|
||||
const checkLoginStatus = inject('checkLoginStatus');
|
||||
const calculateTimeDiff = inject('calculateTimeDiff');
|
||||
|
||||
const router = useRouter()
|
||||
const $http = inject('$http')
|
||||
|
||||
// 响应式状态
|
||||
const form = ref({
|
||||
username: localStorage.getItem('rememberedUsername') || '',
|
||||
password: localStorage.getItem('rememberedPassword') || '',
|
||||
remember: localStorage.getItem('rememberedUsername') ?
|
||||
Boolean(localStorage.getItem('rememberedUsername')) :
|
||||
true,
|
||||
code: ''
|
||||
})
|
||||
|
||||
|
||||
const isDarkMode = ref(window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
const loading = ref(false);
|
||||
const submitDisabled = ref(false);
|
||||
const isLocked = ref(false);
|
||||
const errorAttempts = ref(parseInt(localStorage.getItem('loginErrorAttempts')) || 0);
|
||||
const lockUntil = ref(parseInt(localStorage.getItem('loginLockUntil')) || 0);
|
||||
const captchaSrc = ref('');
|
||||
const captchaValue = ref('');
|
||||
|
||||
// 计算属性
|
||||
const lockRemainTime = computed(() => {
|
||||
if (!isLocked.value) return '00:00'
|
||||
const remain = (lockUntil.value - Date.now()) / 1000
|
||||
return `${Math.floor(remain / 60)}分${Math.floor(remain % 60)}秒`
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 方法实现
|
||||
const initAuthState = () => {
|
||||
if (lockUntil.value && Date.now() < lockUntil.value) {
|
||||
setupUnlockTimer(lockUntil.value - Date.now())
|
||||
}
|
||||
}
|
||||
|
||||
// 新增深色模式状态
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
isDarkMode.value = true;
|
||||
} else {
|
||||
isDarkMode.value = false;
|
||||
}
|
||||
|
||||
|
||||
const setupUnlockTimer = (duration) => {
|
||||
isLocked.value = true
|
||||
setTimeout(() => {
|
||||
isLocked.value = false
|
||||
errorAttempts.value = 0
|
||||
localStorage.removeItem('loginLockUntil')
|
||||
localStorage.removeItem('loginErrorAttempts')
|
||||
}, duration)
|
||||
}
|
||||
|
||||
// 生成验证码
|
||||
const generateCaptcha = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const chars = '0123456789';
|
||||
let captcha = '';
|
||||
canvas.width = 86;
|
||||
canvas.height = 30;
|
||||
|
||||
// 生成验证码字符串
|
||||
for (let i = 0; i < 4; i++) {
|
||||
captcha += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
captchaValue.value = captcha; // 存储验证码值用于验证
|
||||
|
||||
// 绘制背景
|
||||
ctx.fillStyle = isDarkMode.value ? '#242424' : '#FFFFFF';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// 绘制噪点
|
||||
ctx.fillStyle = isDarkMode.value ? '#FFFFFF' : '#000000';
|
||||
for (let i = 0; i < 33; i++) {
|
||||
const x = Math.random() * canvas.width;
|
||||
const y = Math.random() * canvas.height;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, 1, 0, Math.PI * 2, false);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// 绘制验证码
|
||||
ctx.font = '24px Arial';
|
||||
ctx.fillStyle = isDarkMode.value ? '#FFFFFF' : '#000000';
|
||||
let xnd = 10;
|
||||
for (let i = 0; i < captcha.length; i++) {
|
||||
const angle = (Math.random() * 30) - 15; // -10度到+10度
|
||||
|
||||
// 保存当前状态
|
||||
ctx.save();
|
||||
|
||||
// 旋转并绘制文字
|
||||
ctx.translate(xnd, 20);
|
||||
ctx.rotate(angle * Math.PI / 180);
|
||||
ctx.fillText(captcha[i], 0, 0);
|
||||
|
||||
// 恢复状态
|
||||
ctx.restore();
|
||||
|
||||
// 更新下一个字符的x位置
|
||||
xnd += 15 + Math.abs(angle) / 2; // 根据角度调整字符间距
|
||||
}
|
||||
|
||||
// 添加5-10条干扰条纹
|
||||
ctx.strokeStyle = isDarkMode.value ? '#CCCCCC' : '#6F4A2F';
|
||||
const bug = Math.floor(Math.random() * 6) + 3
|
||||
for (let i = 0; i < bug; i++) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(Math.random() * canvas.width, Math.random() * canvas.height);
|
||||
ctx.lineTo(Math.random() * canvas.width, Math.random() * canvas.height);
|
||||
ctx.stroke();
|
||||
}
|
||||
// 将canvas转换为图片URL
|
||||
captchaSrc.value = canvas.toDataURL('image/png');
|
||||
}
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (isLocked.value || submitDisabled.value) return
|
||||
if (!validateForm()) return
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
const response = await $http.post('RCU/Login', {
|
||||
username: form.value.username,
|
||||
password: form.value.password
|
||||
})
|
||||
|
||||
//console.log(response)
|
||||
handleLoginResponse(response.data)
|
||||
} catch (error) {
|
||||
handleLoginError(error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
// 新增表单验证方法
|
||||
const validateForm = () => {
|
||||
if (!form.value.username.trim()) {
|
||||
ElMessage.error('请输入账号!')
|
||||
return false
|
||||
}
|
||||
if (!form.value.password.trim()) {
|
||||
ElMessage.error('请输入密码!')
|
||||
return false
|
||||
}
|
||||
if (!form.value.code.trim()) {
|
||||
ElMessage.error('请输入验证码!')
|
||||
return false
|
||||
}
|
||||
if (form.value.code !== captchaValue.value) {
|
||||
ElMessage.error('验证码错误!')
|
||||
generateCaptcha()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// 新增错误处理方法
|
||||
const handleLoginError = (error) => {
|
||||
console.error('登录请求失败:', error)
|
||||
ElMessage.error('网络请求失败,请检查网络连接')
|
||||
errorAttempts.value++
|
||||
}
|
||||
|
||||
|
||||
const handleLoginResponse = (data) => {
|
||||
if (data.isok) {
|
||||
handleLoginSuccess(JSON.parse(data.response))
|
||||
} else {
|
||||
handleLoginFailure(data.message)
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动到表单底部(用于移动端输入框聚焦)
|
||||
const scrollToFormBottom = () => {
|
||||
window.scrollTo({
|
||||
top: document.body.scrollHeight,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
|
||||
const handleLoginSuccess = (userData) => {
|
||||
if (!userData.isok) {
|
||||
handleLoginFailure(userData.message)
|
||||
return
|
||||
}
|
||||
// 登录成功处理...
|
||||
errorAttempts.value = 0
|
||||
if (localStorage.getItem('ATTEMPTS_STORAGE_KEY')) {
|
||||
localStorage.removeItem(ATTEMPTS_STORAGE_KEY)
|
||||
}
|
||||
if (localStorage.getItem('LOCK_STORAGE_KEY')) {
|
||||
localStorage.removeItem(LOCK_STORAGE_KEY)
|
||||
}
|
||||
localStorage.removeItem('loginErrorAttempts')
|
||||
|
||||
localStorage.setItem('username', form.value.username)
|
||||
localStorage.setItem('password', form.value.password)
|
||||
localStorage.setItem('login', true)
|
||||
//localStorage.setItem('permission', userData.response)
|
||||
console.log(userData.response)
|
||||
|
||||
const hostarr = Array.from(new Map(userData.response.HotelListInfo.map(item => [item.ID, item])).values())
|
||||
localStorage.setItem('AccessibleHotels', JSON.stringify(hostarr))
|
||||
localStorage.setItem('FloorPermission', JSON.stringify(userData.response.OwinFloorGroupList))
|
||||
localStorage.setItem("TokenT", new Date())
|
||||
// 记住账号和密码
|
||||
if (form.value.remember) {
|
||||
localStorage.setItem('rememberedUsername', form.value.username)
|
||||
localStorage.setItem('rememberedPassword', form.value.password)
|
||||
} else {
|
||||
if (localStorage.getItem('rememberedUsername')) {
|
||||
localStorage.removeItem('rememberedPassword')
|
||||
}
|
||||
}
|
||||
ElMessage.success(`登录成功,欢迎:${form.value.username}!`)
|
||||
router.push('/home')
|
||||
}
|
||||
|
||||
const handleLoginFailure = (message) => {
|
||||
ElMessage.error(message)
|
||||
errorAttempts.value++
|
||||
localStorage.setItem('loginErrorAttempts', errorAttempts.value)
|
||||
|
||||
if (errorAttempts.value >= 5) {
|
||||
const lockUntil = Date.now() + 3600000
|
||||
lockUntil.value = lockUntil
|
||||
localStorage.setItem('loginLockUntil', lockUntil)
|
||||
setupUnlockTimer(3600000)
|
||||
}
|
||||
}
|
||||
|
||||
// 验证时间
|
||||
const TokenTCheck = () => {
|
||||
generateCaptcha()
|
||||
console.log(localStorage.getItem("TokenT"))
|
||||
if (localStorage.getItem("TokenT")) {
|
||||
if (calculateTimeDiff(localStorage.getItem("TokenT")) < 666666) {
|
||||
form.value.code = captchaValue.value
|
||||
if (validateForm()) {
|
||||
handleSubmit()
|
||||
}
|
||||
} else {
|
||||
//localStorage.removeItem("TokenT")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
localStorage.removeItem('AccessibleHotels')
|
||||
localStorage.setItem('login', false)
|
||||
//generateCaptcha()
|
||||
TokenTCheck()
|
||||
initAuthState()
|
||||
checkLoginStatus()
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logo-container, .login-container {
|
||||
flex: 1; /* 各占50% */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center; /* 水平居中 */
|
||||
justify-content: center; /* 垂直居中 */
|
||||
/*min-height: 100vh;*/
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
width: 80%;
|
||||
max-width: 400px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
margin: 2rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* 外层容器样式 */
|
||||
div[style*="display: flex"] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 通用样式保持 */
|
||||
.captcha-container {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.captcha-input {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.error-tip {
|
||||
color: var(--el-color-danger);
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
margin-top: -10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.brand-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
cursor: default; /* 禁用文本选择光标 */
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.symbol-container {
|
||||
position: relative;
|
||||
margin-right: 25px;
|
||||
pointer-events: none; /* 禁用图形部分交互 */
|
||||
}
|
||||
|
||||
.text-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
pointer-events: none; /* 禁用文字部分交互 */
|
||||
}
|
||||
|
||||
.main-text {
|
||||
font-size: 88px;
|
||||
font-weight: 900; /* 加粗程度提升 */
|
||||
font-style: italic; /* 新增斜体效果 */
|
||||
margin-bottom: 5px;
|
||||
font-family: Arial, sans-serif; /* 确保斜体生效 */
|
||||
transform: skewX(-10deg);
|
||||
}
|
||||
|
||||
/* 其他保持原有样式 */
|
||||
/* h1 {
|
||||
margin: 100px 0px 100px 0px;
|
||||
text-align: center
|
||||
}*/
|
||||
|
||||
.sub-text {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.5px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.log-img {
|
||||
width: auto;
|
||||
height: 160px;
|
||||
}
|
||||
/* 移动端适配 */
|
||||
@media (max-width: 768px) {
|
||||
.log-img {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
div [style*="display: flex"] {
|
||||
flex-direction: column; /* 改为垂直布局 */
|
||||
padding: 100px;
|
||||
}
|
||||
|
||||
/* 图片容器调整 */
|
||||
div[style*="display: flex"] > div:first-child {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 图片样式调整 */
|
||||
img[src*="logobig.svg"] {
|
||||
/* width: 80% !important;*/
|
||||
max-width: 300px;
|
||||
margin: 0 auto !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
flex: 9;
|
||||
}
|
||||
|
||||
.logo-container,
|
||||
.login-container {
|
||||
padding: 0rem;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
font-size: 66px;
|
||||
}
|
||||
/* 验证码输入容器 */
|
||||
/* .captcha-input {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}*/
|
||||
|
||||
/* 验证码图片 */
|
||||
.captcha-image {
|
||||
width: 120px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.logo-container,
|
||||
.login-container {
|
||||
width: 100%;
|
||||
min-height: auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
max-width: 280px;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* h1 {
|
||||
margin: 10px 0px 50px 0px;
|
||||
}*/
|
||||
|
||||
.login-form {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
378
src/pages/logsetup/index.vue
Normal file
378
src/pages/logsetup/index.vue
Normal file
@@ -0,0 +1,378 @@
|
||||
<template>
|
||||
<div class="user-center-container">
|
||||
<!-- 头部操作按钮 -->
|
||||
<div class="header-actions">
|
||||
<el-button type="primary"
|
||||
:icon="Edit"
|
||||
@click="enableEdit"
|
||||
v-show="!isEdit">
|
||||
编辑信息
|
||||
</el-button>
|
||||
<el-button type="success"
|
||||
:icon="UploadFilled"
|
||||
@click="submitForm"
|
||||
v-show="isEdit && formModified">
|
||||
保存修改
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 用户信息表单 -->
|
||||
<el-form :model="userValue"
|
||||
:rules="rules"
|
||||
ref="formRef"
|
||||
label-width="100px"
|
||||
label-position="right"
|
||||
class="user-form">
|
||||
<el-form-item label="登录名" prop="username">
|
||||
<el-input v-model="userValue.username"
|
||||
disabled="false"
|
||||
placeholder="请输入用户名" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="真实姓名" prop="realname">
|
||||
<el-input v-model="userValue.realname"
|
||||
:disabled="!isEdit"
|
||||
placeholder="请输入真实姓名" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- <el-form-item label="所属公司" prop="comId">
|
||||
<el-select v-model="userValue.comId"
|
||||
:disabled="!isEdit"
|
||||
placeholder="请选择公司">
|
||||
<el-option v-for="company in companies"
|
||||
:key="company.id"
|
||||
:label="company.nameCn"
|
||||
:value="company.id" />
|
||||
</el-select>
|
||||
</el-form-item>-->
|
||||
|
||||
<!-- <el-form-item label="职位" prop="position">
|
||||
<el-select v-model="userValue.position"
|
||||
placeholder="请选择用户类型"
|
||||
:disabled="!isEdit">
|
||||
<el-option v-for="item in positionList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item" />
|
||||
</el-select>
|
||||
</el-form-item>-->
|
||||
|
||||
<el-form-item label="手机号" prop="mobile">
|
||||
<el-input v-model="userValue.mobile"
|
||||
:disabled="!isEdit"
|
||||
placeholder="请输入手机号" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="userValue.email"
|
||||
:disabled="!isEdit"
|
||||
placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="微信号" prop="weixin">
|
||||
<el-input v-model="userValue.weixin"
|
||||
:disabled="!isEdit"
|
||||
placeholder="请输入微信号" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 头像上传组件 -->
|
||||
<el-form-item label="头像" prop="avatar">
|
||||
<el-upload class="avatar-uploader"
|
||||
:disabled="!isEdit"
|
||||
drag
|
||||
accept="image/*"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:on-change="handleAvatarChange"
|
||||
ref="avatarUploadRef">
|
||||
<div v-if="userValue.avatar" class="avatar-preview">
|
||||
<img :src="selectedFile ? avatarPreview : config.Ads + userValue.avatar"
|
||||
class="avatar-image" />
|
||||
<div v-show="isEdit" class="avatar-mask">
|
||||
<el-icon :size="23"><Edit /></el-icon>
|
||||
<div>点击更换头像</div>
|
||||
</div>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-icon class="el-icon--upload"><UploadFilled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
拖拽图片到此 或 <em>点击上传</em>
|
||||
</div>
|
||||
<div class="el-upload__tip">
|
||||
支持JPG/PNG,大小不超过5MB
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, inject, watch } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Plus, Delete, Edit, UploadFilled } from '@element-plus/icons-vue';
|
||||
|
||||
const $http = inject('$http');
|
||||
const ajaxfile = inject('ajaxfile');
|
||||
const config = inject('config');
|
||||
|
||||
// 初始状态定义
|
||||
const isEdit = ref(true);
|
||||
const formModified = ref(false);
|
||||
const formRef = ref(null);
|
||||
const avatarUploadRef = ref(null);
|
||||
const selectedFile = ref(null);
|
||||
const avatarPreview = ref('');
|
||||
const loading = ref(false);
|
||||
const companies = ref([]);
|
||||
const userValue = reactive({
|
||||
id: null,
|
||||
username: "",
|
||||
realname: "",
|
||||
comId: null,
|
||||
company: "",
|
||||
password: "",
|
||||
roleId: null,
|
||||
position: "",
|
||||
weixin: "",
|
||||
email: "",
|
||||
mobile: "",
|
||||
avatar: ""
|
||||
});
|
||||
// 监听表单变化
|
||||
watch(userValue, () => {
|
||||
formModified.value = true;
|
||||
}, { deep: true });
|
||||
|
||||
// 启用编辑
|
||||
const enableEdit = () => {
|
||||
isEdit.value = true;
|
||||
};
|
||||
|
||||
// 头像处理
|
||||
const handleAvatarChange = (file) => {
|
||||
selectedFile.value = file.raw;
|
||||
avatarPreview.value = URL.createObjectURL(file.raw);
|
||||
};
|
||||
// 验证规则
|
||||
const rules = reactive({
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ min: 3, max: 20, message: '长度在3到20个字符', trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, message: '密码长度至少6位', trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
|
||||
]
|
||||
});
|
||||
|
||||
// 获取用户列表
|
||||
const getUser = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const rs = await $http.post('Company/GetComInfo', {
|
||||
IsAll: true,
|
||||
ID: 0,
|
||||
});
|
||||
if (rs.data.isok) {
|
||||
companies.value = rs.data.response;
|
||||
|
||||
const rs1 = await $http.post('Users/GetUserInfo', {
|
||||
IsAll: false,
|
||||
ID: localStorage.getItem("uid"),
|
||||
});
|
||||
if (rs1.data.isok) {
|
||||
// 1. 创建公司映射表(提高查找效率)
|
||||
const companyMap = companies.value.reduce((map, company) => {
|
||||
map[company.id] = company.nameCn;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// 2. 处理用户数据
|
||||
Object.assign(userValue, rs1.data.response);
|
||||
userValue.company = companyMap[userValue.comId];
|
||||
|
||||
console.log(userValue)
|
||||
} else {
|
||||
ElMessage.error(rs1.data.message);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取用户失败');
|
||||
console.error(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
// 表单提交
|
||||
const submitForm = async () => {
|
||||
try {
|
||||
// 表单验证
|
||||
await formRef.value.validate();
|
||||
|
||||
// 头像上传逻辑
|
||||
/* if (selectedFile.value) {
|
||||
let filedata = {
|
||||
File: selectedFile.value,
|
||||
Folder: "face"
|
||||
}
|
||||
const uploadRes = await ajaxfile(filedata);
|
||||
if (uploadRes?.fileName) {
|
||||
userValue.avatar = uploadRes.fileName;
|
||||
}
|
||||
}*/
|
||||
if (selectedFile.value) {
|
||||
const uploadRes = await ajaxfile(filedata);
|
||||
if (uploadRes?.fileName) {
|
||||
userValue.avatar = uploadRes.fileName; // 根据实际接口返回结构调整
|
||||
} else {
|
||||
ElMessage.error('头像上传失败: ' + uploadRes);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
userValue.avatar = userValue.avatar.substring(userValue.avatar.lastIndexOf('/') + 1);
|
||||
}
|
||||
// 更新用户信息
|
||||
const rs = await $http.post('Users/EditUser', userValue);
|
||||
if (rs.data.isok) {
|
||||
ElMessage.success('信息更新成功');
|
||||
isEdit.value = false;
|
||||
formModified.value = false;
|
||||
selectedFile.value = null;
|
||||
avatarUploadRef.value.clearFiles();
|
||||
await getUser(); // 刷新数据
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('保存失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
// 获取身份
|
||||
const positionList = ref([]);
|
||||
const getShengfen = () => {
|
||||
try {
|
||||
const rs = $http.post('ConfigPY/GetSingleValue', {
|
||||
VarName: "用户类型",
|
||||
}).then(rs => {
|
||||
//console.log(JSON.parse(rs.data.response));
|
||||
positionList.value = JSON.parse(rs.data.response)
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
getUser()
|
||||
getShengfen()
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.user-center-container {
|
||||
padding: 20px;
|
||||
max-width: 444px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
}
|
||||
.avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 拖拽区域样式 */
|
||||
.avatar-uploader :deep(.el-upload-dragger) {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
padding: 20px;
|
||||
border-radius: 5%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.avatar-uploader:hover :deep(.el-upload-dragger) {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
/* 头像预览样式 */
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.avatar-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 5%;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.avatar-mask:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 图标和文字样式 */
|
||||
.el-icon--upload {
|
||||
font-size: 36px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.el-upload__text {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-upload__text em {
|
||||
color: var(--el-color-primary);
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.el-upload__tip {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
</style>
|
||||
46
src/pages/radarlog/index.vue
Normal file
46
src/pages/radarlog/index.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, inject, onMounted, computed, watch, onBeforeUnmount } from 'vue';
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { House } from '@element-plus/icons-vue'
|
||||
import qs from 'qs'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const $http = inject('$http')
|
||||
const checkLoginStatus = inject('checkLoginStatus');
|
||||
const isMobile = inject('isMobile');
|
||||
|
||||
|
||||
|
||||
|
||||
// 格式化时间方法
|
||||
const formatTime = (timestamp) => {
|
||||
return dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss');
|
||||
};
|
||||
// 新增方法:格式化时长(分钟)
|
||||
const formatDuration = (ms) => {
|
||||
const sss = Math.floor(ms / 1000);
|
||||
return `${sss}秒`;
|
||||
};
|
||||
onMounted(() => {
|
||||
localStorage.setItem('url', '/radarlog')
|
||||
checkLoginStatus()
|
||||
setFaultRecognition()
|
||||
pickerDate.value = dayjs().format('YYYY-MM-DD');
|
||||
Promise.all([getRooms(), getHostRooms()])
|
||||
.then(() => {
|
||||
//getAllLog();
|
||||
});
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
101
src/router/index.js
Normal file
101
src/router/index.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import Home from '../pages/home/index.vue';
|
||||
import Login from '../pages/login/index.vue';
|
||||
import RadarLog from '../pages/radarlog/index.vue';
|
||||
import LogSetup from '../pages/logsetup/index.vue';
|
||||
import DicManage from '../pages/dicmanage/index.vue';
|
||||
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
// 动态重定向到登录页或主页
|
||||
redirect: () => {
|
||||
const isAuthenticated = localStorage.getItem('TokenT');
|
||||
return isAuthenticated ? '/home' : '/login';
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: '登录',
|
||||
component: Login
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
name: '主页',
|
||||
component: Home,
|
||||
meta: { requiresAuth: true } // 需要认证的路由
|
||||
},
|
||||
{
|
||||
path: '/dicmanage',
|
||||
name: '字典管理',
|
||||
component: DicManage,
|
||||
meta: { requiresAuth: true } // 需要认证的路由
|
||||
},
|
||||
{
|
||||
path: '/radarlog',
|
||||
name: '雷达日志',
|
||||
component: RadarLog,
|
||||
meta: { requiresAuth: true } // 需要认证的路由
|
||||
},
|
||||
{
|
||||
path: '/logsetup',
|
||||
name: '日志设置',
|
||||
component: LogSetup,
|
||||
meta: { requiresAuth: true } // 需要认证的路由
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: '404错误',
|
||||
component: () => import('../pages/404/index.vue') // 404页面
|
||||
},
|
||||
|
||||
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
});
|
||||
|
||||
|
||||
// 路由守卫
|
||||
router.beforeEach((to, from, next) => {
|
||||
//next() //跳过守护
|
||||
const isAuthenticated = localStorage.getItem('AccessibleHotels') // 检查是否登陆过
|
||||
//const username = localStorage.getItem('username') // 获取用户名
|
||||
if (localStorage.getItem("TokenT")) {
|
||||
if (calculateTimeDiff(localStorage.getItem("TokenT")) > 260000) { // 3天内免密登录
|
||||
next('/login')
|
||||
}
|
||||
} else if (to.fullPath != "/login") {
|
||||
next('/login')
|
||||
}
|
||||
|
||||
if (to.meta.requiresAuth && !isAuthenticated) {
|
||||
// 如果需要认证且没有token,则跳转到登录页面
|
||||
next('/login')
|
||||
} /*else if ((to.path == '/usermanage' || to.path == '/scopemanage') && (username != 'Admin' && username != 'MoMoWen')) {
|
||||
// 如果访问的是用户管理页面但用户名不是Admin,则跳转到主页
|
||||
next('/home')
|
||||
} */else {
|
||||
// 其他情况正常放行
|
||||
sessionStorage.setItem('currentRoute', to.fullPath)
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
export default router;
|
||||
|
||||
// 计算时间差
|
||||
const calculateTimeDiff = (targetTimeStr) => {
|
||||
const targetDate = new Date(targetTimeStr);
|
||||
|
||||
// 检查日期是否有效
|
||||
if (isNaN(targetDate.getTime())) {
|
||||
throw new Error("无效的时间格式");
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
return Math.floor((now - targetDate) / 1000);
|
||||
}
|
||||
10
vite.config.js
Normal file
10
vite.config.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import plugin from '@vitejs/plugin-vue';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [plugin()],
|
||||
server: {
|
||||
port: 6789,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user