first commit

This commit is contained in:
Vinjor 2024-08-08 19:03:18 +08:00
commit 9c180e646e
788 changed files with 77008 additions and 0 deletions

3
.commitlintrc.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
extends: ["@commitlint/config-conventional"]
};

15
.env Normal file
View File

@ -0,0 +1,15 @@
# port
VITE_DEV_PORT = '8080'
# development path
# VITE_DEV_PATH = 'https://demo.mtruning.club'
VITE_DEV_PATH = 'http://127.0.0.1:48080'
# production path
VITE_PRO_PATH = 'https://demo.mtruning.club'
# 租户开关
VITE_APP_TENANT_ENABLE=true
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=true

11
.eslintignore Normal file
View File

@ -0,0 +1,11 @@
node_modules/
public/
es/
lib/
dist/
package.json
src/assets/
plop-templates/
handlebars/
website/
build/

30
.eslintrc.js Normal file
View File

@ -0,0 +1,30 @@
module.exports = {
root: true,
parser: 'vue-eslint-parser',
globals: {
postMessage: true
},
parserOptions: {
parser: '@typescript-eslint/parser',
sourceType: 'module',
ecmaFeatures: {
jsx: true,
tsx: true
}
},
env: {
node: true,
// The Follow config only works with eslint-plugin-vue v8.0.0+
'vue/setup-compiler-macros': true
},
extends: ['plugin:vue/vue3-essential', 'eslint:recommended'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-unused-vars': 'off',
'vue/no-unused-vars': 'off',
'vue/multi-word-component-names': 'off',
'vue/valid-template-root': 'off',
'vue/no-mutating-props': 'off'
}
}

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
.vscode

4
.husky/commit-msg Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install commitlint -e

5
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/yudao-ui-go-view.iml" filepath="$PROJECT_DIR$/.idea/yudao-ui-go-view.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,51 @@
version: '1.0'
name: branch-pipeline
displayName: BranchPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
exclude:
- master
include:
- .*

View File

@ -0,0 +1,49 @@
version: '1.0'
name: master-pipeline
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
include:
- master

36
.workflow/pr-pipeline.yml Normal file
View File

@ -0,0 +1,36 @@
version: '1.0'
name: pr-pipeline
displayName: PRPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
triggers:
pr:
branches:
include:
- master

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-present GoView
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

25
Makefile Normal file
View File

@ -0,0 +1,25 @@
.PHONY: dist test
default: help
dev:
npm run dev
dist:
npm run build
view:
npm run preview
lint:
npm run lint
new:
npm run new
help:
@echo " make dev [npm run dev] 开发模式"
@echo " make dist [npm run build] 编译模式"
@echo " make view [npm run preview] 预览打包文件"
@echo " make new [npm run lint] 通过自动化流程创建代码"
@echo " make lint [npm run new] 格式校验"

92
README.md Normal file
View File

@ -0,0 +1,92 @@
## 总览
<p align="center">
<img src="readme/logo-t-y.png" alt="go-view" />
</p>
<h4 align="center">开源、精美、便捷的「数据可视化」低代码开发平台</h4>
由 [芋道](https://doc.iocoder.cn/) 与 GoView 共同建设,基于 Vue3 搭建的低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可完成业务需求。
* 框架:基于 Vue3 框架编写,使用 hooks 写法抽离部分逻辑,使代码结构更加清晰
* 类型:使用 TypeScript 进行类型约束,减少未知错误发生概率,可以大胆修改逻辑内容
* 性能:多处性能优化,使用页面懒加载、组件动态注册、数据滚动加载等方式,提升页面渲染速度
* 存储:拥有本地记忆,部分配置项采用 storage 存储本地,提升使用体验
* 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
* 入选 NaiveUI 社区精选资源推荐:[查看 NaiveUI 推荐列表](https://www.naiveui.com/zh-CN/light/docs/community)
## 项目地址
![preview](readme/preview.png)
* 前端:<https://gitee.com/zhijiantianya/yudao-ui-go-view>
* Boot 后端:<https://gitee.com/zhijiantianya/ruoyi-vue-pro>
* Cloud 后端:<https://gitee.com/zhijiantianya/yudao-cloud>
## 文档地址
* 演示环境:<http://dashboard.yudao.iocoder.cn/login> 「报表管理 - 大屏设计器」
* 文档地址:<https://doc.iocoder.cn/report/>
## 技术栈
主要技术栈为:
| 名称 | 版本 | 名称 | 版本 |
|-------------------|-------|-------------|--------|
| Vue | 3.2.x | TypeScript4 | 4.6.x |
| Vite | 2.9.x | NaiveUI | 2.27.x |
| ECharts | 5.3.x | Pinia | 2.0.x |
| 详见 `package.json` | 😁 | 🥰 | 🤗 |
开发环境:
| 名称 | 版本 | 名称 | 版本 |
|------|---------|---------|-------|
| node | 16.14.x | npm | 8.5.x |
| pnpm | 7.1.x | windows | 11 |
已完成图表:
| 分类 | 名称 | 名称 | 名称 | 名称 |
|-----|--------------|----------|---------|----------------|
| 图表 | 柱状图 | 横向柱状图 | 折线图 | 单/多 折线面积图(渐变色) |
| \* | 饼图 | 环形图 | 水球图 | 雷达图 |
| \* | NaiveUI 多种进度 | 散点图 | 对数回归散点图 | 热力图 |
| \* | 漏斗图 | 中国地图 | 高德地图 | 🦊 |
| 信息 | 文字 | 渐变文字 | 词云 | 嵌套网页 |
| \* | 图片 | 视频 | 😺 | 🐯 |
| 列表 | 滚动排名列表 | 滚动表格 | 🐮 | 🐐 |
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 | 通用时间 |
| \* | 数字计数 | 倒计时 | 时钟 | 🦁 |
## 项目截图
#### 工作台
![工作台](readme/go-view-canvas.png)
#### 请求配置
![请求配置](readme/go-view-fetch.png)
#### 数据过滤
![数据过滤](readme/go-view-filter.png)
#### 高级事件编辑
![高级事件编辑](readme/go-view-event.png)
#### 快捷主页
![快捷主页](readme/go-view-indexpage.png)
#### 主题色
![主题色](readme/go-view-color.png)
#### 亮白主题
![亮白主题](readme/go-view-theme.png)

41
build/constant.ts Normal file
View File

@ -0,0 +1,41 @@
import path from 'path'
export const OUTPUT_DIR = 'dist'
// monaco-editor 路径
export const prefix = `monaco-editor/esm/vs`
// chunk 警告大小
export const chunkSizeWarningLimit = 2000
// 禁用 brotliSize 压缩大小报告
export const brotliSize = false
// 分包
export const rollupOptions = {
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: (chunkInfo) => {
if(['.png', '.jpg', '.jpeg'].includes(path.extname(chunkInfo.name))) {
return `static/[ext]/[name].[ext]`
}
return `static/[ext]/[name]-[hash].[ext]`
},
manualChunks: {
jsonWorker: [`${prefix}/language/json/json.worker`],
cssWorker: [`${prefix}/language/css/css.worker`],
htmlWorker: [`${prefix}/language/html/html.worker`],
tsWorker: [`${prefix}/language/typescript/ts.worker`],
editorWorker: [`${prefix}/editor/editor.worker`]
}
}
}
// 去除开发代码
export const terserOptions = {
compress: {
keep_infinity: true,
drop_console: true,
drop_debugger: true
}
}

85
index.css Normal file
View File

@ -0,0 +1,85 @@
* {
margin: 0;
}
.first-loading-wrp {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #17171a;
}
.first-loading-wrp > h1 {
font-size: 128px;
}
.first-loading-wrp .loading-wrp {
padding: 98px;
display: flex;
justify-content: center;
align-items: center;
}
.dot {
animation: antRotate 1.2s infinite linear;
transform: rotate(45deg);
position: relative;
display: inline-block;
font-size: 32px;
width: 32px;
height: 32px;
box-sizing: border-box;
}
.dot i {
width: 14px;
height: 14px;
position: absolute;
display: block;
background-color: #1890ff;
border-radius: 100%;
transform: scale(0.75);
transform-origin: 50% 50%;
opacity: 0.3;
animation: antSpinMove 1s infinite linear alternate;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@-webkit-keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1;
}
}

29
index.html Normal file
View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta name="description" content="GoView 是高效、高性能的拖拽式低代码数据可视化开发平台,将页面元素封装为基础组件,无需编写代码即可完成业务需求。">
<meta name="keywords" content="GoViewgoview低代码可视化">
<meta name="author" content="奔跑的面条,面条">
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<link rel="icon" href="./favicon.ico" />
<title>GoView</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div id="appProvider" style="display: none;"></div>
<div id="app">
<div class="first-loading-wrp">
<div class="loading-wrp">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

85
package.json Normal file
View File

