@ -0,0 +1,14 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{ts,js,vue,css}]
|
||||
indent_size = 2
|
@ -0,0 +1,3 @@
|
||||
VITE_SOME_KEY=456
|
||||
# 打包路径
|
||||
VITE_BASE_URL = ./
|
@ -0,0 +1,3 @@
|
||||
dist
|
||||
node_modules
|
||||
!.prettierrc.js
|
@ -0,0 +1,76 @@
|
||||
{
|
||||
"extends": ["airbnb-base", "prettier", "plugin:@typescript-eslint/recommended", "plugin:vue/essential"],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"jest": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"cy": "readonly"
|
||||
},
|
||||
"plugins": ["vue", "@typescript-eslint"],
|
||||
"parserOptions": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"sourceType": "module",
|
||||
"allowImportExportEverywhere": true,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/ban-ts-ignore": 0,
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
"@typescript-eslint/no-require-imports": 0,
|
||||
"@typescript-eslint/no-var-requires": 0,
|
||||
"@typescript-eslint/prefer-for-of": 0,
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"import/extensions": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"indent": [2, 2],
|
||||
"camelcase": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"new-cap": 0,
|
||||
"no-new": 1,
|
||||
"no-shadow": 0,
|
||||
"no-console": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-confusing-arrow": 0,
|
||||
"no-plusplus": [
|
||||
"error",
|
||||
{
|
||||
"allowForLoopAfterthoughts": true
|
||||
}
|
||||
],
|
||||
"no-param-reassign": 0,
|
||||
"func-style": 0,
|
||||
"prefer-default-export": 0,
|
||||
"max-len": 0,
|
||||
"consistent-return": 0
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.vue"],
|
||||
"rules": {
|
||||
"vue/return-in-computed-property": 1,
|
||||
"vue/order-in-components": 2,
|
||||
"vue/component-name-in-template-casing": [2, "kebab-case"],
|
||||
"vue/require-default-prop": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"import/order": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["src/*", "*.js"],
|
||||
"rules": {
|
||||
"no-var-requires": 0,
|
||||
"no-console": 0,
|
||||
"no-unused-expressions": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"import/order": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
|
||||
|
||||
name: SamWafWeb CI
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.20.4]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm run build --if-present
|
||||
- run: npm test
|
||||
- name: Get version from package.json
|
||||
id: get_version
|
||||
run: |
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Create .zip package
|
||||
run: |
|
||||
zip -r dist.zip dist
|
||||
|
||||
- name: Create .tar.gz package
|
||||
run: |
|
||||
tar -czvf dist.tar.gz dist
|
||||
|
||||
- name: Upload artifacts dist.zip
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist.zip
|
||||
path: |
|
||||
dist.zip
|
||||
- name: Upload artifacts dist.tar.gz
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist.tar.gz
|
||||
path: |
|
||||
dist.tar.gz
|
||||
- name: Create GitHub Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1.1.4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: v${{ env.VERSION }}
|
||||
release_name: v${{ env.VERSION }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
- name: Upload Release Assets dist.zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: dist.zip
|
||||
asset_name: dist.zip
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload Release Assets dist.tar.gz
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: dist.tar.gz
|
||||
asset_name: dist.tar.gz
|
||||
asset_content_type: application/octet-stream
|
@ -0,0 +1,13 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.vscode
|
||||
.history
|
||||
README.html
|
||||
|
||||
.stylelintcache
|
||||
.idea
|
||||
yarn.lock
|
||||
|
@ -0,0 +1,39 @@
|
||||
module.exports = {
|
||||
// 一行最多 120 字符
|
||||
printWidth: 120,
|
||||
// 使用 2 个空格缩进
|
||||
tabWidth: 2,
|
||||
// 不使用缩进符,而使用空格
|
||||
useTabs: false,
|
||||
// 行尾需要有分号
|
||||
semi: true,
|
||||
// 使用单引号
|
||||
singleQuote: true,
|
||||
// 对象的 key 仅在必要时用引号
|
||||
quoteProps: 'as-needed',
|
||||
// jsx 不使用单引号,而使用双引号
|
||||
jsxSingleQuote: false,
|
||||
// 末尾需要有逗号
|
||||
trailingComma: 'all',
|
||||
// 大括号内的首尾需要空格
|
||||
bracketSpacing: true,
|
||||
// jsx 标签的反尖括号需要换行
|
||||
jsxBracketSameLine: false,
|
||||
// 箭头函数,只有一个参数的时候,也需要括号
|
||||
arrowParens: 'always',
|
||||
// 每个文件格式化的范围是文件的全部内容
|
||||
rangeStart: 0,
|
||||
rangeEnd: Infinity,
|
||||
// 不需要写文件开头的 @prettier
|
||||
requirePragma: false,
|
||||
// 不需要自动在文件开头插入 @prettier
|
||||
insertPragma: false,
|
||||
// 使用默认的折行标准
|
||||
proseWrap: 'preserve',
|
||||
// 根据显示样式决定 html 要不要折行
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
// vue 文件中的 script 和 style 内不用缩进
|
||||
vueIndentScriptAndStyle: false,
|
||||
// 换行符使用 lf
|
||||
endOfLine: 'lf',
|
||||
};
|
@ -0,0 +1,8 @@
|
||||
# .stylelintignore
|
||||
# 旧的不需打包的样式库
|
||||
*.min.css
|
||||
|
||||
# 其他类型文件
|
||||
*.js
|
||||
*.jpg
|
||||
*.woff
|
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,33 @@
|
||||
# SamWafWeb
|
||||
|
||||
## QuickStart
|
||||
|
||||
1.
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
2.
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3.
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
|
||||
# License
|
||||
SamWaf is licensed under the Apache License 2.0. Refer to [LICENSE](./LICENSE) for more details.
|
||||
|
||||
For third-party software usage notice:
|
||||
|
||||
TDesign (https://github.com/Tencent/tdesign-vue-starter).
|
||||
|
||||
# Contribution
|
||||
Thanks for the following contributors!
|
||||
|
||||
<a href="https://github.com/samwafgo/SamWafWeb/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=samwafgo/SamWafWeb" />
|
||||
</a>
|
@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
echo.
|
||||
echo [信息] 使用 Vue CLI 命令运行 Web 工程。
|
||||
echo.
|
||||
|
||||
%~d0
|
||||
cd %~dp0
|
||||
|
||||
cd ..
|
||||
npm run dev
|
||||
|
||||
pause
|
@ -0,0 +1,15 @@
|
||||
# 选择一个 Base 镜像
|
||||
FROM node:12
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /space
|
||||
|
||||
# 将 by 中的文件列表 COPY 过来
|
||||
COPY . .
|
||||
|
||||
# 根据 COPY 过来的文件进行依赖的安装
|
||||
RUN npm i
|
||||
|
||||
# 设置好需要的环境变量
|
||||
ENV NODE_PATH=/space/node_modules
|
||||
|
@ -0,0 +1 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
@ -0,0 +1,20 @@
|
||||
server {
|
||||
if ($request_method = HEAD) {
|
||||
return 200;
|
||||
}
|
||||
|
||||
location / {
|
||||
alias /usr/share/nginx/html/;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
error_log /var/log/nginx/error.log error;
|
||||
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 177 KiB |
@ -0,0 +1,13 @@
|
||||
// 通用声明
|
||||
declare type ClassName = { [className: string]: any } | ClassName[] | string;
|
||||
|
||||
declare interface ImportMeta {
|
||||
env: {
|
||||
MODE: 'mock' | 'development' | 'test' | 'release';
|
||||
};
|
||||
}
|
||||
|
||||
declare module '*.svg' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="robots" content="noindex">
|
||||
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
window.global = window;
|
||||
</script>
|
||||
</html>
|
@ -0,0 +1,13 @@
|
||||
import Vue, { VNode } from 'vue';
|
||||
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
type Element = VNode;
|
||||
type ElementClass = Vue;
|
||||
interface IntrinsicElements {
|
||||
[elem: string]: any;
|
||||
}
|
||||
type IntrinsicAttributes = any;
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
{
|
||||
"name": "localwaf",
|
||||
"version": "1.3.64",
|
||||
"scripts": {
|
||||
"dev:mock": "vite --open --mode mock",
|
||||
"dev": "vite --open --mode development",
|
||||
"dev:linux": "vite --mode development",
|
||||
"build:test": "vite build --mode test",
|
||||
"build": "vite build --mode release",
|
||||
"site:preview": "npm run build && cp -r dist _site",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint --ext .vue,.js,.jsx,.ts,.tsx ./ --max-warnings 0",
|
||||
"lint:fix": "eslint --ext .vue,.js,jsx,.ts,.tsx ./ --max-warnings 0 --fix",
|
||||
"stylelint": "stylelint src/**/*.{html,vue,sass,less}",
|
||||
"stylelint:fix": "stylelint --cache --fix src/**/*.{html,vue,vss,sass,less}",
|
||||
"prepare": "node -e \"if(require('fs').existsSync('.git')){process.exit(1)}\" || is-ci || husky install",
|
||||
"test": "echo \"no test specified,work in process\"",
|
||||
"test:coverage": "echo \"no test:coverage specified,work in process\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"axios": "^0.27.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.10.8",
|
||||
"dompurify": "^3.2.4",
|
||||
"echarts": "~5.1.2",
|
||||
"echarts-wordcloud": "^2.0.0",
|
||||
"marked": "^15.0.7",
|
||||
"nprogress": "^0.2.0",
|
||||
"qrcode.vue": "^1.7.0",
|
||||
"tdesign-icons-vue": "^0.2.5",
|
||||
"tdesign-vue": "^1.10.5",
|
||||
"tvision-color": "~1.6.0",
|
||||
"typescript": "^4.2.4",
|
||||
"uuid": "^9.0.0",
|
||||
"vue": "~2.6.14",
|
||||
"vue-baidu-map": "^0.21.22",
|
||||
"vue-clipboard2": "^0.3.1",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-i18n": "^8.28.2",
|
||||
"vue-meta": "^2.4.0",
|
||||
"vue-router": "^3.5.1",
|
||||
"vuex": "^3.6.2",
|
||||
"vuex-router-sync": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.0.3",
|
||||
"@commitlint/config-conventional": "^17.1.0",
|
||||
"@types/vue-color": "^2.4.3",
|
||||
"@typescript-eslint/eslint-plugin": "^4.19.0",
|
||||
"@typescript-eslint/parser": "^4.19.0",
|
||||
"commitizen": "^4.2.3",
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-vue": "^7.8.0",
|
||||
"husky": "^8.0.1",
|
||||
"less": "^4.1.0",
|
||||
"lint-staged": "^13.0.3",
|
||||
"mockjs": "^1.1.0",
|
||||
"prettier": "^2.6.0",
|
||||
"stylelint": "~13.13.1",
|
||||
"stylelint-config-prettier": "~9.0.3",
|
||||
"stylelint-less": "1.0.5",
|
||||
"stylelint-order": "~4.1.0",
|
||||
"vite": "^2.7.10",
|
||||
"vite-plugin-mock": "^2.3.0",
|
||||
"vite-plugin-require-transform": "^1.0.4",
|
||||
"vite-plugin-theme": "^0.8.1",
|
||||
"vite-plugin-vue2": "^2.0.1",
|
||||
"vite-plugin-vue2-svg": "~0.3.0",
|
||||
"vue-template-compiler": "~2.6.14"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"prepare-commit-msg": "exec < /dev/tty && git cz --hook || true",
|
||||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,vue,ts,tsx}": [
|
||||
"prettier --write",
|
||||
"npm run lint:fix",
|
||||
"git add ."
|
||||
],
|
||||
"*.{html,vue,vss,sass,less}": [
|
||||
"npm run stylelint:fix",
|
||||
"git add ."
|
||||
]
|
||||
},
|
||||
"description": "localwaf"
|
||||
}
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,2 @@
|
||||
User-agent:*
|
||||
Disallow:/
|
@ -0,0 +1,5 @@
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue;
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<router-view :class="[mode]" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import config from '@/config/style';
|
||||
import websocket from "@/utils/websocket.js";
|
||||
import { DialogPlugin } from 'tdesign-vue';
|
||||
import {AesDecrypt} from './utils/usuallytool'
|
||||
const env = import.meta.env.MODE || 'development';
|
||||
|
||||
export default Vue.extend({
|
||||
computed: {
|
||||
mode() {
|
||||
return this.$store.getters['setting/mode'];
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ws: null, // ws
|
||||
disConnectTimer: null, // 断连计时
|
||||
mydialog: null,
|
||||
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('setting/changeTheme', { ...config });
|
||||
},
|
||||
created() {
|
||||
this.initWebSocket();
|
||||
},
|
||||
methods:{
|
||||
initWebSocket() {
|
||||
console.log("log",window.location.host)
|
||||
if(!this.ws) {
|
||||
// url
|
||||
let url = env=="development"? "ws://127.0.0.1:26666/samwaf/ws" : "ws://"+window.location.host+"/samwaf/ws"
|
||||
this.ws = websocket.useWebSocket(
|
||||
url, // url
|
||||
localStorage.getItem("access_token"),
|
||||
this.wsOnOpen, // 链接回调
|
||||
this.wsOnMessage, // 连接成功后处理接口返回信息
|
||||
this.wsOnClose, // 关闭回调
|
||||
this.wsOnError, // 消息通知错误回调
|
||||
[], // 发送后台的心跳包参数
|
||||
null, // 给后台传送心跳包的间隔时间
|
||||
true, // 是否断掉立即重连
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
wsOnOpen() {
|
||||
console.log('开始连接')
|
||||
},
|
||||
wsOnError(e) {
|
||||
console.log(e,'消息通知错误回调,重新连接')
|
||||
this.ws.close();
|
||||
this.ws = null;
|
||||
this.initWebSocket();
|
||||
},
|
||||
wsOnMessage(e) {
|
||||
let wsData = JSON.parse(e.data)
|
||||
if(wsData.msg_code=="200"){
|
||||
console.log('接口返回信息',wsData)
|
||||
|
||||
let msgDataEnstr =wsData.msg_data
|
||||
|
||||
console.log('msgDataEnstr',msgDataEnstr)
|
||||
let tmpSrcContent = AesDecrypt(msgDataEnstr)
|
||||
console.log('tmpSrcContent',tmpSrcContent)
|
||||
let msgData = JSON.parse(tmpSrcContent)
|
||||
console.log('msgData',msgData)
|
||||
wsData.msg_data = msgData
|
||||
if(wsData.msg_cmd_type=="RELOAD_PAGE"){
|
||||
if(this.mydialog){
|
||||
this.mydialog.hide()
|
||||
this.mydialog =null
|
||||
}
|
||||
this.mydialog = this.$dialog({
|
||||
header: wsData.msg_data.message_type,
|
||||
body: wsData.msg_data.message_data,
|
||||
className: 't-dialog-new-class1 t-dialog-new-class2',
|
||||
style: 'color: rgba(0, 0, 0, 0.6)',
|
||||
confirmBtn:'确认并刷新',
|
||||
onConfirm: ({ e }) => {
|
||||
window.location.reload()
|
||||
this.mydialog.hide();
|
||||
},
|
||||
});
|
||||
return
|
||||
}else if(wsData.msg_cmd_type=="DOWNLOAD_LOG"){
|
||||
let token =localStorage.getItem("access_token")? localStorage.getItem("access_token"):""
|
||||
//下载连接
|
||||
let downloadUrl = env=="development"? "http://127.0.0.1:26666/samwaf/waflog/attack/download" : "http://"+window.location.host+"/samwaf/waflog/attack/download"
|
||||
downloadUrl = downloadUrl +"?X-Token="+token
|
||||
console.log(downloadUrl)
|
||||
window.open(downloadUrl)
|
||||
}
|
||||
this.$store.commit('notification/addMsgData', wsData.msg_data);
|
||||
}else if(wsData.msg_code=="-999"){
|
||||
Object.keys(localStorage).forEach(key => {
|
||||
if (key !== "lang") {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
});
|
||||
console.log("鉴权失败")
|
||||
}
|
||||
},
|
||||
wsOnClose() {
|
||||
console.log('关闭')
|
||||
// 意外关闭之后重新连接
|
||||
if(!this.disConnectTimer) {
|
||||
//this.ws.close();
|
||||
this.ws = null;
|
||||
this.disConnectTimer = setTimeout(() => {
|
||||
this.initWebSocket()
|
||||
this.disConnectTimer = null
|
||||
}, 10000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
var ws = new WebSocket("ws://127.0.0.1:26666/samwaf/ws",[localStorage.getItem("access_token")]);
|
||||
//连接打开时触发
|
||||
ws.onopen = function(evt) {
|
||||
console.log("Connection open ...");
|
||||
ws.send("ping");
|
||||
};
|
||||
//接收到消息时触发
|
||||
ws.onmessage = function(evt) {
|
||||
console.log("Received Message: " + evt.data);
|
||||
};
|
||||
//连接关闭时触发
|
||||
ws.onclose = function(evt) {
|
||||
console.log("Connection closed.");
|
||||
}; */
|
||||
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.tdesign-starter-side-nav-logo-tdesign-logo{
|
||||
padding: 0 0px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,27 @@
|
||||
import request from '@/utils/request'
|
||||
//查询所有账号列表
|
||||
export function account_list_api(data) {
|
||||
return request({
|
||||
url: 'account/list',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//查询所有账号操作日志列表
|
||||
export function account_log_list_api(params) {
|
||||
return request({
|
||||
url: 'account_log/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
// 重置2Fa
|
||||
export function account_reset_2fa_api(data) {
|
||||
return request({
|
||||
url: 'account/resetotp',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
import request from '@/utils/request'
|
||||
//查看抵御CC攻击列表
|
||||
export function wafAntiCCListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/anticc/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除抵御CC攻击
|
||||
export function wafAntiCCDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/anticc/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑抵御CC攻击
|
||||
export function wafAntiCCEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/anticc/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加抵御CC攻击
|
||||
export function wafAntiCCAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/anticc/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细抵御CC攻击
|
||||
export function wafAntiCCDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/anticc/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 封禁ip列表
|
||||
* @param params
|
||||
*/
|
||||
export function wafAntiCCBanIPListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/anticc/baniplist',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除ip方法
|
||||
* @param params
|
||||
*/
|
||||
export function wafAntiCCRemoveBanIpApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/anticc/removebanip',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 批量任务配置-列表
|
||||
export function batchTaskListApi(params) {
|
||||
return request({
|
||||
url: '/batch_task/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 批量任务配置 - 删除
|
||||
export function batchTaskDelApi(params) {
|
||||
return request({
|
||||
url: '/batch_task/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// 批量任务配置 - 编辑
|
||||
export function batchTaskEditApi(params) {
|
||||
return request({
|
||||
url: '/batch_task/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 批量任务配置 - 添加
|
||||
export function batchTaskAddApi(params) {
|
||||
return request({
|
||||
url: '/batch_task/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 批量任务配置 - 详情
|
||||
export function batchTaskDetailApi(params) {
|
||||
return request({
|
||||
url: '/batch_task/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// 批量任务配置 - 手工触发
|
||||
export function batchTaskManualApi(params) {
|
||||
return request({
|
||||
url: '/batch_task/manual',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//列表
|
||||
export function wafBlockingPageListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/blockingpage/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除
|
||||
export function wafBlockingPageDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/blockingpage/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑
|
||||
export function wafBlockingPageEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/blockingpage/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加
|
||||
export function wafBlockingPageAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/blockingpage/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细
|
||||
export function wafBlockingPageDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/blockingpage/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
//查看控制中心列表
|
||||
export function centerListApi(params) {
|
||||
return request({
|
||||
url: '/center/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细控制中心详情
|
||||
export function centerDetailApi(params) {
|
||||
return request({
|
||||
url: '/center/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
|
||||
//导出excel文件
|
||||
export function export_api(params) {
|
||||
return request({
|
||||
url: 'export',
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
timeout: 20000,
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
import request from '@/utils/request'
|
||||
//查询所有主机列表
|
||||
export function allhost(params) {
|
||||
return request({
|
||||
url: 'wafhost/host/allhost',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
//通过主机Code查询所有主机域名信息
|
||||
export function alldomainbyhostcode(params) {
|
||||
return request({
|
||||
url: 'wafhost/host/alldomainbyhostcode',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
//查询主机列表
|
||||
export function hostlist(data) {
|
||||
return request({
|
||||
url: 'wafhost/host/list',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//更改防护状态
|
||||
export function changeGuardStatus(params) {
|
||||
return request({
|
||||
url: 'wafhost/host/guardstatus',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//更改启动状态
|
||||
export function changeStartStatus(params) {
|
||||
return request({
|
||||
url: 'wafhost/host/startstatus',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//加载详情
|
||||
export function getHostDetail(params) {
|
||||
return request({
|
||||
url: 'wafhost/host/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//删除主机
|
||||
export function delHost(params) {
|
||||
return request({
|
||||
url: 'wafhost/host/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
//添加主机
|
||||
export function addHost(data) {
|
||||
return request({
|
||||
url: 'wafhost/host/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
//编辑主机
|
||||
export function editHost(data) {
|
||||
return request({
|
||||
url: 'wafhost/host/edit',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
//修改所有主机的防护状态
|
||||
export function modifyAllGuardStatus(data) {
|
||||
return request({
|
||||
url: 'wafhost/host/modfiyallstatus',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//列表
|
||||
export function wafHttpAuthBaseListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/httpauthbase/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除
|
||||
export function wafHttpAuthBaseDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/httpauthbase/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑
|
||||
export function wafHttpAuthBaseEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/httpauthbase/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加
|
||||
export function wafHttpAuthBaseAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/httpauthbase/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细
|
||||
export function wafHttpAuthBaseDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/httpauthbase/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//查看IP白名单列表
|
||||
export function wafIPBlockListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipblock/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除IP黑名单
|
||||
export function wafIPBlockDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipblock/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑IP黑名单
|
||||
export function wafIPBlockEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipblock/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加IP黑名单
|
||||
export function wafIPBlockAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipblock/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细IP黑名单
|
||||
export function wafIPBlockDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipblock/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//查看IP白名单列表
|
||||
export function wafIPWhiteListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipwhite/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除IP白名单
|
||||
export function wafIPWhiteDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipwhite/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑IP白名单
|
||||
export function wafIPWhiteEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipwhite/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加IP白名单
|
||||
export function wafIPWhiteAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipwhite/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细IP白名单
|
||||
export function wafIPWhiteDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ipwhite/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//查看隐私保护URL列表
|
||||
export function wafLdpURLListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ldpurl/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除隐私保护URL
|
||||
export function wafLdpURLDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ldpurl/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑隐私保护URL
|
||||
export function wafLdpURLEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ldpurl/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加隐私保护URL
|
||||
export function wafLdpURLAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ldpurl/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细隐私保护URL
|
||||
export function wafLdpURLDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/ldpurl/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 授权文件
|
||||
*/
|
||||
|
||||
//获取授权详情
|
||||
export function getLicenseDetailApi(params) {
|
||||
return request({
|
||||
url: '/license/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//确认刚刚输入的文件
|
||||
export function confirmLicenseApi(params) {
|
||||
return request({
|
||||
url: '/license/confirm',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//查看负载列表
|
||||
export function wafLoadBalanceListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/loadbalance/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除负载
|
||||
export function wafLoadBalanceDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/loadbalance/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑负载
|
||||
export function wafLoadBalanceEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/loadbalance/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加负载
|
||||
export function wafLoadBalanceAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/loadbalance/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细负载
|
||||
export function wafLoadBalanceDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/loadbalance/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import request from '@/utils/request'
|
||||
//登录
|
||||
export function loginapi(params) {
|
||||
return request({
|
||||
url: 'public/login',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
//注销
|
||||
export function logoutapi(params) {
|
||||
return request({
|
||||
url: 'logout',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
//查看一键修改记录列表
|
||||
export function wafOneKeyModListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/onekeymod/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除一键修改记录
|
||||
export function wafOneKeyModDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/onekeymod/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//详细一键修改记录
|
||||
export function wafOneKeyModDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/onekeymod/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//触发一键修改
|
||||
export function wafDoOneKeyModApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/onekeymod/doModify',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
import request from '@/utils/request'
|
||||
//初始化
|
||||
export function wafOtpInitApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/otp/init',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// 绑定OTP
|
||||
export function wafOtpBindApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/otp/bind',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
//解绑OTP
|
||||
export function wafOtpUnBindApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/otp/unbind',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//查看规则列表
|
||||
export function wafRuleListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/rule/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除规则
|
||||
export function wafRuleDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/rule/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑规则
|
||||
export function wafRuleEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/rule/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加规则
|
||||
export function wafRuleAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/rule/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细规则
|
||||
export function wafRuleDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/rule/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//Sensitive Manage
|
||||
export function wafSensitiveListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sensitive/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//Delete Sensitive
|
||||
export function wafSensitiveDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sensitive/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//Edit Sensitive
|
||||
export function wafSensitiveEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sensitive/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//Add Sensitive
|
||||
export function wafSensitiveAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sensitive/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//Detail Sensitive
|
||||
export function wafSensitiveDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sensitive/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
import request from '@/utils/request'
|
||||
//列表
|
||||
export function wafSslExpireListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslexpire/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除
|
||||
export function wafSslExpireDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslexpire/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑
|
||||
export function wafSslExpireEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslexpire/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加
|
||||
export function wafSslExpireAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslexpire/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细
|
||||
export function wafSslExpireDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslexpire/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//发起检测
|
||||
export function wafSslExpireNowCheckApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslexpire/nowcheck',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//同步已有域名
|
||||
export function wafSslExpireSyncHostApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslexpire/sync_host',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// SSL 配置管理 - 获取 SSL 配置列表
|
||||
export function sslConfigListApi(params) {
|
||||
return request({
|
||||
url: '/sslconfig/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 配置管理 - 删除 SSL 配置
|
||||
export function sslConfigDelApi(params) {
|
||||
return request({
|
||||
url: '/sslconfig/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 配置管理 - 编辑 SSL 配置
|
||||
export function sslConfigEditApi(params) {
|
||||
return request({
|
||||
url: '/sslconfig/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 配置管理 - 添加 SSL 配置
|
||||
export function sslConfigAddApi(params) {
|
||||
return request({
|
||||
url: '/sslconfig/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 配置管理 - 获取 SSL 配置详情
|
||||
export function sslConfigDetailApi(params) {
|
||||
return request({
|
||||
url: '/sslconfig/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// SSL 订单列表
|
||||
export function sslOrderListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslorder/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 订单 - 删除
|
||||
export function sslOrderDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslorder/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 订单 - 编辑
|
||||
export function sslOrderEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslorder/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 订单 - 添加
|
||||
export function sslOrderAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslorder/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// SSL 订单 - 获取详情
|
||||
export function sslOrderDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/sslorder/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
import request from '@/utils/request'
|
||||
//查询顶部的汇总天信息
|
||||
export function wafstatsumdayapi(params) {
|
||||
return request({
|
||||
url: 'wafstatsumday',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//查询周期区间的攻击和正常信息
|
||||
export function wafstatsumdayrangeapi(params) {
|
||||
return request({
|
||||
url: 'wafstatsumdayrange',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//查询周期区间的IP攻击和正常信息
|
||||
export function wafstatsumdaytopiprangeapi(params) {
|
||||
return request({
|
||||
url: 'wafstatsumdaytopiprange',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//首页获取基本信息
|
||||
export function wafStatSysinfoapi(params) {
|
||||
return request({
|
||||
url: 'statsysinfo',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//首页获取运行基本信息
|
||||
export function wafStatRuntimeSysinfoapi(params) {
|
||||
return request({
|
||||
url: 'statrumtimesysinfo',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//【数据分析】查询周期区间国家级别攻击和正常信息
|
||||
export function wafanalysisdaycountryrange(params) {
|
||||
return request({
|
||||
url: 'wafanalysisdaycountryrange',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
//查询版本信息
|
||||
export function SysVersionApi(params) {
|
||||
return request({
|
||||
url: 'sysinfo/version',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
//查询是否需要升级版本信息
|
||||
export function CheckVersionApi(params) {
|
||||
return request({
|
||||
url: 'sysinfo/checkversion',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
//升级
|
||||
export function DoUpdateApi(params) {
|
||||
return request({
|
||||
url: 'sysinfo/update',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
//查询所有系统操作日志列表
|
||||
export function sys_log_list_api(params) {
|
||||
return request({
|
||||
url: 'sys_log/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
//查询所有系统配置列表
|
||||
export function system_config_list_api(data) {
|
||||
return request({
|
||||
url: 'systemconfig/list',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
import request from '@/utils/request'
|
||||
//列表
|
||||
export function wafTaskListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/task/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除
|
||||
export function wafTaskDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/task/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑
|
||||
export function wafTaskEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/task/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加
|
||||
export function wafTaskAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/task/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细
|
||||
export function wafTaskDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/task/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//手工执行
|
||||
export function wafTaskManualExecApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/task/manual_exec',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//查看URL黑名单列表
|
||||
export function wafURLBlockListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlblock/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除URL黑名单
|
||||
export function wafURLBlockDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlblock/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑URL黑名单
|
||||
export function wafURLBlockEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlblock/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加URL黑名单
|
||||
export function wafURLBlockAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlblock/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细URL黑名单
|
||||
export function wafURLBlockDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlblock/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request'
|
||||
//查看URL白名单列表
|
||||
export function wafURLWhiteListApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlwhite/list',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//删除URL白名单
|
||||
export function wafURLWhiteDelApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlwhite/del',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//编辑URL白名单
|
||||
export function wafURLWhiteEditApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlwhite/edit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//添加URL白名单
|
||||
export function wafURLWhiteAddApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlwhite/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
//详细URL白名单
|
||||
export function wafURLWhiteDetailApi(params) {
|
||||
return request({
|
||||
url: '/wafhost/urlwhite/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
import request from '@/utils/request'
|
||||
//查询攻击日志列表
|
||||
export function attacklogList(params) {
|
||||
return request({
|
||||
url: '/waflog/attacklog/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
//查询存档日志库列表
|
||||
export function allsharedblist(params) {
|
||||
return request({
|
||||
url: 'waflog/attack/allsharedb',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
//导出json数据
|
||||
export function exportlog(data) {
|
||||
return request({
|
||||
url: 'waflog/attack/export',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
//下载已经生成好的数据
|
||||
export function downloadlog() {
|
||||
return request({
|
||||
url: 'waflog/attack/download',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
//查看日志详情
|
||||
export function geWebLogDetail(params) {
|
||||
return request({
|
||||
url: 'waflog/attack/detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
// 复制脱敏后数据
|
||||
export function getHeaderCopyDetail(params) {
|
||||
return request({
|
||||
url: 'waflog/attack/httpcopymask',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
// 危险ip列表
|
||||
export function attackIpListApi(data) {
|
||||
return request({
|
||||
url: 'waflog/attack/attackiplist',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//查询攻击iptag列表
|
||||
export function allattacktaglist(params) {
|
||||
return request({
|
||||
url: 'waflog/attack/alliptag',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 789 KiB |
After Width: | Height: | Size: 972 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 979 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 958 B |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,4 @@
|
||||
// bus.js
|
||||
import Vue from 'vue';
|
||||
const bus = new Vue();
|
||||
export default bus
|
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div :style="style" class="color-container" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { getBrandColor } from '@/config/color';
|
||||
|
||||
const panelColor =
|
||||
'conic-gradient(from 90deg at 50% 50%, #FF0000 -19.41deg, #FF0000 18.76deg, #FF8A00 59.32deg, #FFE600 99.87deg, #14FF00 141.65deg, #00A3FF 177.72deg, #0500FF 220.23deg, #AD00FF 260.13deg, #FF00C7 300.69deg, #FF0000 340.59deg, #FF0000 378.76deg)';
|
||||
|
||||
export default {
|
||||
name: 'Color',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
style() {
|
||||
const { colorList } = this.$store.state.setting;
|
||||
return {
|
||||
background: this.value !== 'dynamic' ? getBrandColor(this.value, colorList)['--td-brand-color'] : panelColor,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.color-container {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 负载均衡模式 -->
|
||||
<div v-if="isLoadBalance">
|
||||
<load-balance-status
|
||||
v-if="healthyStatus && healthyStatus.length > 0"
|
||||
:healthyStatusList="healthyStatus"
|
||||
/>
|
||||
<t-tag v-else theme="default" variant="light">{{ $t('page.host.healthy_status_unknown') }}</t-tag>
|
||||
</div>
|
||||
|
||||
<!-- 单服务器模式 -->
|
||||
<div v-else>
|
||||
<single-server-status
|
||||
v-if="healthyStatus && healthyStatus.length > 0"
|
||||
:healthyStatus="healthyStatus[0]"
|
||||
/>
|
||||
<t-tag v-else theme="default" variant="light">{{ $t('page.host.healthy_status_unknown') }}</t-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SingleServerStatus from './SingleServerStatus.vue';
|
||||
import LoadBalanceStatus from './LoadBalanceStatus.vue';
|
||||
|
||||
export default {
|
||||
name: 'HealthStatus',
|
||||
components: {
|
||||
SingleServerStatus,
|
||||
LoadBalanceStatus
|
||||
},
|
||||
props: {
|
||||
healthyStatus: {
|
||||
type: [Array, Object],
|
||||
default: () => []
|
||||
},
|
||||
isLoadBalance: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<div class="health-status-container">
|
||||
<t-tooltip placement="top" theme="light">
|
||||
|
||||
<t-tag
|
||||
theme="primary"
|
||||
:variant="hasUnhealthyServer ? 'dark' : 'light'"
|
||||
:style="{
|
||||
backgroundColor: hasUnhealthyServer ? '#fbe9e7' : '#e8f4ff',
|
||||
color: hasUnhealthyServer ? '#e34d59' : '#00a870'
|
||||
}"
|
||||
>
|
||||
{{ unhealthyCount === 0 ? $t('page.host.healthy_status_normal') : `${healthyStatusList.length}/${unhealthyCount}` }}
|
||||
|
||||
</t-tag>
|
||||
<template #content>
|
||||
<div class="health-status-tooltip">
|
||||
<div class="tooltip-content-wrapper">
|
||||
<!-- 每个服务器的详细信息 -->
|
||||
<div v-for="(status, index) in healthyStatusList" :key="index" class="server-section">
|
||||
<div class="server-title" :class="status.IsHealthy ? 'healthy-text' : 'unhealthy-text'">
|
||||
{{ getServerInfo(status, index) }}: {{ status.IsHealthy ? $t('page.host.healthy_status_normal') : $t('page.host.healthy_status_abnormal') }}
|
||||
</div>
|
||||
<table class="status-table">
|
||||
<tr>
|
||||
<td class="label">{{ $t('page.host.healthy_status_detail.check_time') }}</td>
|
||||
<td class="value">{{ formatTime(status.LastCheckTime) }}</td>
|
||||
</tr>
|
||||
<tr v-if="!status.IsHealthy">
|
||||
<td class="label">{{ $t('page.host.healthy_status_detail.success_cnt') }}</td>
|
||||
<td class="value">{{ status.SuccessCount || 0 }}</td>
|
||||
</tr>
|
||||
<tr v-if="!status.IsHealthy">
|
||||
<td class="label">{{ $t('page.host.healthy_status_detail.failure_cnt') }}</td>
|
||||
<td class="value">{{ status.FailCount }}</td>
|
||||
</tr>
|
||||
<tr v-if="!status.IsHealthy && status.LastErrorReason">
|
||||
<td class="label error-text">{{ $t('page.host.healthy_status_detail.error_reason') }}</td>
|
||||
<td class="value error-text">{{ status.LastErrorReason }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</t-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'LoadBalanceStatus',
|
||||
props: {
|
||||
healthyStatusList: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasUnhealthyServer() {
|
||||
return this.healthyStatusList.some(status => !status.IsHealthy);
|
||||
},
|
||||
unhealthyCount() {
|
||||
return this.healthyStatusList.filter(status => !status.IsHealthy).length;
|
||||
},
|
||||
healthyCount() {
|
||||
return this.healthyStatusList.filter(status => status.IsHealthy).length;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatTime(time) {
|
||||
return new Date(time).toLocaleString();
|
||||
},
|
||||
getServerInfo(status, index) {
|
||||
return `${status.BackIP}:${status.BackPort}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.health-status-container {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.health-status-tooltip {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.tooltip-content-wrapper {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
padding-right: 5px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #ccc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 4px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.server-section {
|
||||
margin-top: 16px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px dashed #ddd;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.server-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.status-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding: 6px;
|
||||
font-weight: 500;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.value {
|
||||
padding: 6px;
|
||||
text-align: right;
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.healthy-text {
|
||||
color: #00a870;
|
||||
}
|
||||
|
||||
.unhealthy-text {
|
||||
color: #e34d59;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: #e34d59;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div class="health-status-container">
|
||||
<t-tooltip placement="top" theme="light">
|
||||
<t-tag
|
||||
theme="primary"
|
||||
:variant="healthyStatus.IsHealthy ? 'light' : 'dark'"
|
||||
:style="{
|
||||
backgroundColor: healthyStatus.IsHealthy ? '#e8f4ff' : '#fbe9e7',
|
||||
color: healthyStatus.IsHealthy ? '#00a870' : '#e34d59'
|
||||
}"
|
||||
>
|
||||
{{ healthyStatus.IsHealthy ? $t('page.host.healthy_status_normal') : $t('page.host.healthy_status_abnormal') }}
|
||||
</t-tag>
|
||||
<template #content>
|
||||
<div class="health-status-tooltip">
|
||||
<table class="status-table">
|
||||
<tr>
|
||||
<td class="label">{{ $t('page.host.healthy_status_detail.check_time') }}</td>
|
||||
<td class="value">{{ formatTime(healthyStatus.LastCheckTime) }}</td>
|
||||
</tr>
|
||||
<tr v-if="!healthyStatus.IsHealthy">
|
||||
<td class="label">{{ $t('page.host.healthy_status_detail.success_cnt') }}</td>
|
||||
<td class="value">{{ healthyStatus.SuccessCount || 0 }}</td>
|
||||
</tr>
|
||||
<tr v-if="!healthyStatus.IsHealthy">
|
||||
<td class="label">{{ $t('page.host.healthy_status_detail.failure_cnt') }}</td>
|
||||
<td class="value">{{ healthyStatus.FailCount }}</td>
|
||||
</tr>
|
||||
<tr v-if="!healthyStatus.IsHealthy && healthyStatus.LastErrorReason">
|
||||
<td class="label error-text">{{ $t('page.host.healthy_status_detail.error_reason') }}</td>
|
||||
<td class="value error-text">{{ healthyStatus.LastErrorReason }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
</t-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SingleServerStatus',
|
||||
props: {
|
||||
healthyStatus: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatTime(time) {
|
||||
return new Date(time).toLocaleString();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.health-status-container {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.health-status-tooltip {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.status-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding: 6px;
|
||||
font-weight: 500;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.value {
|
||||
padding: 6px;
|
||||
text-align: right;
|
||||
width: 60%;
|
||||
}
|
||||
.healthy-text {
|
||||
color: #00a870;
|
||||
}
|
||||
.unhealthy-text {
|
||||
color: #e34d59;
|
||||
}
|
||||
.error-text {
|
||||
color: #e34d59;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<t-card theme="poster2">
|
||||
<template #avatar>
|
||||
<t-avatar size="56px">
|
||||
<template #icon>
|
||||
<shop-icon v-if="product.type === 1" />
|
||||
<calendar-icon v-if="product.type === 2" />
|
||||
<service-icon v-if="product.type === 3" />
|
||||
<user-avatar-icon v-if="product.type === 4" />
|
||||
<laptop-icon v-if="product.type === 5" />
|
||||
</template>
|
||||
</t-avatar>
|
||||
</template>
|
||||
<template #status>
|
||||
<t-tag :theme="product.isSetup ? 'success' : 'default'" :disabled="!product.isSetup">{{
|
||||
product.isSetup ? '已启用' : '已停用'
|
||||
}}</t-tag>
|
||||
</template>
|
||||
<template #content>
|
||||
<p class="list-card-item_detail--name">{{ product.name }}</p>
|
||||
<p class="list-card-item_detail--desc">{{ product.description }}</p>
|
||||
</template>
|
||||
<template #footer>
|
||||
<t-avatar-group cascading="left-up" :max="2">
|
||||
<t-avatar>{{ typeMap[product.type - 1] }}</t-avatar>
|
||||
<t-avatar
|
||||
><template #icon>
|
||||
<add-icon />
|
||||
</template>
|
||||
</t-avatar>
|
||||
</t-avatar-group>
|
||||
</template>
|
||||
<template #actions>
|
||||
<t-dropdown
|
||||
:disabled="!product.isSetup"
|
||||
trigger="click"
|
||||
:options="[
|
||||
{
|
||||
content: '管理',
|
||||
value: 'manage',
|
||||
onClick: () => handleManageProduct(product),
|
||||
},
|
||||
{
|
||||
content: '删除',
|
||||
value: 'delete',
|
||||
onClick: () => handleDeleteItem(product),
|
||||
},
|
||||
]"
|
||||
>
|
||||
<t-button theme="default" :disabled="!product.isSetup" shape="square" variant="text">
|
||||
<more-icon />
|
||||
</t-button>
|
||||
</t-dropdown>
|
||||
</template>
|
||||
</t-card>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ShopIcon, CalendarIcon, ServiceIcon, UserAvatarIcon, LaptopIcon, MoreIcon, AddIcon } from 'tdesign-icons-vue';
|
||||
|
||||
export default {
|
||||
name: 'ListCard',
|
||||
components: {
|
||||
ShopIcon,
|
||||
CalendarIcon,
|
||||
ServiceIcon,
|
||||
UserAvatarIcon,
|
||||
LaptopIcon,
|
||||
MoreIcon,
|
||||
AddIcon,
|
||||
},
|
||||
props: {
|
||||
product: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return { typeMap: ['A', 'B', 'C', 'D', 'E'] };
|
||||
},
|
||||
methods: {
|
||||
handleClickManage(product) {
|
||||
this.$emit('manage-product', product);
|
||||
},
|
||||
handleClickDelete(product) {
|
||||
this.$emit('delete-item', product);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '@/style/variables';
|
||||
|
||||
.list-card-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
|
||||
&_detail {
|
||||
min-height: 140px;
|
||||
|
||||
&--name {
|
||||
margin-bottom: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: var(--td-text-color-primary);
|
||||
}
|
||||
|
||||
&--desc {
|
||||
color: var(--td-text-color-secondary);
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="result-container">
|
||||
<div class="result-bg-img">
|
||||
<component :is="dynamicComponent"></component>
|
||||
</div>
|
||||
<div class="result-title">{{ title }}</div>
|
||||
<div class="result-tip">{{ tip }}</div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
import Result403Icon from '@/assets/assets-result-403.svg';
|
||||
import Result404Icon from '@/assets/assets-result-404.svg';
|
||||
import Result500Icon from '@/assets/assets-result-500.svg';
|
||||
import ResultIeIcon from '@/assets/assets-result-ie.svg';
|
||||
import ResultWifiIcon from '@/assets/assets-result-wifi.svg';
|
||||
import ResultMaintenanceIcon from '@/assets/assets-result-maintenance.svg';
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Result',
|
||||
props: {
|
||||
bgUrl: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
tip: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
dynamicComponent() {
|
||||
switch (this.type) {
|
||||
case '403':
|
||||
return Result403Icon;
|
||||
case '404':
|
||||
return Result404Icon;
|
||||
case '500':
|
||||
return Result500Icon;
|
||||
case 'ie':
|
||||
return ResultIeIcon;
|
||||
case 'wifi':
|
||||
return ResultWifiIcon;
|
||||
case 'maintenance':
|
||||
return ResultMaintenanceIcon;
|
||||
default:
|
||||
return Result403Icon;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import '@/style/variables';
|
||||
|
||||
.result {
|
||||
&-link {
|
||||
color: var(--td-brand-color);
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--td-brand-color);
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: var(--td-brand-color);
|
||||
}
|
||||
|
||||
&--active {
|
||||
color: var(--td-brand-color);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-container {
|
||||
min-height: 400px;
|
||||
height: 75vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
&-bg-img {
|
||||
width: 200px;
|
||||
color: var(--td-brand-color);
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
margin-top: 8px;
|
||||
color: var(--td-text-color-primary);
|
||||
font-size: @font-size-xl;
|
||||
line-height: @text-line-height-xl;
|
||||
}
|
||||
|
||||
&-tip {
|
||||
margin: 8px 0 32px;
|
||||
font-size: @font-size-base;
|
||||
color: var(--td-text-color-secondary);
|
||||
line-height: @text-line-height-base;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<img :class="className" :src="url" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'thumbnail',
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'layout',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
className() {
|
||||
return [
|
||||
'thumbnail-container',
|
||||
{
|
||||
'thumbnail-circle': this.type === 'circle',
|
||||
'thumbnail-layout': this.type === 'layout',
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import url('@/style/index.less');
|
||||
|
||||
.thumbnail {
|
||||
&-container {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&-circle {
|
||||
border-radius: @border-radius-50;
|
||||
}
|
||||
|
||||
&-layout {
|
||||
width: 88px;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<span :class="containerCls">
|
||||
<span :class="iconCls">
|
||||
<svg
|
||||
v-if="type === 'down'"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M11.5 8L8 11.5L4.5 8" stroke="currentColor" stroke-width="1.5" />
|
||||
<path d="M8 11L8 4" stroke="currentColor" stroke-width="1.5" />
|
||||
</svg>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" v-else>
|
||||
<path d="M4.5 8L8 4.5L11.5 8" stroke="currentColor" stroke-width="1.5" />
|
||||
<path d="M8 5V12" stroke="currentColor" stroke-width="1.5" />
|
||||
</svg>
|
||||
</span>
|
||||
<span>{{ describe }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Trend',
|
||||
|
||||
props: {
|
||||
type: String,
|
||||
describe: [String, Number],
|
||||
isReverseColor: Boolean,
|
||||
},
|
||||
computed: {
|
||||
containerCls() {
|
||||
return [
|
||||
'trend-container',
|
||||
{
|
||||
'trend-container__reverse': this.isReverseColor,
|
||||
'trend-container__up': !this.isReverseColor && this.type === 'up',
|
||||
'trend-container__down': !this.isReverseColor && this.type === 'down',
|
||||
},
|
||||
];
|
||||
},
|
||||
iconCls() {
|
||||
return ['trend-icon-container'];
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '@/style/variables.less';
|
||||
|
||||
.trend {
|
||||
|
||||
&-container {
|
||||
|
||||
&__up {
|
||||
color: var(--td-error-color);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.trend-icon-container {
|
||||
background: var(--td-error-color-2);
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&__down {
|
||||
color: var(--td-success-color);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.trend-icon-container {
|
||||
background: var(--td-success-color-2);
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&__reverse {
|
||||
color: #ffffff;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.trend-icon-container {
|
||||
background: var(--td-brand-color-5);
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.trend-icon-container {
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,228 @@
|
||||
import { Color } from 'tvision-color';
|
||||
/* eslint-disable indent */
|
||||
export type ColorToken = Record<string, string>;
|
||||
export type ColorSeries = Record<string, ColorToken>;
|
||||
|
||||
export const defaultLightColor = [
|
||||
'#0052d9',
|
||||
'#0594fa',
|
||||
'#00a870',
|
||||
'#ebb105',
|
||||
'#ed7b2f',
|
||||
'#e34d59',
|
||||
'#ed49b4',
|
||||
'#834ec2',
|
||||
];
|
||||
export const defaultDarkColor = [
|
||||
'#4582e6',
|
||||
'#29a4fb',
|
||||
'#03a56f',
|
||||
'#ca8d03',
|
||||
'#ed7b2f',
|
||||
'#ea7b84',
|
||||
'#f172c5',
|
||||
'#ab87d5',
|
||||
];
|
||||
|
||||
export const COLOR_TOKEN: ColorSeries = {
|
||||
DEFAULT: {
|
||||
'--td-brand-color': '#0052D9',
|
||||
'--td-brand-color-1': '#e0ebff',
|
||||
'--td-brand-color-2': '#c0d8ff',
|
||||
'--td-brand-color-3': '#a1c4ff',
|
||||
'--td-brand-color-4': '#81b1ff',
|
||||
'--td-brand-color-5': '#5f9bff',
|
||||
'--td-brand-color-6': '#3d87ff',
|
||||
'--td-brand-color-7': '#176eff',
|
||||
'--td-brand-color-8': '#0052D9',
|
||||
'--td-brand-color-9': '#0048cd',
|
||||
'--td-brand-color-10': '#0035b5',
|
||||
},
|
||||
|
||||
CYAN: {
|
||||
'--td-brand-color': '#0594FA',
|
||||
'--td-brand-color-1': '#d7eefe',
|
||||
'--td-brand-color-2': '#aeddfd',
|
||||
'--td-brand-color-3': '#84cafd',
|
||||
'--td-brand-color-4': '#58b8fc',
|
||||
'--td-brand-color-5': '#29a4fb',
|
||||
'--td-brand-color-6': '#0594FA',
|
||||
'--td-brand-color-7': '#29a4fb',
|
||||
'--td-brand-color-8': '#0594FA',
|
||||
'--td-brand-color-9': '#0378df',
|
||||
'--td-brand-color-10': '#01409b',
|
||||
},
|
||||
GREEN: {
|
||||
'--td-brand-color': '#00A870',
|
||||
'--td-brand-color-1': '#8dffd9',
|
||||
'--td-brand-color-2': '#00f2a2',
|
||||
'--td-brand-color-3': '#00dc92',
|
||||
'--td-brand-color-4': '#00c583',
|
||||
'--td-brand-color-5': '#00A870',
|
||||
'--td-brand-color-6': '#009a5d',
|
||||
'--td-brand-color-7': '#00c583',
|
||||
'--td-brand-color-8': '#00A870',
|
||||
'--td-brand-color-9': '#009a5d',
|
||||
'--td-brand-color-10': '#004a14',
|
||||
},
|
||||
ORANGE: {
|
||||
'--td-brand-color': '#ED7B2F',
|
||||
'--td-brand-color-1': '#fce5d7',
|
||||
'--td-brand-color-2': '#f8cdaf',
|
||||
'--td-brand-color-3': '#f4b285',
|
||||
'--td-brand-color-4': '#f19659',
|
||||
'--td-brand-color-5': '#ED7B2F',
|
||||
'--td-brand-color-6': '#e75510',
|
||||
'--td-brand-color-7': '#f19659',
|
||||
'--td-brand-color-8': '#ED7B2F',
|
||||
'--td-brand-color-9': '#e75510',
|
||||
'--td-brand-color-10': '#7f0a02',
|
||||
},
|
||||
RED: {
|
||||
'--td-brand-color': '#E34D59',
|
||||
'--td-brand-color-1': '#fbe5e7',
|
||||
'--td-brand-color-2': '#f7ccd0',
|
||||
'--td-brand-color-3': '#f3b2b8',
|
||||
'--td-brand-color-4': '#ef989f',
|
||||
'--td-brand-color-5': '#ea7b84',
|
||||
'--td-brand-color-6': '#E34D59',
|
||||
'--td-brand-color-7': '#ea7b84',
|
||||
'--td-brand-color-8': '#E34D59',
|
||||
'--td-brand-color-9': '#e42c3a',
|
||||
'--td-brand-color-10': '#8d0309',
|
||||
},
|
||||
PINK: {
|
||||
'--td-brand-color': '#ED49B4',
|
||||
'--td-brand-color-1': '#fce5f4',
|
||||
'--td-brand-color-2': '#facae9',
|
||||
'--td-brand-color-3': '#f7aede',
|
||||
'--td-brand-color-4': '#f491d2',
|
||||
'--td-brand-color-5': '#f172c5',
|
||||
'--td-brand-color-6': '#ED49B4',
|
||||
'--td-brand-color-7': '#f172c5',
|
||||
'--td-brand-color-8': '#ED49B4',
|
||||
'--td-brand-color-9': '#e80f9d',
|
||||
'--td-brand-color-10': '#8f025e',
|
||||
},
|
||||
PURPLE: {
|
||||
'--td-brand-color': '#834EC2',
|
||||
'--td-brand-color-1': '#eee6f7',
|
||||
'--td-brand-color-2': '#ddceee',
|
||||
'--td-brand-color-3': '#ccb6e6',
|
||||
'--td-brand-color-4': '#bb9edc',
|
||||
'--td-brand-color-5': '#ab87d5',
|
||||
'--td-brand-color-6': '#9a6fce',
|
||||
'--td-brand-color-7': '#9a6fce',
|
||||
'--td-brand-color-8': '#834EC2',
|
||||
'--td-brand-color-9': '#783ac3',
|
||||
'--td-brand-color-10': '#4c1397',
|
||||
},
|
||||
YELLOW: {
|
||||
'--td-brand-color': '#EBB105',
|
||||
'--td-brand-color-1': '#fde9ab',
|
||||
'--td-brand-color-2': '#fbd152',
|
||||
'--td-brand-color-3': '#EBB105',
|
||||
'--td-brand-color-4': '#dda204',
|
||||
'--td-brand-color-5': '#ca8d03',
|
||||
'--td-brand-color-6': '#b67803',
|
||||
'--td-brand-color-7': '#fbd152',
|
||||
'--td-brand-color-8': '#EBB105',
|
||||
'--td-brand-color-9': '#dda204',
|
||||
'--td-brand-color-10': '#603100',
|
||||
},
|
||||
};
|
||||
|
||||
export const LIGHT_CHART_COLORS: ColorToken = {
|
||||
textColor: 'rgba(0, 0, 0, 0.9)',
|
||||
placeholderColor: 'rgba(0, 0, 0, 0.35)',
|
||||
borderColor: '#dcdcdc',
|
||||
containerColor: '#fff',
|
||||
};
|
||||
|
||||
export const DARK_CHART_COLORS: ColorToken = {
|
||||
textColor: 'rgba(255, 255, 255, 0.9)',
|
||||
placeholderColor: 'rgba(255, 255, 255, 0.35)',
|
||||
borderColor: '#5e5e5e',
|
||||
containerColor: '#242424',
|
||||
};
|
||||
|
||||
function toUnderline(name: string): string {
|
||||
return name.replace(/([A-Z])/g, '_$1').toUpperCase();
|
||||
}
|
||||
|
||||
export function getBrandColor(type: string, colorList: ColorSeries): ColorToken {
|
||||
const name = /^#[A-F\d]{6}$/i.test(type) ? type : toUnderline(type);
|
||||
return colorList[name || 'DEFAULT'];
|
||||
}
|
||||
|
||||
export function getColorList(colorArray: Array<ColorToken>): Array<string> {
|
||||
const pureColorList = [];
|
||||
colorArray.map((colorToken) => Object.keys(colorToken).map((key) => pureColorList.push(colorToken[key])));
|
||||
|
||||
return pureColorList;
|
||||
}
|
||||
// inspired by https://stackoverflow.com/questions/36721830/convert-hsl-to-rgb-and-hex
|
||||
export function hslToHex(h: number, s: number, l: number) {
|
||||
l /= 100;
|
||||
const a = (s * Math.min(l, 1 - l)) / 100;
|
||||
const f = (n: number) => {
|
||||
const k = (n + h / 30) % 12;
|
||||
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
||||
return Math.round(255 * color)
|
||||
.toString(16)
|
||||
.padStart(2, '0');
|
||||
};
|
||||
return `#${f(0)}${f(8)}${f(4)}`;
|
||||
}
|
||||
|
||||
export function generateColorMap(theme: string, colorPalette: Array<string>, mode: 'light' | 'dark') {
|
||||
const isDarkMode = mode === 'dark';
|
||||
let brandColorIdx = colorPalette.indexOf(theme);
|
||||
|
||||
if (isDarkMode) {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
colorPalette.reverse().map((color) => {
|
||||
const [h, s, l] = Color.colorTransform(color, 'hex', 'hsl');
|
||||
return Color.colorTransform([h, Number(s) - 4, l], 'hsl', 'hex');
|
||||
});
|
||||
brandColorIdx = 5;
|
||||
colorPalette[0] = `${colorPalette[brandColorIdx]}20`;
|
||||
}
|
||||
|
||||
const colorMap = {
|
||||
'--td-brand-color': colorPalette[brandColorIdx], // 主题色
|
||||
'--td-brand-color-1': colorPalette[0], // light
|
||||
'--td-brand-color-2': colorPalette[1], // focus
|
||||
'--td-brand-color-3': colorPalette[2], // disabled
|
||||
'--td-brand-color-4': colorPalette[3],
|
||||
'--td-brand-color-5': colorPalette[4],
|
||||
'--td-brand-color-6': colorPalette[5],
|
||||
'--td-brand-color-7': brandColorIdx > 0 ? colorPalette[brandColorIdx - 1] : theme, // hover
|
||||
'--td-brand-color-8': colorPalette[brandColorIdx], // 主题色
|
||||
'--td-brand-color-9': brandColorIdx > 8 ? theme : colorPalette[brandColorIdx + 1], // click
|
||||
'--td-brand-color-10': colorPalette[9],
|
||||
};
|
||||
return colorMap;
|
||||
}
|
||||
export function insertThemeStylesheet(theme: string, colorMap: ColorToken, mode: 'light' | 'dark') {
|
||||
const isDarkMode = mode === 'dark';
|
||||
const root = !isDarkMode ? `:root[theme-color='${theme}']` : `:root[theme-color='${theme}'][theme-mode='dark']`;
|
||||
|
||||
const styleSheet = document.createElement('style');
|
||||
styleSheet.type = 'text/css';
|
||||
styleSheet.innerText = `${root}{
|
||||
--td-brand-color: ${colorMap['--td-brand-color']};
|
||||
--td-brand-color-1: ${colorMap['--td-brand-color-1']};
|
||||
--td-brand-color-2: ${colorMap['--td-brand-color-2']};
|
||||
--td-brand-color-3: ${colorMap['--td-brand-color-3']};
|
||||
--td-brand-color-4: ${colorMap['--td-brand-color-4']};
|
||||
--td-brand-color-5: ${colorMap['--td-brand-color-5']};
|
||||
--td-brand-color-6: ${colorMap['--td-brand-color-6']};
|
||||
--td-brand-color-7: ${colorMap['--td-brand-color-7']};
|
||||
--td-brand-color-8: ${colorMap['--td-brand-color-8']};
|
||||
--td-brand-color-9: ${colorMap['--td-brand-color-9']};
|
||||
--td-brand-color-10: ${colorMap['--td-brand-color-10']};
|
||||
}`;
|
||||
|
||||
document.head.appendChild(styleSheet);
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export const prefix = 'tdesign-starter';
|
||||
export const TOKEN_NAME = 'tdesign-starter';
|
@ -0,0 +1,20 @@
|
||||
export default {
|
||||
development: {
|
||||
// 开发环境接口请求
|
||||
API: 'http://127.0.0.1:26666/samwaf',
|
||||
// 开发环境 cdn 路径
|
||||
CDN: '',
|
||||
},
|
||||
test: {
|
||||
// 测试环境接口地址
|
||||
API: 'https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com',
|
||||
// 测试环境 cdn 路径
|
||||
CDN: '',
|
||||
},
|
||||
release: {
|
||||
// 正式环境接口地址
|
||||
API: '/samwaf',
|
||||
// 正式环境 cdn 路径
|
||||
CDN: '',
|
||||
},
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
export default {
|
||||
"showFooter": true,
|
||||
"isSidebarCompact": false,
|
||||
"showBreadcrumb": true,
|
||||
"mode": "auto",
|
||||
"layout": "side",
|
||||
"splitMenu": false,
|
||||
"isFooterAside": false,
|
||||
"isSidebarFixed": true,
|
||||
"isHeaderFixed": true,
|
||||
"isUseTabsRouter": false,
|
||||
"showHeader": true,
|
||||
"backgroundTheme": "blueGrey",
|
||||
"brandTheme": "default"
|
||||
};
|
@ -0,0 +1,74 @@
|
||||
interface IOption {
|
||||
value: number | string;
|
||||
label: string;
|
||||
}
|
||||
// 规则状态枚举
|
||||
export const RULE_STATUS = {
|
||||
STOPPING: 0,
|
||||
RUNNING: 1,
|
||||
};
|
||||
// 防护状态枚举
|
||||
export const GUARD_STATUS = {
|
||||
UN_GUARDDING: 0,
|
||||
GUARDDING: 1,
|
||||
};
|
||||
// SSL证书状态枚举
|
||||
export const SSL_STATUS = {
|
||||
NOT_SSL: 0,
|
||||
SSL: 1,
|
||||
};
|
||||
|
||||
// 启动状态枚举
|
||||
export const START_STATUS = {
|
||||
START: 0,
|
||||
NOT_START: 1,
|
||||
};
|
||||
// 合同状态枚举
|
||||
export const CONTRACT_STATUS = {
|
||||
FAIL: 0,
|
||||
AUDIT_PENDING: 1,
|
||||
EXEC_PENDING: 2,
|
||||
EXECUTING: 3,
|
||||
FINISH: 4,
|
||||
};
|
||||
|
||||
export const CONTRACT_STATUS_OPTIONS: Array<IOption> = [
|
||||
{ value: CONTRACT_STATUS.FAIL, label: '审核失败' },
|
||||
{ value: CONTRACT_STATUS.AUDIT_PENDING, label: '待审核' },
|
||||
{ value: CONTRACT_STATUS.EXEC_PENDING, label: '待履行' },
|
||||
{ value: CONTRACT_STATUS.EXECUTING, label: '审核成功' },
|
||||
{ value: CONTRACT_STATUS.FINISH, label: '已完成' },
|
||||
];
|
||||
|
||||
// 合同类型枚举
|
||||
export const CONTRACT_TYPES = {
|
||||
MAIN: 0,
|
||||
SUB: 1,
|
||||
SUPPLEMENT: 2,
|
||||
};
|
||||
|
||||
export const CONTRACT_TYPE_OPTIONS: Array<IOption> = [
|
||||
{ value: CONTRACT_TYPES.MAIN, label: '主合同' },
|
||||
{ value: CONTRACT_TYPES.SUB, label: '子合同' },
|
||||
{ value: CONTRACT_TYPES.SUPPLEMENT, label: '补充合同' },
|
||||
];
|
||||
|
||||
// 合同收付类型枚举
|
||||
export const CONTRACT_PAYMENT_TYPES = {
|
||||
PAYMENT: 0,
|
||||
RECIPT: 1,
|
||||
};
|
||||
|
||||
// 通知的优先级对应的TAG类型
|
||||
export const NOTIFICATION_TYPES = {
|
||||
low: 'primary',
|
||||
middle: 'warning',
|
||||
high: 'danger',
|
||||
};
|
||||
|
||||
// 攻击类型TAG类型
|
||||
export const ATTACK_TYPES = {
|
||||
CC: 0,
|
||||
CMD: 1,
|
||||
WEBUPLOAD: 2,
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
import Vue from "vue";
|
||||
import VueI18n from "vue-i18n";
|
||||
import zh_CN from "./zh_CN";
|
||||
import en_US from "./en_US";
|
||||
Vue.use(VueI18n);
|
||||
|
||||
const i18n = new VueI18n({
|
||||
locale: localStorage.getItem("lang") || "zh_CN", // 语言标识
|
||||
messages: {
|
||||
zh_CN, // 中文语言包
|
||||
en_US, // 英文语言包
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|