@ -0,0 +1,85 @@
{
"name": "go-view",
"version": "2.1.6",
"engines": {
"node": ">=16.14 <18.0.0"
},
"scripts": {
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"new": "plop --plopfile ./plop/plopfile.js",
"postinstall": "husky install",
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src",
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx,.vue src --fix"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@amap/amap-jsapi-types": "^0.0.8",
"@types/color": "^3.0.3",
"@types/crypto-js": "^4.1.1",
"@types/keymaster": "^1.6.30",
"@types/lodash": "^4.14.184",
"animate.css": "^4.1.1",
"axios": "^0.27.2",
"color": "^4.2.3",
"crypto-js": "^4.1.1",
"dom-helpers": "^5.2.1",
"echarts-liquidfill": "^3.1.0",
"echarts-stat": "^1.2.0",
"echarts-wordcloud": "^2.0.0",
"gsap": "^3.11.3",
"highlight.js": "^11.5.0",
"html2canvas": "^1.4.1",
"keymaster": "^1.6.2",
"monaco-editor": "^0.33.0",
"naive-ui": "2.34.3",
"pinia": "^2.0.13",
"screenfull": "^6.0.1",
"three": "^0.145.0",
"vue": "^3.2.31",
"vue-demi": "^0.13.1",
"vue-i18n": "^9.2.2",
"vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@commitlint/cli": "^17.0.2",
"@commitlint/config-conventional": "^17.0.2",
"@types/node": "^16.11.26",
"@types/three": "^0.144.0",
"@typescript-eslint/eslint-plugin": "^5.18.0",
"@typescript-eslint/parser": "^5.18.0",
"@vicons/carbon": "^0.12.0",
"@vicons/ionicons5": "~0.11.0",
"@vitejs/plugin-vue": "^1.10.2",
"@vitejs/plugin-vue-jsx": "^1.3.9",
"@vue/compiler-sfc": "^3.2.31",
"@vueuse/core": "^7.7.1",
"commitlint": "^17.0.2",
"default-passive-events": "^2.0.0",
"echarts": "^5.3.2",
"eslint": "^8.12.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.5.0",
"husky": "^8.0.1",
"lodash": "~4.17.21",
"mockjs": "^1.1.0",
"plop": "^3.0.5",
"prettier": "^2.6.2",
"sass": "^1.49.11",
"sass-loader": "^12.6.0",
"typescript": "4.6.3",
"vite": "2.9.9",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-importer": "^0.2.5",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-monaco-editor": "^1.1.0",
"vue-echarts": "^6.0.2",
"vue-tsc": "^0.28.10"
}
}

5
plop/plopfile.js Normal file
View File

@ -0,0 +1,5 @@
const storeGenerator = require('./store-template/prompt')
module.exports = (plop) => {
plop.setGenerator('store', storeGenerator)
}

View File

@ -0,0 +1,3 @@
export interface {{upperDataName}}StoreType {
}

View File

@ -0,0 +1,11 @@
import { defineStore } from 'pinia'
import { {{upperDataName}}StoreType } from './{{name}}Store.d'
import { setLocalStorage, getLocalStorage } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum'
export const use{{upperDataName}}Store = defineStore({
id: 'use{{upperDataName}}Store',
state: (): {{upperDataName}}StoreType => ({}),
getters: {},
actions: {}
})

View File

@ -0,0 +1,45 @@
module.exports = {
description: 'create a store',
prompts: [
{
type: 'input',
name: 'name',
message: 'Please enter store namesuch as "newStoreName" :',
validate (value) {
if (!value || value.trim === '') {
return 'name is required';
}
return true;
},
}
],
actions: (data) => {
const dataName = data.name
// 首字母大写
const upperDataName = dataName.slice(0, 1).toUpperCase() + dataName.slice(1)
const actions = [
{
type: 'add',
path: `${process.cwd()}/src/store/modules/${dataName}Store/${dataName}Store.ts`, // 这里的name就是上面定义的键
templateFile: './store-template/index.hbs',
data: {
name: data.name,
upperDataName,
}
},
{
type: 'add',
path: `${process.cwd()}/src/store/modules/${dataName}Store/${dataName}Store.d.ts`, // 这里的name就是上面定义的键
templateFile: './store-template/index.d.hbs',
data: {
name: data.name,
upperDataName,
}
},
]
return actions
}
}

7252
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

12
prettier.config.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
printWidth: 120,
tabWidth: 2,
useTabs: false,
singleQuote: true,
semi: false,
trailingComma: "none",
bracketSpacing: true,
jsxSingleQuote: true,
jsxBracketSameLine: false,
arrowParens: "avoid"
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
readme/go-view-canvas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

BIN
readme/go-view-color.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

BIN
readme/go-view-doc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
readme/go-view-event.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
readme/go-view-fetch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

BIN
readme/go-view-filter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
readme/go-view-qq.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
readme/go-view-theme.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
readme/logo-poster.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
readme/logo-t-y.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
readme/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
readme/preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

37
src/App.vue Normal file
View File

@ -0,0 +1,37 @@
<template>
<n-config-provider
:theme="darkTheme"
:hljs="hljsTheme"
:locale="locale"
:date-locale="dateLocale"
:theme-overrides="overridesTheme"
>
<go-app-provider>
<I18n></I18n>
<router-view></router-view>
</go-app-provider>
</n-config-provider>
</template>
<script lang="ts" setup>
import { NConfigProvider } from 'naive-ui'
import { GoAppProvider } from '@/components/GoAppProvider'
import { I18n } from '@/components/I18n'
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
//
const darkTheme = useDarkThemeHook()
//
const overridesTheme = useThemeOverridesHook()
//
const hljsTheme = useCode()
//
useSystemInit()
//
const { locale, dateLocale } = useLang()
</script>

12
src/api/axios.config.ts Normal file
View File

@ -0,0 +1,12 @@
import { ModuleTypeEnum } from '@/enums/httpEnum'
// 接口白名单(免登录)
export const fetchAllowList = [
// 登录
`${ModuleTypeEnum.SYSTEM}/auth-login`,
// 预览获取数据
`${ModuleTypeEnum.PROJECT}/getData`,
]
// 接口黑名单
export const fetchBlockList = []

97
src/api/axios.ts Normal file
View File

@ -0,0 +1,97 @@
import axios, { AxiosResponse, AxiosRequestConfig, Axios } from 'axios'
import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum"
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
import { StorageEnum } from '@/enums/storageEnum'
import { axiosPre } from '@/settings/httpSetting'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
import { fetchAllowList } from './axios.config'
import includes from 'lodash/includes'
export interface MyResponseType<T> {
code: ResultEnum
data: T
message: string
}
export interface MyRequestInstance extends Axios {
<T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>>
}
const axiosInstance = axios.create({
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
timeout: ResultEnum.TIMEOUT,
}) as unknown as MyRequestInstance
axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 获取 tenantId
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
const tenantId = info ? info[SystemStoreEnum.TENANT_INFO]['tenantId'] : undefined
if (tenantId) {
config.headers = {
...config.headers,
'tenant-id': tenantId
}
}
// 白名单校验
if (includes(fetchAllowList, config.url)) return config
// 获取 token
// 重新登录
if (!info) {
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return config
}
const userInfo = info[SystemStoreEnum.USER_INFO]
config.headers = {
...config.headers,
[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token']: 'Bearer ' + userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
}
return config
},
(err: AxiosRequestConfig) => {
Promise.reject(err)
}
)
// 响应拦截器
axiosInstance.interceptors.response.use(
(res: AxiosResponse) => {
// 预览页面错误不进行处理
if (isPreview()) {
return Promise.resolve(res.data)
}
// 如果是验证码的返回,直接返回数据
const { code } = res.data as { code: number }
if (code === undefined || code === null) return Promise.resolve(res)
// 成功
if (code === ResultEnum.SUCCESS) {
return Promise.resolve(res.data)
}
// 登录过期
if (code === ResultEnum.TOKEN_OVERDUE) {
window['$message'].error(window['$t']('http.token_overdue_message'))
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return Promise.resolve(res.data)
}
// 固定错误码重定向
if (ErrorPageNameMap.get(code)) {
redirectErrorPage(code)
return Promise.resolve(res.data)
}
// 提示错误
window['$message'].error(window['$t']((res.data as any).msg))
return Promise.resolve(res.data)
},
(err: AxiosResponse) => {
Promise.reject(err)
}
)
export default axiosInstance

254
src/api/http.ts Normal file
View File

@ -0,0 +1,254 @@
import axiosInstance from './axios'
import {
RequestHttpEnum,
ContentTypeEnum,
RequestBodyEnum,
RequestDataTypeEnum,
RequestContentTypeEnum,
RequestParamsObjType
} from '@/enums/httpEnum'
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { getLocalStorage } from "@/utils";
import { StorageEnum } from "@/enums/storageEnum";
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
export const get = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.GET,
params: params,
})
}
export const post = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.POST,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
export const patch = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.PATCH,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.PUT,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
export const del = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.DELETE,
params
})
}
// 获取请求函数默认get
export const http = (type?: RequestHttpEnum) => {
switch (type) {
case RequestHttpEnum.GET:
return get
case RequestHttpEnum.POST:
return post
case RequestHttpEnum.PATCH:
return patch
case RequestHttpEnum.PUT:
return put
case RequestHttpEnum.DELETE:
return del
default:
return get
}
}
const prefix = 'javascript:'
// 对输入字符进行转义处理
export const translateStr = (target: string | Record<any, any>) => {
if (typeof target === 'string') {
if (target.startsWith(prefix)) {
const funcStr = target.split(prefix)[1]
let result
try {
result = new Function(`${funcStr}`)()
} catch (error) {
console.log(error)
window['$message'].error('js内容解析有误')
}
return result
} else {
return target
}
}
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const subTarget = target[key]
target[key] = translateStr(subTarget)
}
}
return target
}
// 处理 token 和多租户的头;注意:只拼接属于 VITE_DEV_PATH 或 VITE_PROD_PATH 开头的 URL 地址,就是自己的后端
export const appendTokenAndTenant = (headers: RequestParamsObjType, requestUrl: string) => {
if (requestUrl.indexOf(import.meta.env.VITE_DEV_PATH) === -1
|| requestUrl.indexOf(import.meta.env.VITE_PROD_PATH) === -1) {
return headers
}
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
if (!info) {
return headers;
}
// ① 获取 tenantId
const tenantId = info ? info[SystemStoreEnum.TENANT_INFO]['tenantId'] : undefined
if (tenantId) {
headers['tenant-id'] = tenantId
}
// ② 获取 token
const userInfo = info[SystemStoreEnum.USER_INFO]
if (!userInfo) {
return headers
}
headers[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token'] = 'Bearer ' + userInfo[SystemStoreUserInfoEnum.USER_TOKEN]
return headers
}
/**
* *
* @param targetParams
* @param globalParams
*/
export const customizeHttp = (targetParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
if (!targetParams || !globalParams) {
return
}
// 全局
const {
// 全局请求源地址
requestOriginUrl,
// 全局请求内容
requestParams: globalRequestParams
} = globalParams
// 目标组件(优先级 > 全局组件)
const {
// 请求地址
requestUrl,
// 普通 / sql
requestContentType,
// 获取数据的方式
requestDataType,
// 请求方式 get/post/del/put/patch
requestHttpType,
// 请求体类型 none / form-data / x-www-form-urlencoded / json /xml
requestParamsBodyType,
// SQL 请求对象
requestSQLContent,
// 请求内容 params / cookie / header / body: 同 requestParamsBodyType
requestParams: targetRequestParams
} = targetParams
// 静态排除
if (requestDataType === RequestDataTypeEnum.STATIC) return
if (!requestUrl) {
return
}
// 处理头部
let headers: RequestParamsObjType = {
...globalRequestParams.Header,
...targetRequestParams.Header
}
headers = translateStr(headers)
// 处理 token 和多租户的头
headers = appendTokenAndTenant(headers, requestUrl)
// data 参数
let data: RequestParamsObjType | FormData | string = {}
// params 参数
let params: RequestParamsObjType = { ...targetRequestParams.Params }
params = translateStr(params)
// form 类型处理
let formData: FormData = new FormData()
formData.set('default', 'defaultData')
// 类型处理
switch (requestParamsBodyType) {
case RequestBodyEnum.NONE:
break
case RequestBodyEnum.JSON:
headers['Content-Type'] = ContentTypeEnum.JSON
data = translateStr(JSON.parse(targetRequestParams.Body['json']))
// json 赋值给 data
break
case RequestBodyEnum.XML:
headers['Content-Type'] = ContentTypeEnum.XML
// xml 字符串赋值给 data
data = translateStr(targetRequestParams.Body['xml'])
break
case RequestBodyEnum.X_WWW_FORM_URLENCODED: {
headers['Content-Type'] = ContentTypeEnum.FORM_URLENCODED
const bodyFormData = targetRequestParams.Body['x-www-form-urlencoded']
for (const i in bodyFormData) formData.set(i, translateStr(bodyFormData[i]))
// FormData 赋值给 data
data = formData
break
}
case RequestBodyEnum.FORM_DATA: {
headers['Content-Type'] = ContentTypeEnum.FORM_DATA
const bodyFormUrlencoded = targetRequestParams.Body['form-data']
for (const i in bodyFormUrlencoded) {
formData.set(i, translateStr(bodyFormUrlencoded[i]))
}
// FormData 赋值给 data
data = formData
break
}
}
// sql 处理
if (requestContentType === RequestContentTypeEnum.SQL) {
headers['Content-Type'] = ContentTypeEnum.JSON
data = requestSQLContent
}
try {
const url = (new Function("return `" + `${requestOriginUrl}${requestUrl}`.trim() + "`"))();
return axiosInstance({
url,
method: requestHttpType,
data,
params,
headers
})
} catch (error) {
console.log(error)
window['$message'].error('URL地址格式有误')
}
}

View File

@ -0,0 +1,199 @@
{
"xAxis": [
"12a",
"1a",
"2a",
"3a",
"4a",
"5a",
"6a",
"7a",
"8a",
"9a",
"10a",
"11a",
"12p",
"1p",
"2p",
"3p",
"4p",
"5p",
"6p",
"7p",
"8p",
"9p",
"10p",
"11p"
],
"yAxis": ["Saturday", "Friday", "Thursday", "Wednesday", "Tuesday", "Monday", "Sunday"],
"seriesData": [
[0, 0, "@integer(0, 10)"],
[1, 0, "@integer(0, 10)"],
[2, 0, "-"],
[3, 0, "-"],
[4, 0, "-"],
[5, 0, "-"],
[6, 0, "-"],
[7, 0, "-"],
[8, 0, "-"],
[9, 0, "-"],
[10, 0, "-"],
[11, 0, "@integer(0, 10)"],
[12, 0, "@integer(0, 10)"],
[13, 0, "@integer(0, 10)"],
[14, 0, "@integer(0, 10)"],
[15, 0, "@integer(0, 10)"],
[16, 0, "@integer(0, 10)"],
[17, 0, "@integer(0, 10)"],
[18, 0, "@integer(0, 10)"],
[19, 0, "@integer(0, 10)"],
[20, 0, "@integer(0, 10)"],
[21, 0, "@integer(0, 10)"],
[22, 0, "@integer(0, 10)"],
[23, 0, "@integer(0, 10)"],
[0, 1, 7],
[1, 1, "-"],
[2, 1, "-"],
[3, 1, "-"],
[4, 1, "-"],
[5, 1, "-"],
[6, 1, "-"],
[7, 1, "-"],
[8, 1, "-"],
[9, 1, "-"],
[10, 1, "@integer(0, 10)"],
[11, 1, "@integer(0, 10)"],
[12, 1, "@integer(0, 10)"],
[13, 1, "@integer(0, 10)"],
[14, 1, "@integer(0, 10)"],
[15, 1, "@integer(0, 10)"],
[16, 1, "@integer(0, 10)"],
[17, 1, "@integer(0, 10)"],
[18, 1, "@integer(0, 10)"],
[19, 1, "@integer(0, 10)"],
[20, 1, "@integer(0, 10)"],
[21, 1, "@integer(0, 10)"],
[22, 1, "@integer(0, 10)"],
[23, 1, "@integer(0, 10)"],
[0, 2, 1],
[1, 2, 1],
[2, 2, "-"],
[3, 2, "-"],
[4, 2, "-"],
[5, 2, "-"],
[6, 2, "-"],
[7, 2, "-"],
[8, 2, "-"],
[9, 2, "-"],
[10, 2, "@integer(0, 10)"],
[11, 2, "@integer(0, 10)"],
[12, 2, "@integer(0, 10)"],
[13, 2, "@integer(0, 10)"],
[14, 2, "@integer(0, 10)"],
[15, 2, "@integer(0, 10)"],
[16, 2, "@integer(0, 10)"],
[17, 2, "@integer(0, 10)"],
[18, 2, "@integer(0, 10)"],
[19, 2, "@integer(0, 10)"],
[20, 2, "@integer(0, 10)"],
[21, 2, "@integer(0, 10)"],
[22, 2, "@integer(0, 10)"],
[23, 2, "@integer(0, 10)"],
[0, 3, 7],
[1, 3, 3],
[2, 3, "-"],
[3, 3, "-"],
[4, 3, "-"],
[5, 3, "-"],
[6, 3, "-"],
[7, 3, "-"],
[8, 3, 1],
[9, 3, "-"],
[10, 3, "@integer(0, 10)"],
[11, 3, "@integer(0, 10)"],
[12, 3, "@integer(0, 10)"],
[13, 3, "@integer(0, 10)"],
[14, 3, "@integer(0, 10)"],
[15, 3, "@integer(0, 10)"],
[16, 3, "@integer(0, 10)"],
[17, 3, "@integer(0, 10)"],
[18, 3, "@integer(0, 10)"],
[19, 3, "@integer(0, 10)"],
[20, 3, "@integer(0, 10)"],
[21, 3, "@integer(0, 10)"],
[22, 3, "@integer(0, 10)"],
[23, 3, "@integer(0, 10)"],
[0, 4, "@integer(0, 10)"],
[1, 4, "@integer(0, 10)"],
[2, 4, "-"],
[3, 4, "-"],
[4, 4, "-"],
[5, 4, "@integer(0, 10)"],
[6, 4, "-"],
[7, 4, "-"],
[8, 4, "-"],
[9, 4, "@integer(0, 10)"],
[10, 4, "@integer(0, 10)"],
[11, 4, "@integer(0, 10)"],
[12, 4, "@integer(0, 10)"],
[13, 4, "@integer(0, 10)"],
[14, 4, "@integer(0, 10)"],
[15, 4, "@integer(0, 10)"],
[16, 4, "@integer(0, 10)"],
[17, 4, "@integer(0, 10)"],
[18, 4, "@integer(0, 10)"],
[19, 4, "@integer(0, 10)"],
[20, 4, "@integer(0, 10)"],
[21, 4, "@integer(0, 10)"],
[22, 4, "@integer(0, 10)"],
[23, 4, "-"],
[0, 5, "@integer(0, 10)"],
[1, 5, "@integer(0, 10)"],
[2, 5, "-"],
[3, 5, "@integer(0, 10)"],
[4, 5, "-"],
[5, 5, "-"],
[6, 5, "-"],
[7, 5, "-"],
[8, 5, "@integer(0, 10)"],
[9, 5, "-"],
[10, 5, "@integer(0, 10)"],
[11, 5, "@integer(0, 10)"],
[12, 5, "@integer(0, 10)"],
[13, 5, "@integer(0, 10)"],
[14, 5, "@integer(0, 10)"],
[15, 5, "@integer(0, 10)"],
[16, 5, "@integer(0, 10)"],
[17, 5, "@integer(0, 10)"],
[18, 5, "-"],
[19, 5, "@integer(0, 10)"],
[20, 5, "@integer(0, 10)"],
[21, 5, "@integer(0, 10)"],
[22, 5, "@integer(0, 10)"],
[23, 5, "-"],
[0, 6, "@integer(0, 10)"],
[1, 6, "-"],
[2, 6, "-"],
[3, 6, "-"],
[4, 6, "-"],
[5, 6, "-"],
[6, 6, "-"],
[7, 6, "-"],
[8, 6, "-"],
[9, 6, "-"],
[10, 6, "@integer(0, 10)"],
[11, 6, "-"],
[12, 6, "@integer(0, 10)"],
[13, 6, "@integer(0, 10)"],
[14, 6, "@integer(0, 10)"],
[15, 6, "@integer(0, 10)"],
[16, 6, "-"],
[17, 6, "-"],
[18, 6, "-"],
[19, 6, "-"],
[20, 6, "@integer(0, 10)"],
[21, 6, "@integer(0, 10)"],
[22, 6, "@integer(0, 10)"],
[23, 6, "@integer(0, 10)"]
]
}

108
src/api/mock/index.ts Normal file
View File

@ -0,0 +1,108 @@
import test from './test.mock'
import { MockMethod } from 'vite-plugin-mock'
import { RequestHttpEnum } from '@/enums/httpEnum'
// 单个X数据
export const chartDataUrl = '/mock/chartData'
export const chartSingleDataUrl = '/mock/chartSingleData'
export const numberFloatUrl = '/mock/number/float'
export const numberIntUrl = '/mock/number/int'
export const textUrl = '/mock/text'
export const imageUrl = '/mock/image'
export const rankListUrl = '/mock/rankList'
export const scrollBoardUrl = '/mock/scrollBoard'
export const radarUrl = '/mock/radarData'
export const heatMapUrl = '/mock/heatMapData'
export const scatterBasicUrl = '/mock/scatterBasic'
export const mapUrl = '/mock/map'
export const capsuleUrl = '/mock/capsule'
export const wordCloudUrl = '/mock/wordCloud'
export const treemapUrl = '/mock/treemap'
export const threeEarth01Url = '/mock/threeEarth01Data'
const mockObject: MockMethod[] = [
{
// 正则
// url: /\/mock\/mockData(|\?\S*)$/,
url: chartDataUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMockData
},
{
url: chartSingleDataUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMockSingleData
},
{
url: numberFloatUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchNumberFloat
},
{
url: numberIntUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchNumberInt
},
{
url: textUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchText
},
{
url: imageUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchImage(Math.round(Math.random() * 10))
},
{
url: rankListUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchRankList
},
{
url: scrollBoardUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchScrollBoard
},
{
url: radarUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchRadar
},
{
url: heatMapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchHeatmap
},
{
url: scatterBasicUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchScatterBasic
},
{
url: mapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMap
},
{
url: capsuleUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchCapsule
},
{
url: wordCloudUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchWordCloud
},
{
url: treemapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchTreemap
},
{
url: threeEarth01Url,
method: RequestHttpEnum.GET,
response: () => test.threeEarth01Data
},
]
export default mockObject

9
src/api/mock/map.json Normal file
View File

@ -0,0 +1,9 @@
{
"markers|50": [
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@float(115, 117, 1, 6)", "@float(38, 40, 1, 6)"]
}
]
}

56
src/api/mock/scatter.json Normal file
View File

@ -0,0 +1,56 @@
[
{
"dimensions": ["data1"],
"source": [
[10.0, "@integer(0, 100)"],
[8.07, "@integer(0, 100)"],
[13.0, "@integer(0, 100)"],
[9.05, "@integer(0, 100)"],
[11.0, "@integer(0, 100)"],
[14.0, "@integer(0, 100)"],
[13.4, "@integer(0, 100)"],
[10.0, "@integer(0, 100)"],
[14.0, "@integer(0, 100)"],
[12.5, "@integer(0, 100)"],
[9.15, "@integer(0, 100)"],
[11.5, "@integer(0, 100)"],
[3.03, "@integer(0, 100)"],
[12.2, "@integer(0, 100)"],
[2.02, "@integer(0, 100)"],
[1.05, "@integer(0, 100)"],
[4.05, "@integer(0, 100)"],
[6.03, "@integer(0, 100)"],
[12.0, "@integer(0, 100)"],
[12.0, "@integer(0, 100)"],
[7.08, "@integer(0, 100)"],
[5.02, "@integer(0, 100)"]
]
},
{
"dimensions": ["data2"],
"source": [
[10.0, "@integer(0, 70)"],
[8.07, "@integer(0, 70)"],
[13.0, "@integer(0, 70)"],
[9.05, "@integer(0, 70)"],
[11.0, "@integer(0, 70)"],
[14.0, "@integer(0, 70)"],
[13.4, "@integer(0, 70)"],
[10.0, "@integer(0, 70)"],
[14.0, "@integer(0, 70)"],
[12.5, "@integer(0, 70)"],
[9.15, "@integer(0, 70)"],
[11.5, "@integer(0, 70)"],
[3.03, "@integer(0, 70)"],
[12.2, "@integer(0, 70)"],
[2.02, "@integer(0, 70)"],
[1.05, "@integer(0, 70)"],
[4.05, "@integer(0, 70)"],
[6.03, "@integer(0, 70)"],
[12.0, "@integer(0, 70)"],
[12.0, "@integer(0, 70)"],
[7.08, "@integer(0, 70)"],
[5.02, "@integer(0, 70)"]
]
}
]

223
src/api/mock/test.mock.ts Normal file
View File

@ -0,0 +1,223 @@
import heatmapJson from './heatMapData.json'
import scatterJson from './scatter.json'
import mapJson from './map.json'
import tTreemapJson from './treemap.json'
export default {
// 单图表
fetchMockSingleData: {
code: 0,
status: 200,
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne'],
'source|20': [
{
product: '@name',
'dataOne|0-900': 3
}
]
}
},
// 胶囊图
fetchCapsule: {
code: 0,
status: 200,
msg: '请求成功',
data: {
dimensions: ['name', 'value'],
"source|2-5": [
{ 'name|+1': ["厦门","福州","北京","上海","新疆","郑州","湖南","内蒙古"], 'value|0-40': 20 },
]
}
},
// 图表
fetchMockData: {
code: 0,
status: 200,
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne', 'dataTwo', 'dataThree'],
'source|20': [
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3,
'dataThree|100-900': 3
}
]
}
},
// 排名列表
fetchRankList: {
code: 0,
status: 200,
msg: '请求成功',
'data|50': [{ name: '@name', 'value|100-900': 5 }]
},
// 轮播表格
fetchScrollBoard: {
code: 0,
status: 200,
msg: '请求成功',
data: [
['行1列1', '行1列2', '1'],
['行2列1', '行2列2', '2'],
['行3列1', '行3列2', '3'],
['行4列1', '行4列2', '4'],
['行5列1', '行5列2', '5'],
['行6列1', '行6列2', '6'],
['行7列1', '行7列2', '行7列3'],
['行8列1', '行8列2', '行8列3'],
['行9列1', '行9列2', '行9列3'],
['行10列1', '行10列2', '行10列3']
]
},
// 获取数字-浮点型
fetchNumberFloat: {
code: 0,
status: 200,
msg: '请求成功',
data: '@float(0, 0.99, 1, 4)'
},
// 获取数字-整型
fetchNumberInt: {
code: 0,
status: 200,
msg: '请求成功',
data: '@integer(0, 100)'
},
// 文字
fetchText: {
code: 0,
status: 200,
msg: '请求成功',
data: '@paragraph(1, 10)'
},
// 图片
fetchImage: (num: number) => ({
code: 0,
status: 200,
msg: '请求成功',
data: `https://robohash.org/${num}`
}),
// 雷达
fetchRadar: {
code: 0,
status: 200,
msg: '请求成功',
data: {
radarIndicator: [
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 }
],
seriesData: [
{
value: [
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)'
],
name: 'data1'
},
{
value: [
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)'
],
name: 'data2'
}
]
}
},
// 热力图
fetchHeatmap: {
code: 0,
status: 200,
msg: '请求成功',
data: heatmapJson
},
// 散点图
fetchScatterBasic: {
code: 0,
status: 200,
msg: '请求成功',
data: scatterJson
},
// 中国地图
fetchMap: {
code: 0,
status: 200,
msg: '请求成功',
data: mapJson
},
// 词云
fetchWordCloud: {
code: 0,
status: 200,
msg: '请求成功',
data: [
{
name: '@name',
value: 8000,
textStyle: {
color: '#78fbb2'
},
emphasis: {
textStyle: {
color: 'red'
}
}
},
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' }
]
},
// 树图
fetchTreemap: {
code: 0,
status: 200,
msg: '请求成功',
data: tTreemapJson
},
// 三维地球
threeEarth01Data: {
code: 0,
status: 200,
msg: '请求成功',
data: [
{
startArray: { name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' },
'endArray|10': [{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' }]
}
]
}
}

50
src/api/mock/treemap.json Normal file
View File

@ -0,0 +1,50 @@
[
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 500)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 00)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
}
]

3
src/api/path/index.ts Normal file
View File

@ -0,0 +1,3 @@
export * from '@/api/path/project.api'
export * from '@/api/path/system.api'
export * from '@/api/path/infra.api'

13
src/api/path/infra.api.ts Normal file
View File

@ -0,0 +1,13 @@
import { http } from '@/api/http'
import { httpErrorHandle } from '@/utils'
import { RequestHttpEnum, ModuleTypeEnum, ContentTypeEnum } from '@/enums/httpEnum'
// * 上传文件
export const uploadFile = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)<string>(`${ModuleTypeEnum.INFRA}/file/upload`, data, ContentTypeEnum.FORM_DATA)
return res
} catch {
httpErrorHandle()
}
}

View File

@ -0,0 +1,77 @@
import { http } from '@/api/http'
import { httpErrorHandle } from '@/utils'
import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
import { ProjectItem, ProjectDetail } from './project' // TODO 分页返回,优化使用 ProjectItem
// * 项目列表
export const projectListApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.GET)<{
list: ProjectItem[],
count: number
}>(`${ModuleTypeEnum.PROJECT}/my-page`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 新增项目
export const createProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)<number>(`${ModuleTypeEnum.PROJECT}/create`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 获取项目
export const fetchProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.GET)<ProjectDetail>(`${ModuleTypeEnum.PROJECT}/get`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 保存项目
export const saveProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/update`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 修改项目基础信息
export const updateProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/update`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 删除项目
export const deleteProjectApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.DELETE)(`${ModuleTypeEnum.PROJECT}/delete`, data)
return res
} catch {
httpErrorHandle()
}
}
// * 修改发布状态 [0 已发布, 1 未发布]
export const changeProjectReleaseApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/update`, data)
return res
} catch {
httpErrorHandle()
}
}

40
src/api/path/project.d.ts vendored Normal file
View File

@ -0,0 +1,40 @@
export type ProjectItem = {
/**
* id
*/
id: string
/**
*
*/
name: string
/**
* :
*
* 0 -
* 1 -
*/
status: number
/**
*
*/
createTime: number
/**
* URL
*/
picUrl: string
/**
*
*/
creator: string
/**
*
*/
remark: string
}
export interface ProjectDetail extends ProjectItem {
/**
*
*/
content: string
}

View File

@ -0,0 +1,66 @@
import { http } from '@/api/http'
import { httpErrorHandle } from '@/utils'
import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
import {AuthLoginRespVO, ProfileVO} from './system'
// * 登录
export const loginApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)<AuthLoginRespVO>(`${ModuleTypeEnum.SYSTEM}/auth/login`, data)
console.log(res)
return res
} catch (err) {
httpErrorHandle()
}
}
// * 登出
export const logoutApi = async () => {
try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/auth/logout`)
return res
} catch (err) {
httpErrorHandle()
}
}
// 查询用户个人信息
export const getUserProfileApi = async () => {
try {
const res = await http(RequestHttpEnum.GET)<ProfileVO>(`${ModuleTypeEnum.SYSTEM}/user/profile/get`)
return res
} catch (err) {
httpErrorHandle()
}
}
// 获取验证图片 以及token
export const getCodeApi = async (data: any) => {
try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/captcha/get`, data)
return res.data
} catch (err) {
httpErrorHandle()
}
}
// 滑动或者点选验证
export const reqCheckApi = async (data: any) => {
try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/captcha/check`, data)
return res.data
} catch (err) {
httpErrorHandle()
}
}
// 使用租户名,获得租户编号
export const getTenantIdByNameApi = async (name: string) => {
try {
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/tenant/get-id-by-name?name=` + name)
return res
} catch (err) {
httpErrorHandle()
}
}

23
src/api/path/system.d.ts vendored Normal file
View File

@ -0,0 +1,23 @@
export interface AuthLoginRespVO {
/**
*
*/
userId: number
/**
* 访
*/
accessToken: string
/**
*
*/
refreshToken: string
/**
*
*/
expiresTime: number
}
export interface ProfileVO {
id: number
nickname: string
}

255
src/assets/images/Error.svg Normal file
View File

@ -0,0 +1,255 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px"
viewBox="0 0 600 600" enable-background="new 0 0 600 600" xml:space="preserve">
<g id="LEFT_ARM_1">
<g id="XMLID_46_">
<path id="XMLID_290_" fill="#FFB96C" d="M294.4,485.5c-1.2,0.3-2.4,0.4-3.6,0.4c-0.2,0-0.4,0-0.6,0c-8.4-0.3-16.2-6.9-21-15.7
c-21.3-39.2-27.1-63.4-34.8-89.9c-1.9-6.6-1.4-13.3,1.4-18.1c2.2-3.7,5.7-6.4,10.5-6.9c0.6-0.1,1.1-0.1,1.7-0.1
c8.5,0,17.4,6.8,20.9,15.6l36.5,89.4C310,471.5,305,483.1,294.4,485.5z"/>
<path id="XMLID_280_" fill="#FCAF63" d="M290.2,485.9c-8.4-0.3-16.2-6.9-21-15.7c-21.3-39.2-27.1-63.4-34.8-89.9
c-1.9-6.6-1.4-13.3,1.4-18.1c9.5,23,40.7,98.5,50.3,116.1C287.6,481.1,289,483.6,290.2,485.9z"/>
</g>
</g>
<g id="LEFT_ARM_2">
<g id="XMLID_10_">
<g id="XMLID_42_">
<path id="XMLID_293_" fill="#FFB96C" d="M340.2,472c-0.9,2.3-2.1,4.1-3.3,5c-7.2,5.7-14.3,7-26.2,9.6c-11.9,2.6-24.2,2-29.9-3.4
c-1.9-1.8-3.3-3.8-4.1-5.9c-2.5-6-0.3-12.3,6.8-15c4.2-1.6,42.4-10.6,48.7-9.4C343.1,455,342.9,465.3,340.2,472z"/>
<path id="XMLID_279_" fill="#FCAF63" d="M340.2,472c-0.9,2.3-2.1,4.1-3.3,5c-7.2,5.7-14.3,7-26.2,9.6c-11.9,2.6-24.2,2-29.9-3.4
c-1.9-1.8-3.3-3.8-4.1-5.9c3.2,0.9,9.6,2.1,20.5,0.9C306.4,477.2,325.3,474.3,340.2,472z"/>
</g>
<g id="XMLID_41_">
<path id="XMLID_49_" fill="#FEA691" d="M330.2,453.6c-11.9,4-10.6,11.9-8.8,19.6c1.8,7.7,16.6,27.5,21.1,28.5s4.8-0.8,3.6-4.5
c-1.2-3.7-9.7-16.6-9.7-16.6s9.4,12.8,13.3,16.6c3.9,3.8,7.2,3.5,7.1-0.7c-0.2-4.2-9.5-18.3-9.5-18.3s8.2,10.8,11.6,14.5
s7.9,3.1,6.3-1.9c-1.5-5-8.3-15.9-8.3-15.9s6.6,11,11,12.1c4.4,1.1,1.7-5.5-3-13.9C360.3,464.5,345,448.6,330.2,453.6z"/>
<path id="XMLID_50_" fill="#FEA691" d="M320.2,464.6c0,0-2.5,9.8-0.9,18.4s4.3,10.3,6.1,10.7s2.4-1.9,1.5-5.6
c-0.9-3.7,1.5-11,1.5-11S325.8,462.4,320.2,464.6z"/>
</g>
</g>
</g>
<g id="BODY">
<g id="XMLID_70_">
<path id="XMLID_45_" fill="#FEC272" d="M273.1,496H172.2c0,0-13.9-97.2-5.1-121.1c2.5-6.8,5.8-12.3,9.6-16.9
c9.5-11.6,21.7-16.9,30-19c10.9-2.8,20.4-2.9,28.6-0.9c21.8,5.2,33.9,25.1,37.8,46.8C278.5,414.8,273.1,496,273.1,496z"/>
<path id="XMLID_43_" fill="#F9B35F" d="M207.6,358.5c-13.2,3.4-25.3,3-31-0.5c9.5-11.6,21.7-16.9,30-19
c10.9-2.8,20.4-2.9,28.6-0.9C237,344.9,224.6,354.1,207.6,358.5z"/>
</g>
</g>
<g id="RIGHT_ARM_1">
<g id="XMLID_16_">
<path id="XMLID_278_" fill="#FFCD92" d="M199,381.3c0,1.6-0.1,3.2-0.4,4.7c-4.1,26.6-27.7,90.6-27.7,90.6c-1.7,5.1-5.3,8.9-9.7,11
c-4.4,2-9.5,2.4-14.4,0.5c-7.6-3-11.2-10.2-11.2-18.1c0-1.7,0.2-3.4,0.5-5.1c6.9-37.3,19.2-68.2,29.3-90
c4.4-9.6,15.2-15.6,24.7-10.8c2.9,1.4,4.9,3.7,6.4,6.3C198.3,373.6,199,377.4,199,381.3z"/>
<path id="XMLID_273_" fill="#FCB765" d="M199,381.3c0,1.6-0.1,3.2-0.4,4.7c-4.1,26.6-27.7,90.6-27.7,90.6c-1.7,5.1-5.3,8.9-9.7,11
l35.2-117.3C198.3,373.6,199,377.4,199,381.3z"/>
</g>
</g>
<g id="RIGHT_ARM_2">
<g id="XMLID_17_">
<g id="XMLID_20_">
<path id="XMLID_285_" fill="#FFCD92" d="M230.5,487.4c-2.2,5.4-9.4,5.6-9.4,5.6s-20.2,1.2-37.7,1.2c-17.5,0-34.7,0-41.7-7.9
c-1.4-1.6-2.5-3.4-3.1-5.3c-2.6-7.3,0.7-16,11.1-20.4c7.5-3.2,16.1-2.1,25.5-1.2c9.4,0.9,27.5,5.1,38,7.9
c10.6,2.7,16.9,5.4,17.8,15.4C231.3,484.6,231,486.1,230.5,487.4z"/>
<path id="XMLID_284_" fill="#FCB765" d="M230.5,487.4c-2.2,5.4-9.4,5.6-9.4,5.6s-20.2,1.2-37.7,1.2c-17.5,0-34.7,0-41.7-7.9
c-1.4-1.6-2.5-3.4-3.1-5.3c7.8,2.4,18.3,5.2,26.7,5.9C189,488.9,220.4,487.9,230.5,487.4z"/>
</g>
<g id="XMLID_2_">
<g id="XMLID_18_">
<path id="XMLID_47_" fill="#FEA691" d="M251.6,471.3c0,1.6-0.2,3.3-0.6,5.1c-2.1,8.6-13.2,15.2-30.1,16.1
c-7.5,0.4-12.6,0.4-16-0.4c-4.4-1.1-6.1-3.7-6.5-9.1c-0.5-6.9,4.7-13.2,8.6-15.9c11.7-7.9,22.6-8.5,32.1-7.6
C247.6,460.4,251.5,465.1,251.6,471.3z"/>
<path id="XMLID_44_" fill="#FC8172" d="M251.6,471.3c0,1.6-0.2,3.3-0.6,5.1c-2.1,8.6-13.2,15.2-30.1,16.1
c-7.5,0.4-12.6,0.4-16-0.4c-0.4-1-0.7-2.2-0.8-3.7c-0.5-5.9,4.4-11.4,8.2-13.7c11.1-6.8,21.5-7.4,30.5-6.5
C246.8,468.5,249.7,469.6,251.6,471.3z"/>
</g>
<g id="XMLID_19_">
<path id="XMLID_48_" fill="#C7DCF9" d="M264.7,488.7c0,1.1-0.2,2.1-0.5,3.2h-55c-0.3-1-0.5-2.1-0.5-3.2c0-9.6,12.5-17.4,28-17.4
C252.2,471.3,264.7,479.1,264.7,488.7z"/>
<path id="XMLID_254_" opacity="0.55" fill="#C7DCF9" d="M263.5,490.2c0,0.6-0.1,1.1-0.4,1.7h-50.3c-0.3-0.6-0.4-1.1-0.4-1.7
c0-5.1,11.4-9.3,25.5-9.3C252.1,480.9,263.5,485.1,263.5,490.2z"/>
</g>
<g id="XMLID_37_">
<path id="XMLID_28_" fill="#FEA691" d="M252.6,456.6c3.6,0.4,6.1,2.7,7.5,7.5c1.4,4.8,1.7,11.9,0.2,14.4
c-1.5,2.5-4.3,3.6-7.4,1.1c-3.1-2.5-4.8-9.5-5.8-13C245.9,462,244.5,455.8,252.6,456.6z"/>
<g id="XMLID_4_">
<path id="XMLID_38_" fill="#FEA691" d="M239.2,454.3c3.9,0.4,5.5,3.7,7,8.7c1.5,5,1.8,12.6,0.2,15.3c-1.6,2.6-4.6,3.8-7.9,1.2
c-3.3-2.6-5.2-10.1-6.2-13.8C231,460.8,230.4,453.5,239.2,454.3z"/>
<path id="XMLID_79_" fill="#FF8D76" d="M243.1,480.8c-1.4,0.3-3,0-4.6-1.4c-3.3-2.6-5.1-10.1-6.2-13.8c-1.1-4-1.7-9.7,3-11.1
c-0.9,2.7-0.4,6.4,0.3,9.2c1,4.3,2.9,13,6.2,16C242.3,480.2,242.7,480.6,243.1,480.8z"/>
</g>
<path id="XMLID_39_" fill="#FEA691" d="M224.6,456.6c3.9,0.4,6.5,2.9,8,7.9s1.8,12.6,0.2,15.3c-1.6,2.6-4.6,3.8-7.9,1.2
c-3.3-2.6-5.2-10.1-6.2-13.8C217.4,462.3,215.9,455.7,224.6,456.6z"/>
<path id="XMLID_81_" fill="#FF8D76" d="M228.5,482.4c-1.1,0-2.3-0.5-3.5-1.5c-3.3-2.6-5.1-10.1-6.2-13.8
c-1-3.8-2.2-8.6,1.5-10.2c-0.3,2.5,0.4,5.7,1.1,8.3c1.2,4.5,3.3,13.7,7,17C228.4,482.4,228.4,482.4,228.5,482.4z"/>
<path id="XMLID_40_" fill="#FEA691" d="M211.5,459.4c3.4-1,6,2.7,7.3,7.3c1.3,4.6,1.7,11.6,0.2,14c-1.4,2.4-4.2,3.5-7.2,1.1
c-3-2.4-3.8-7-4.7-10.4C205.9,467,204.9,461.4,211.5,459.4z"/>
<path id="XMLID_82_" fill="#FF8D76" d="M215.2,483.2c-1.1,0-2.2-0.4-3.4-1.4c-3-2.4-3.8-7-4.7-10.4c-1.1-3.8-1.9-8.5,2.1-11
c-0.3,2.7,0.2,5.6,0.7,8.2c0.9,4.6,1.6,10.9,5,14.3C215,483,215.1,483.1,215.2,483.2z"/>
<path id="XMLID_78_" fill="#FF8D76" d="M256.8,480.9c-1.2,0.1-2.5-0.3-3.8-1.4c-3.1-2.5-4.8-9.5-5.8-13c-1-3.7-2.2-8.5,1.8-9.7
c0,2.2,0.5,4.7,1,6.9c1,4.5,2.9,13.5,6.1,16.7C256.4,480.6,256.6,480.8,256.8,480.9z"/>
</g>
</g>
</g>
</g>
<g id="HEAD">
<g id="XMLID_89_">
<path id="XMLID_6_" fill="#FF8D76"
d="M208.8,235c0,0,9.3-3.8,15.6,8.8c6.3,12.7-0.5,20.8-0.5,20.8S217.7,246.3,208.8,235z"/>
<path id="XMLID_173_" fill="#FEA691" d="M215.2,350.9c-8.8,4.1-14.9-1.6-14.9-1.6l-5.5-11.9l-9.9-21.4c14.9-3.2,27.9-5.7,27.9-5.7
l2.3,9.5l4.3,17.7C219.2,337.6,224,346.9,215.2,350.9z"/>
<path id="XMLID_171_" fill="#FF8D76" d="M215,319.9c-1.3,1.9-2.7,3.9-4.4,5.8c-4.3,5.1-10.5,9-15.9,11.7l-9.9-21.4
c14.9-3.2,27.9-5.7,27.9-5.7L215,319.9z"/>
<ellipse id="XMLID_3_" transform="matrix(0.8545 -0.5194 0.5194 0.8545 -114.0092 131.008)"
fill="#FEA691" cx="176.9" cy="269" rx="47.2" ry="57.7"/>
<path id="XMLID_12_" fill="#FF8D76" d="M217.4,308.8c-2.9,3.7-6.5,6.9-10.6,9.5c-22.3,13.5-53.7,2.4-70.3-24.8
c-16.4-26.9-12-59.6,9.7-73.4c-12.6,16.2-13.2,42.2,0.3,64.3c16.5,27.2,48,38.3,70.3,24.8C217,309.1,217.2,309,217.4,308.8z"/>
<path id="XMLID_5_" fill="#283575" d="M157.2,309.5c0,0-17-13.4-21.3-37.4s0.5-33.7,20.2-45.3c19.7-11.5,34.4-7.4,34.4-7.4
s-14-10.5-36.9-6.6c-22.9,3.8-46.2,25.6-41.4,58.4C117.2,306.2,138,316.5,157.2,309.5z"/>
<path id="XMLID_11_" fill="#F76F59" d="M177.8,246.8c-2.7,1.9,1.1,12,9.3,19.5c8.2,7.5,16.1,3.6,16.3-3.8
C203.6,254.9,187.1,240.2,177.8,246.8z"/>
<path id="XMLID_7_" fill="#FF8D76"
d="M137.5,291.4c0,0-16,15.7-1.6,29.4c13.8,13.1,31.2-4.5,31.2-4.5S142.7,303.2,137.5,291.4z"
/>
<path id="XMLID_250_" fill="#F76F59"
d="M139.4,300.5c0,0-9,8.8-0.9,16.6c7.8,7.4,17.6-2.5,17.6-2.5S142.3,307.2,139.4,300.5z"/>
</g>
</g>
<g id="HAIR">
<g id="XMLID_84_">
<path id="XMLID_8_" fill="#283575" d="M188.5,218.1c0,0,1.7-30.2-15.5-42.5c-19.4-13.8-30.3,6.1-23.9,22.4
c2.8,7.3,5.8,11.7,8.2,14.3c2.2,2.4,5.2,3.8,8.4,4L188.5,218.1z"/>
<path id="XMLID_9_" fill="#283575" d="M122.7,192.6c-15.3,12.2-2.1,29.7,4.2,34.4c2.7,2,5.6,3.6,8.1,4.8c3.4,1.6,7.4,1.4,10.6-0.6
l21.6-13.7C167.2,217.6,143,176.5,122.7,192.6z"/>
<path id="XMLID_51_" fill="#3C4E8E"
d="M159,172.3c-4.8,0.6,0.5,9.8,7.5,11S171.3,170.8,159,172.3z"/>
<path id="XMLID_61_" fill="#3C4E8E"
d="M128.7,192.8c-2.8,3.2,4.5,7.3,10.4,5.3C145.1,196.2,134.9,185.8,128.7,192.8z"/>
</g>
</g>
<g id="MOUTH">
<g id="XMLID_83_">
<path id="XMLID_177_" fill="#F76F59" d="M217.7,285c-0.5,1-1.2,1.9-2.2,2.7c-3.7,2.9-6.5,7.1-8.5,11.5c-1.8,3.9-6.4,8.5-10.7,5.2
c-0.5-0.4-1-0.8-1.4-1.4c-4.5-5.7-2.8-20.4,4.2-26.9c5.4-5,12.1-3.7,15.5-0.9C217.9,277.7,219.3,281.7,217.7,285z"/>
<path id="XMLID_175_" fill="#FF6EA9" d="M217.7,285c-0.5,1-1.2,1.9-2.2,2.7c-3.7,2.9-6.5,7.1-8.5,11.5c-1.8,3.9-6.4,8.5-10.7,5.2
c0-6.3,2.3-13.7,6.7-17.7C208.1,282.1,214.1,282.7,217.7,285z"/>
</g>
</g>
<g id="EYE_1">
<g id="XMLID_14_">
<path id="XMLID_86_" fill="#1C3177" d="M155.8,267.7c-3.2,0-5.7-1-5.9-1.1c-1.3-0.5-1.9-2-1.4-3.3c0.5-1.3,2-1.9,3.3-1.4
c0.1,0,5.6,2.2,8.6-1.1c3.9-4.1-0.2-9.4-0.3-9.6c-0.9-1.1-0.7-2.7,0.4-3.6c1.1-0.9,2.7-0.7,3.6,0.4c2.4,3.1,5.5,10.4,0,16.2
C161.6,266.9,158.5,267.7,155.8,267.7z"/>
</g>
</g>
<g id="EYE_2">
<g id="XMLID_15_">
<path id="XMLID_85_" fill="#1C3177" d="M193,242.6c-5.1,0-9.4-3.8-9.7-4c-1.1-0.9-1.1-2.6-0.2-3.6c0.9-1,2.5-1.1,3.6-0.2
c0,0,4.6,3.9,8,2.4c1.5-0.7,0.4-3.8,0.3-3.9c-0.5-1.3,0.1-2.8,1.5-3.3c1.3-0.5,2.8,0.1,3.3,1.4c1.5,3.7,1.1,8.6-3,10.4
C195.5,242.4,194.2,242.6,193,242.6z"/>
</g>
</g>
<g id="EYEBROW_1">
<g id="XMLID_1_">
<path id="XMLID_88_" fill="#1C3177" d="M142.4,261.7c-0.1,0-0.2,0-0.3,0c-1.4-0.2-2.4-1.4-2.3-2.8c0-0.3,0.7-6.3,4.9-12.4
c4.1-6.1,8.3-8.2,8.5-8.3c1.3-0.6,2.8-0.1,3.4,1.2c0.6,1.3,0.1,2.8-1.2,3.4c0,0-3.2,1.7-6.5,6.5c-3.4,5-4,10-4,10.1
C144.8,260.7,143.7,261.7,142.4,261.7z"/>
</g>
</g>
<g id="EYEBROW_2">
<g id="XMLID_13_">
<path id="XMLID_87_" fill="#1C3177" d="M179,232.1c-0.7,0-1.5-0.3-2-0.9c-0.9-1.1-0.7-2.7,0.4-3.6c0.3-0.2,2.6-2.1,6.7-3.3
c4.1-1.2,7.5-1.1,7.6-1.1c1.4,0,2.5,1.2,2.5,2.6c0,1.4-1.3,2.5-2.6,2.5c0,0-2.7-0.1-6,0.9c-3.2,1-5,2.4-5,2.4
C180.1,231.9,179.6,232.1,179,232.1z"/>
</g>
</g>
<g id="TABLE">
<g id="XMLID_248_">
<path id="XMLID_22_" fill="#99ADF9" d="M505.9,506.3H98.3c-4,0-7.2-3.2-7.2-7.2l0,0c0-4,3.2-7.2,7.2-7.2h407.6
c4,0,7.2,3.2,7.2,7.2l0,0C513.1,503,509.9,506.3,505.9,506.3z"/>
<path id="XMLID_198_" fill="#789FEF" d="M505.2,506.3H157.1c-4,0-7.2-3.2-7.2-7.2l0,0c0-4,3.2-7.2,7.2-7.2h348.1
c4,0,7.2,3.2,7.2,7.2l0,0C512.5,503,509.2,506.3,505.2,506.3z"/>
</g>
</g>
<g id="DESKTOP">
<g id="XMLID_186_">
<g id="XMLID_182_">
<path id="XMLID_25_" fill="#E1ECFF" d="M457.6,444.7h-186c-3.3,0-5.9-3-5.3-6.3l19.8-118.7c0.4-2.6,2.7-4.5,5.3-4.5h186
c3.3,0,5.9,3,5.3,6.3L463,440.2C462.5,442.8,460.3,444.7,457.6,444.7z"/>
<path id="XMLID_29_" fill="#C7DCF9" d="M461.6,444.7H278c-3.3,0-5.9-3-5.3-6.3l19.8-118.7c0.4-2.6,2.7-4.5,5.3-4.5h183.6
c3.3,0,5.9,3,5.3,6.3l-19.8,118.7C466.5,442.8,464.2,444.7,461.6,444.7z"/>
<path id="XMLID_31_" fill="#B7D4F7" d="M442.2,432H302c-2.6,0-4.5-2.3-4.1-4.8l15.1-90.6c0.3-2,2.1-3.5,4.1-3.5h140.1
c2.6,0,4.5,2.3,4.1,4.8l-15.1,90.6C445.9,430.5,444.2,432,442.2,432z"/>
</g>
<g id="XMLID_183_">
<path id="XMLID_24_" fill="#E1ECFF" d="M382.3,484.5h-25.5c-2.4,0-4.2-2-4-4.4l6.7-66.5c0.2-2,1.9-3.6,4-3.6H389
c2.4,0,4.2,2,4,4.4l-6.7,66.5C386.1,483,384.4,484.5,382.3,484.5z"/>
<path id="XMLID_26_" fill="#C7DCF9" d="M384.1,484.5h-23.4c-1.5,0-2.7-1.3-2.6-2.8l7-69.4c0.1-1.3,1.2-2.3,2.6-2.3h23.4
c1.5,0,2.7,1.3,2.6,2.8l-7,69.4C386.5,483.5,385.4,484.5,384.1,484.5z"/>
</g>
<g id="XMLID_185_">
<path id="XMLID_27_" fill="#E1ECFF" d="M424.7,491.8H318.5c-2.2,0-4-1.8-4-4V479c0-2.2,1.8-4,4-4h106.2c2.2,0,4,1.8,4,4v8.8
C428.7,490,426.9,491.8,424.7,491.8z"/>
<path id="XMLID_30_" fill="#C7DCF9" d="M426.9,491.8H327c-2.3,0-4.2-1.9-4.2-4.2v-8.4c0-2.3,1.9-4.2,4.2-4.2h99.9
c2.3,0,4.2,1.9,4.2,4.2v8.4C431,489.9,429.2,491.8,426.9,491.8z"/>
</g>
</g>
</g>
<g id="SIGN">
<g id="XMLID_21_">
<path id="XMLID_77_" fill="#FF97C9" d="M501.5,298.7c-1,0.7-2.3,1.2-3.7,1.2H402c-4.8,0-7.8-5-5.6-9.3l34.8-66.9l12.8-24.6
c2.4-4.5,8.8-4.5,11.2,0l48.2,91.5C505,293.6,503.9,297,501.5,298.7z"/>
<path id="XMLID_74_" fill="#FC72BB" d="M501.5,298.7c-1,0.7-2.3,1.2-3.7,1.2H402c-4.8,0-7.8-5-5.6-9.3l34.8-66.9L420.6,280
c-0.9,4.8,2.4,9.3,7.3,9.9L501.5,298.7z"/>
<g id="XMLID_32_">
<g id="XMLID_34_">
<path id="XMLID_35_" fill="#FFFFFF" d="M445.2,264.1l-5-35.8c-0.2-1.2,0.8-2.3,2-2.3h14.2c1.2,0,2.1,1.1,2,2.3l-5,35.8
c-0.1,1-1,1.7-2,1.7h-4.3C446.1,265.9,445.3,265.1,445.2,264.1z"/>
</g>
<circle id="XMLID_33_" fill="#FFFFFF" cx="449.3" cy="279.1" r="7.1"/>
</g>
</g>
</g>
<g id="STAR">
<path id="XMLID_195_" fill="#FEC272" d="M189.7,141.2l1.8,3.7c0.2,0.5,0.7,0.8,1.2,0.8l4,0.6c1.3,0.2,1.8,1.7,0.8,2.6l-2.9,2.8
c-0.4,0.4-0.5,0.9-0.4,1.4l0.7,4c0.2,1.2-1.1,2.2-2.2,1.6l-3.6-1.9c-0.4-0.2-1-0.2-1.4,0l-3.6,1.9c-1.1,0.6-2.4-0.4-2.2-1.6l0.7-4
c0.1-0.5-0.1-1-0.4-1.4l-2.9-2.8c-0.9-0.9-0.4-2.4,0.8-2.6l4-0.6c0.5-0.1,0.9-0.4,1.2-0.8l1.8-3.7
C187.5,140.1,189.1,140.1,189.7,141.2"/>
</g>
<g id="BUBBLE_1">
<path id="XMLID_23_" fill="#F0F6FF" d="M384.3,170.2c0,13.8-4,26.6-10.9,37.5c0,0,0,0,0,0c-2.5,5.8-15.1,30.3-57.9,49.9
c-44.9,20.6-84.7,5.9-84.7,5.9s24.5-16.1,19.9-43c-3.6-21.2-6.1-36.4-5.9-49.2c0-0.4,0-0.7,0-1.1c0-38.5,31.2-69.7,69.7-69.7
S384.3,131.7,384.3,170.2z"/>
</g>
<g id="BUBBLE_2">
<path id="XMLID_187_" fill="#C7DCF9" d="M238.1,216.5c-3.7-9.5-7.4-9.1-9.9-7.3c-2.3,1.7-2.8,7.6,0,13.2s5.6,5.2,8.4,3.7
S239.8,220.9,238.1,216.5z"/>
</g>
<g id="BUBBLE_3">
<path id="XMLID_249_" fill="#C7DCF9" d="M361.6,237.5c-15.4,8.2-14,14.5-10.4,18.3c3.4,3.6,13.5,3.2,22.4-2.6s7.8-10.5,4.7-15
C375.2,233.7,368.7,233.6,361.6,237.5z"/>
</g>
<g id="Layer_23">
<g id="XMLID_75_">
<g id="XMLID_73_">
<path id="XMLID_274_" fill="#99ADF9" d="M364.6,191.8c0,3.8-1.8,7.6-5.2,9.9c-7.4,5.2-19.2,12.9-32.2,19.7
c-8.3,4.4-15.5,7.8-21.3,10.3c-4.8,2.1-10.1,1.7-14.4-0.7c-2.9-1.6-5.3-4.1-6.8-7.3c-1-2.2-1.6-4.6-1.6-7c0-2,0.4-4,1.1-6
l0.4-1.1l17.2-43.6l-23,12.4c-6.4,3.4-14.3,1.2-18-5.1c-0.1-0.2-0.2-0.4-0.3-0.6c-1-2-1.5-4.1-1.5-6.2c0-4.4,2.2-8.8,6.2-11.3
c7.3-4.7,17.9-11.1,30.5-17.8c24.2-12.9,36.2-11.3,39.6-4.8c3.4,6.6-16.1,61.8-16.1,61.8s26.1-13.1,28.9-14.1
c6-2.3,12.7,0.5,15.4,6.3c0.6,1.3,0.9,2.7,1,4.1C364.6,191.2,364.6,191.5,364.6,191.8z"/>
<path id="XMLID_267_" fill="#7D9AF9" d="M309.1,158.8c-5.8,14.3-19.5,47.2-24.3,50.9l17.2-43.6l-23,12.4
c-6.4,3.5-14.5,1.2-18.1-5.2c0.2-0.2,0,0,0.2-0.2c2.3,1.1,6.4,2.1,12.5-0.9c11.4-5.4,24.4-12.5,31.9-16.6
C307.6,154.5,310,156.6,309.1,158.8z"/>
<path id="XMLID_264_" fill="#7D9AF9" d="M364.6,191.8c0,3.8-1.8,7.6-5.2,9.9c-7.4,5.2-19.2,12.9-32.2,19.7
c-8.3,4.4-15.5,7.8-21.3,10.3c-4.8,2.1-10.1,1.7-14.4-0.7c0.9-0.2,1.8-0.4,2.6-0.7c4.5-1.5,24.8-12.2,44.7-22.9
c13-7,21.8-12.6,25.7-16.4C364.6,191.2,364.6,191.5,364.6,191.8z"/>
</g>
<path id="XMLID_76_" opacity="0.49" fill="#FFFFFF" d="M314.2,131.6c-9,3-13.6,8.6-2.8,8s16.5-6.1,14.6-7.9
C324.1,130,318.3,130.2,314.2,131.6z"/>
<path id="XMLID_80_" opacity="0.49" fill="#FFFFFF" d="M348.7,182.6c-5.7,1.9-8.7,5.5-1.8,5.1c6.9-0.4,10.5-3.9,9.3-5
C354.9,181.6,351.3,181.7,348.7,182.6z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

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