main
wuyufei 2023-01-05 16:12:46 +08:00
parent ff12a14fae
commit d033deae77
59 changed files with 13170 additions and 124 deletions

2
.env.development 100644
View File

@ -0,0 +1,2 @@
VITE_BASE_URL = "./"
VITE_BASE_API_URL = "/api"

2
.env.production 100644
View File

@ -0,0 +1,2 @@
VITE_BASE_URL = "/"
VITE_BASE_API_URL = ""

3
.eslintignore 100644
View File

@ -0,0 +1,3 @@
dist
node_modules
!.prettierrc.js

136
.gitignore vendored
View File

@ -1,132 +1,24 @@
# ---> Node
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
node_modules
dist
dist-ssr
*.local
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

21
.prettierignore 100644
View File

@ -0,0 +1,21 @@
## OS
.DS_Store
.idea
.editorconfig
pnpm-lock.yaml
.npmrc
# Ignored suffix
*.log
*.md
*.svg
*.png
*.ico
*ignore
## Local
.husky
## Built-files
.cache
dist

43
.prettierrc.js 100644
View File

@ -0,0 +1,43 @@
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,
// 换行符使用 crlf
endOfLine: "crlf",
// 格式化嵌入的内容
embeddedLanguageFormatting: "auto",
// html, vue, jsx 中每个属性占一行
singleAttributePerLine: false,
};

3
.vscode/extensions.json vendored 100644
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

View File

@ -1,3 +1,17 @@
# vue3-template
# 通用模板
vue3脚手架
使用 vue3、pinia、axios、echarts、elementPlus
- 其中大量使用 vue3 的 setup 函数书写、同时支持 jsx 写法;但保留灵活性并不引入 typescript
- 使用 pinia 代替了 vue2 中的 vuex 来做数据管理;
- svg 图片使用的是 vite-plugin-svg-icons 插件进行管理,将需要的 svg 文件放入`src/icons`中即可
- 依然使用 axios 作为请求数据,数据请求都集中在`src/api`下进行管理,并已经进行了封装,在此基础继续封装即可
- 使用 echarts 进行图表的显示
- UI 主要遵从 elementPlus组件语言已设置为中文
- css 预渲染为 less
## 启动前须知
- 安装 ESlint 插件
- 安装代码风格插件 Prettier 安装结束后配置好就行
- 因为使用 vue3 所以使用 volar 插件

13
index.html 100644
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="zh-cn" class="dark">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>中化石油销售有限公司智慧HSE平台</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

8
jsconfig.json 100644
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@/*": ["*"],
},
},
}

7196
package-lock.json generated 100644

File diff suppressed because it is too large Load Diff

40
package.json 100644
View File

@ -0,0 +1,40 @@
{
"name": "panel-demo",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@element-plus/icons-vue": "^2.0.10",
"axios": "^1.2.0",
"dayjs": "^1.11.7",
"echarts": "^5.4.1",
"element-plus": "^2.2.26",
"pinia": "^2.0.27",
"vue": "^3.2.41",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue-jsx": "^2.1.1",
"eslint": "^8.30.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-define-config": "^1.12.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.8.0",
"fast-glob": "^3.2.12",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"prettier": "^2.8.1",
"vite": "^3.2.3",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vue-eslint-parser": "^9.1.0"
}
}

1
public/logo.svg 100644

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

29
src/App.vue 100644
View File

@ -0,0 +1,29 @@
<script setup>
import { RouterView } from "vue-router";
</script>
<template>
<router-view v-slot="{ Component }">
<transition name="slide-fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</template>
<style lang="less">
.slide-fade-enter-active {
transition: all 0.3s ease-out;
}
.slide-fade-leave-active {
transition: all 0.1s;
}
.slide-fade-enter-from,
.slide-fade-leave-to {
opacity: 0.1;
}
.slide-fade-enter-to, .slide-fade-leave-from {
opacity: 1;
}
</style>

11
src/api/base.js 100644
View File

@ -0,0 +1,11 @@
import request from "@/utils/request";
// 登录
export const doLogin = (data) => request.post("/base/login", data);
// 注册
export const doRegister = (data) => request.post("/base/register", data);
// 获取用户自己信息
export const getUserInfo = (params) =>
request.get("/user/getUserInfo", { params });

50
src/api/home.js 100644
View File

@ -0,0 +1,50 @@
import request from "@/utils/request";
// HSE观察统计
export const getgctj = () =>
request.post("/bigdata/analysis/service/chart/data", {
type: 1,
analysisId: "1671182746237",
owner: "u4000000012732737",
conditions: [],
});
// 问题对应隐患类型占比
export const getlxzb = () =>
request.post("/bigdata/analysis/service/chart/data", {
type: 1,
analysisId: "1671183106247",
owner: "u4000000012732737",
conditions: [],
});
// HSE人数统计
export const getrstj = () =>
request.post("/bigdata/analysis/service/chart/data", {
type: 1,
analysisId: "1671183187310",
owner: "u4000000012732737",
conditions: [],
});
// HSE要素排名
export const getyspm = () =>
request.post("/bigdata/analysis/service/chart/data", {
type: 1,
analysisId: "1671183449923",
owner: "u4000000012732737",
conditions: [],
});
// 企业HSE观察数量排名
export const getslpm = () =>
request.post("/bigdata/analysis/service/chart/data", {
type: 1,
analysisId: "1671184401230",
owner: "u4000000012732737",
conditions: [],
});
// 人员位置
export const getrywz = () =>
request.post("/bigdata/analysis/service/chart/data", {
type: 1,
analysisId: "1671517738564",
owner: "u4000000012732737",
conditions: [],
});

5
src/api/user.js 100644
View File

@ -0,0 +1,5 @@
import request from "@/utils/request";
// 注册
export const doRegister = (data) => request.post("/base/register", data);

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,59 @@
<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from 'echarts';
// dom "myChart"
const chartDom = ref()
let myChart = null;
const props = defineProps({
option: Object,
chartType: {
type: String,
default: 'dark'
}
})
//
const resizeHandler = () => {
myChart.resize();
}
//
const debounce = (fun, delay) => {
let timer;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fun();
}, delay);
}
};
const cancalDebounce = debounce(resizeHandler, 500);
//
onMounted(() => {
// svg 使 Canvas
myChart = echarts.init(chartDom.value, props.chartType )
myChart.setOption(props.option, true);
//
window.addEventListener('resize', cancalDebounce);
})
//
onBeforeUnmount(() => {
window.removeEventListener('resize', cancalDebounce)
myChart.dispose()
})
//
watch(() => props.option, () => {
myChart.setOption(props.option, true);
}, { deep: true })
</script>
<template>
<div class="echart" ref="chartDom"></div>
</template>
<style lang="less" scoped>
.echart {
width: 100%;
height: 100%
}
</style>

View File

@ -0,0 +1,35 @@
<template>
<svg aria-hidden="true" class="svg-icon" :width="props.size" :height="props.size">
<use :xlink:href="symbolId" :fill="props.color" />
</svg>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
prefix: {
type: String,
default: 'icon'
},
name: {
type: String,
required: true
},
color: {
type: String,
default: '#333'
},
size: {
type: String,
default: '1em'
}
})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>
<style scoped>
.svg-icon {
display: inline-block;
}
</style>

1
src/icons/ai.svg 100644
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形备份 31" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份 32" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(11 11) rotate(0 10 10)"><path id="矩形" fill-rule="evenodd" style="fill:#000000" transform="translate(0 0) rotate(0 10 10)" opacity="0" d="M0,20L20,20L20,0L0,0L0,20Z " /><path id="形状" fill-rule="evenodd" style="fill:#00FFFF" transform="translate(2.5 2.5) rotate(0 7.5 7.5)" opacity="1" d="M0 10.8333L0 15.0033L4.17 15.0033L4.17 13.3333L1.67 13.3333L1.67 10.8333L0 10.8333Z M13.3333 10.8333L13.3333 13.3333L10.8333 13.3333L10.8333 15.0033L15.0033 15.0033L15.0033 10.8333L13.3333 10.8333Z M6.6 3.63583L4.91 3.63583L3.71 6.99583L0 7.23583L0 7.70583L3.45 7.70583L2.34 10.8358L3.91 10.8358L4.41 9.35583L7.06 9.35583L7.52 10.8358L9.15 10.8358L8.05 7.70583L9.95 7.70583L9.95 10.8358L11.44 10.8358L11.44 7.70583L15 7.70583L15 7.29583L11.44 7.03583L11.44 3.63583L9.95 3.63583L9.95 6.93583L7.72 6.77583L6.6 3.63583Z M4.9425 7.7075L4.8125 8.1175L6.6425 8.1175L6.5125 7.7075L4.9425 7.7075Z M5.20833 6.90167L6.23833 6.84167L5.73833 5.28167L5.20833 6.90167Z M0 0L0 4.17L1.67 4.17L1.67 1.67L4.17 1.67L4.17 0L0 0Z M10.8333 0L10.8333 1.67L13.3333 1.67L13.3333 4.17L15.0033 4.17L15.0033 0L10.8333 0Z " /></g></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形备份 23" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份 24" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(5.99999999999998 7) rotate(0 12.49999247639143 11.5)"><path id="矩形" fill-rule="evenodd" style="fill:#000000" transform="translate(0 0) rotate(0 10 10)" opacity="0" d="M0,20L20,20L20,0L0,0L0,20Z " /><path id="形状" fill-rule="evenodd" style="fill:#00FFFF" transform="translate(5.000015047217175 3) rotate(0 9.999984952782865 10)" opacity="1" d="M18.4203 17.4555C18.4703 17.6955 18.4103 17.9455 18.2503 18.1355C18.1603 18.2555 17.9603 18.4355 17.6303 18.4355L14.1003 18.4355C13.6703 18.4355 13.3203 18.7855 13.3203 19.2155C13.3203 19.6455 13.6703 19.9955 14.1003 19.9955L17.6303 19.9955C18.3503 19.9955 19.0103 19.6855 19.4703 19.1255C19.9203 18.5655 20.1003 17.8455 19.9503 17.1355C19.8603 16.7155 19.4503 16.4455 19.0303 16.5355C18.6003 16.6155 18.3303 17.0355 18.4203 17.4555Z M12.29 17.45L10.79 10.66C13.36 10.89 15.7 12.27 17.15 14.44C17.39 14.79 17.87 14.89 18.23 14.65C18.59 14.41 18.69 13.92 18.45 13.57C17.17 11.65 15.3 10.26 13.18 9.57C14.47 8.6 15.31 7.05 15.31 5.31C15.31 2.38 12.93 0 10 0C7.07 0 4.69 2.38 4.69 5.31C4.69 7.05 5.53 8.6 6.82 9.57C5.64 9.96 4.52 10.57 3.55 11.37C1.76 12.84 0.52 14.89 0.05 17.14C-0.1 17.84 0.08 18.57 0.53 19.13C0.98 19.68 1.66 20 2.37 20L5.78 20C6.21 20 6.56 19.65 6.56 19.22C6.56 18.79 6.21 18.44 5.78 18.44L2.37 18.44C2.04 18.44 1.84 18.25 1.75 18.14C1.59 17.95 1.53 17.7 1.58 17.46C2.34 13.78 5.45 11.04 9.13 10.66L7.64 17.45C7.58 17.71 7.66 17.98 7.85 18.17L9.41 19.73C9.41 19.73 9.75 19.96 9.96 19.96C10.17 19.96 10.37 19.88 10.51 19.73L12.08 18.17C12.26 17.98 12.34 17.71 12.29 17.45Z M9.81998 9.0625C9.81998 9.0625 9.93999 9.0525 9.99998 9.0525C10.06 9.0525 10.19 9.0625 10.19 9.0625C12.17 8.9625 13.75 7.3225 13.75 5.3125C13.75 3.2425 12.07 1.5625 9.99998 1.5625C7.92998 1.5625 6.24998 3.2425 6.24998 5.3125C6.24998 7.3225 7.82998 8.9625 9.81998 9.0625Z M10.6732 17.3672L9.96319 14.1472L9.25319 17.3672L9.96319 18.0772L10.6732 17.3672Z " /></g></g></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(9 9) rotate(0 12 12)"><path id="矩形" fill-rule="evenodd" style="fill:#000000" transform="translate(0 0) rotate(0 12 12)" opacity="0" d="M0,24L24,24L24,0L0,0L0,24Z " /><path id="形状" fill-rule="evenodd" style="fill:#00FFFF" transform="translate(4.500000000000002 2.25) rotate(0 9.739125 9.75)" opacity="1" d="M6.85 2.66L6.89 2.59C7.12 2.28 7.54 2.19 7.87 2.38L7.95 2.43C8.04 2.49 8.1 2.57 8.15 2.66L12.06 9.6L15 6.96L15 0.75C15 0.34 14.66 0 14.25 0L0.75 0C0.34 0 0 0.34 0 0.75L0 18.75C0 19.16 0.34 19.5 0.75 19.5L14.25 19.5C14.66 19.5 15 19.16 15 18.75L15 15.01L12.24 17.48L7.38 18.1L7.97 13.5L2.03 13.5L1.95 13.49C1.69 13.46 1.48 13.31 1.36 13.09C1.25 12.87 1.26 12.6 1.38 12.38L6.85 2.66Z M9.31 14.0502L9 16.4802L11.43 16.1702L17.36 10.9902L15.24 8.87025L9.31 14.0502Z M6.75 11.25C6.75 11.66 7.09 12 7.5 12C7.91 12 8.25 11.66 8.25 11.25C8.25 10.84 7.91 10.5 7.5 10.5C7.09 10.5 6.75 10.84 6.75 11.25Z M16.296 7.81L18.416 9.93L19.476 8.87L17.356 6.75L16.296 7.81Z M8.25 6L8.24 5.91C8.2 5.53 7.88 5.25 7.5 5.25C7.12 5.25 6.8 5.53 6.76 5.91L6.75 6L6.75 9L6.76 9.09C6.8 9.46 7.12 9.75 7.5 9.75C7.88 9.75 8.2 9.46 8.24 9.09L8.25 9L8.25 6Z " /></g></g></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形备份 19" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份 20" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(9 9) rotate(0 12 12)"><path id="矩形" fill-rule="evenodd" style="fill:#000000" transform="translate(0 0) rotate(0 12 12)" opacity="0" d="M0,24L24,24L24,0L0,0L0,24Z " /><path id="形状" fill-rule="evenodd" style="fill:#00FFFF" transform="translate(3 1.9999999921875) rotate(0 9 10.0000000078125)" opacity="1" d="M18 9C18 4.03 13.97 0 9 0C4.03 0 0 4.03 0 9C0 13.97 7.75 20 9 20C10.25 20 18 13.97 18 9Z M11.75 9C11.75 7.48 10.52 6.25 9 6.25C7.48 6.25 6.25 7.48 6.25 9C6.25 10.52 7.48 11.75 9 11.75C10.52 11.75 11.75 10.52 11.75 9Z " /></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形备份 2" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份 3" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(9.00000000000003 9) rotate(0 11.999916670543225 12)"><path id="矩形" fill-rule="evenodd" style="fill:#000000" transform="translate(0 0.0001666589135427686) rotate(0 11.99991667054323 11.99991667054323)" opacity="0" d="M0,24L24,24L24,0L0,0L0,24Z " /><path id="形状" fill-rule="evenodd" style="fill:#00FFFF" transform="translate(2.26832096889392 0) rotate(0 9.731595701649304 11.67536715664928)" opacity="1" d="M8.43 0.31L7.38 0.86C6.13 1.49 4.82 2 3.48 2.39L2.1 2.8C0.84 3.17 -0.02 4.35 0 5.66L0 13.52C0 18.95 4.36 23.35 9.73 23.35C15.11 23.35 19.46 18.95 19.46 13.52L19.46 5.66C19.48 4.35 18.63 3.17 17.36 2.8L16.02 2.39C14.68 1.99 13.38 1.48 12.13 0.85L11.04 0.31C10.22 -0.1 9.25 -0.1 8.43 0.31Z M12.0071 10.2107L9.08714 10.2107L10.6271 7.27068C10.8771 6.78068 10.6871 6.19068 10.2071 5.94068C9.97714 5.82068 9.70714 5.80068 9.46714 5.88068C9.21714 5.96068 9.00714 6.13068 8.89714 6.36068L6.62714 10.7907C6.45714 11.1007 6.45714 11.4707 6.62714 11.7807C6.80714 12.0707 7.12714 12.2507 7.46714 12.2507L10.4871 12.2507L8.84714 15.8707C8.73714 16.1107 8.72714 16.3807 8.81714 16.6307C8.90714 16.8707 9.08714 17.0707 9.32714 17.1807C9.44714 17.2407 9.58714 17.2707 9.72714 17.2707C10.1371 17.2607 10.4971 17.0007 10.6271 16.6207L12.8971 11.6007C13.0271 11.3007 13.0071 10.9507 12.8271 10.6707C12.6471 10.3807 12.3371 10.2107 12.0071 10.2107Z " /></g></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形备份 27" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份 28" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(8 14) rotate(0 13 6)"><text><tspan x="0" y="9.27734375" font-size="10" line-height="0" fill="#00FFFF" opacity="1" font-family="Roboto-Regular" letter-spacing="0" >STOP</tspan></text></g></g></svg>

After

Width:  |  Height:  |  Size: 878 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形备份 29" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份 30" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(11 10) rotate(0 10 10)"><path id="矩形" fill-rule="evenodd" style="fill:#000000" transform="translate(0 0) rotate(0 10 10)" opacity="0" d="M0,20L20,20L20,0L0,0L0,20Z " /><path id="形状" fill-rule="evenodd" style="fill:#00FFFF" transform="translate(2.49875 0) rotate(0 7.5 10)" opacity="1" d="M0.63 20L14.37 20C14.72 20 15 19.72 15 19.38L15 5C15 3.62 13.88 2.5 12.5 2.5L6.25 2.5L6.25 1.25C6.25 0.56 5.69 0 5 0L2.5 0C1.81 0 1.25 0.56 1.25 1.25L1.25 2.5L0.63 2.5C0.28 2.5 0 2.78 0 3.13L0 19.38C0 19.72 0.28 20 0.63 20Z M10.3125 11.1675C10.3125 11.1675 10.3525 11.2475 10.3925 11.2475L11.4825 11.2475C11.5225 11.2475 11.5625 11.1675 11.5625 11.1675L11.5625 6.0975C11.5625 6.0075 11.4925 5.9375 11.4025 5.9375L10.3925 5.9375C10.3525 5.9375 10.3125 6.0175 10.3125 6.0175L10.3125 11.1675Z " /></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42" fill="none"><g opacity="1" transform="translate(0 0) rotate(0 21 21)"><path id="椭圆形备份 21" fill-rule="evenodd" style="fill:#088F95" transform="translate(0 0) rotate(0 21 21)" opacity="1" d="M42,21C42,9.4 32.6,0 21,0C9.4,0 0,9.4 0,21C0,32.6 9.4,42 21,42C32.6,42 42,32.6 42,21Z " /><path id="椭圆形备份 22" fill-rule="evenodd" style="fill:#0E0E40" transform="translate(3 3) rotate(0 18 18)" opacity="1" d="M36,18C36,8.06 27.94,0 18,0C8.06,0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18Z " /><g opacity="1" transform="translate(9 9.000000000000004) rotate(0 11 10.953757244427035)"><path id="矩形" fill-rule="evenodd" style="fill:#000000" transform="translate(0 0) rotate(0 10 10)" opacity="0" d="M0,20L20,20L20,0L0,0L0,20Z " /><path id="形状" fill-rule="evenodd" style="fill:#00FFFF" transform="translate(2 2.022237214845291) rotate(0 10 9.94263863700439)" opacity="1" d="M6.59 17.5301L13.81 17.5301C14.17 18.9201 15.42 19.8901 16.85 19.8901C18.58 19.8701 19.98 18.4701 20 16.7401C20 15.9101 19.66 15.1201 19.07 14.5501C18.47 13.9801 17.67 13.6701 16.85 13.7001C15.42 13.7001 14.17 14.6601 13.81 16.0501L6.59 16.0501C5.13 16.0501 3.95 14.8701 3.95 13.4101C3.95 11.9501 5.13 10.7701 6.59 10.7701L13.47 10.7701C14.96 10.7701 16.34 9.98013 17.09 8.68013C17.84 7.39013 17.84 5.79013 17.09 4.50013C16.34 3.21013 14.96 2.41013 13.47 2.41013L6.25 2.41013C5.98 1.34013 5.23 0.520126 4.24 0.170126C3.89 0.0601261 3.52 0.000126054 3.15 0.000126054C1.42 0.0201261 0.02 1.42013 0 3.15013C0.01 4.90013 1.41 6.32013 3.15 6.36013C4.21 6.35013 5.2 5.82013 5.79 4.93013L5.85 4.81013C5.9 4.70013 6.02 4.53013 6.02 4.53013C6.07 4.41013 6.07 4.41013 6.13 4.36013C6.13 4.36013 6.19 4.13013 6.25 4.07013C6.3 4.01013 6.25 4.01013 6.3 3.96013L13.52 3.90013C14.96 3.92013 16.11 5.10013 16.11 6.53013C16.11 7.97013 14.96 9.14013 13.52 9.17013L6.59 9.17013C4.28 9.17013 2.41 11.0401 2.41 13.3501C2.41 15.6601 4.28 17.5301 6.59 17.5301Z M18.37 16.8457C18.37 15.9957 17.7 15.2857 16.85 15.2457C16.26 15.2257 15.71 15.5257 15.41 16.0257C15.1 16.5357 15.1 17.1657 15.41 17.6757C15.71 18.1757 16.26 18.4757 16.85 18.4557C17.7 18.4057 18.37 17.7057 18.37 16.8457Z " /></g></g></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,197 @@
<script setup>
import dayjs from 'dayjs'
import userUserStore from "@/store/user";
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const router = useRouter();
const userStore = userUserStore();
const goto = (path) => {
if (path !== route.path && path)
router.push(path)
}
//
const command = (val) => {
switch (val) {
case "logout":
userStore.logout();
break;
default:
break;
}
};
//
const menuList = [
{ title: "主页", icon: "home", path: "/home" },
{ title: "双重预防", icon: "scyf", path: "/scyf" },
{ title: "非常规作业", icon: "fcgzy", path: "/fcgcz" },
{ title: "人员定位", icon: "rydw" },
{ title: "智能巡检", icon: "znxj" },
{ title: "承包商", icon: "cbs" },
// { title: "", icon: "zdwxy" },
{ title: "STOP", icon: "stop" },
// { title: "", icon: "yqhs" },
// { title: "AI", icon: "ai" },
]
const day = dayjs().format('YYYY-MM-DD')
</script>
<template>
<div class="header">
<div class="title">
<span class="txt">
中化石油销售有限公司智慧HSE平台
</span>
</div>
<div class="menu-layer">
<div class="left">
<div class="menu-item" @click="goto(item.path)" :class="{ active: route.path === item.path }"
v-for="item in menuList" :key="item.title">
<div class="img">
<svg-icon :name="item.icon" size="2.3em" />
</div>
<div class="txt" :class="{ active: route.path === item.path }">{{ item.title }}</div>
</div>
</div>
<div class="right">
<el-dropdown @command="command" trigger="click">
<span class="dropdown-content" style="color: var(--txt-color);">
企业
<el-icon>
<CaretBottom />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="showInfo">企业信息</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<div class="user">
<el-dropdown @command="command" trigger="click">
<span class="dropdown-content">
<img src="@/assets/img/user.png" alt="用户头像">
<el-icon>
<CaretBottom />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="showUserInfo">用户信息</el-dropdown-item>
<el-dropdown-item command="showUserInfo">修改密码</el-dropdown-item>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<div class="day">{{ day }}</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.header {
height: 100%;
position: relative;
.title {
font-weight: 600;
font-size: 24px;
color: var(--txt-color);
height: 100%;
width: 100%;
text-align: center;
line-height: 80px;
position: relative;
background: url("@/assets/img/main-title-bottom.png") no-repeat center 40px;
.txt {
position: relative;
top: -8px;
}
&::before {
content: '';
display: inline-block;
width: 321px;
height: 71px;
background: url("@/assets/img/main-title-left.png") no-repeat center center;
position: absolute;
top: 4px;
left: calc(50% - 480px);
}
&::after {
content: '';
display: inline-block;
width: 321px;
height: 71px;
background: url("@/assets/img/main-title-right.png") no-repeat center center;
position: absolute;
top: 4px;
left: calc(50% + 158px);
}
}
.menu-layer {
position: absolute;
left: 0;
top: 0;
display: flex;
padding-top: 12px;
width: 100%;
justify-content: space-between;
.left {
display: flex;
.menu-item {
text-align: center;
width: 62px;
cursor: pointer;
color: var(--txt-color);
&.active {
color: var(---active-color);
}
&+.menu-item {
margin-left: 2px;
}
.txt {
font-size: 12px;
}
}
}
.right {
display: flex;
align-items: center;
.dropdown-content {
display: flex;
align-items: center;
cursor: pointer;
}
.user {
margin-left: 12px;
img {
display: inline-block;
}
}
.day {
margin-left: 12px;
}
}
}
}
</style>

View File

@ -0,0 +1,45 @@
<script setup>
import { ref, onMounted } from "vue";
import { RouterView } from "vue-router";
import Header from "./components/header.vue";
// import userUserStore from "@/store/user";
// const userStore = userUserStore();
// onMounted(() => {
// userStore.getUserInfo();
// });
</script>
<template>
<div class="common-layout">
<el-container style="height: 100vh">
<el-container>
<el-header>
<Header />
</el-header>
<el-main>
<el-scrollbar>
<router-view v-slot="{ Component }">
<transition name="slide-fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</el-scrollbar>
</el-main>
</el-container>
</el-container>
</div>
</template>
<style lang="less" scoped>
.common-layout {
height: 100vh;
background-color: var(--theme-color);
color: #fff;
:deep(.el-header) {
height: 75px;
}
}
</style>

16
src/main.js 100644
View File

@ -0,0 +1,16 @@
import { createApp } from "vue";
import { createPinia } from 'pinia'
import App from "./App.vue";
import router from "./router";
import SvgIcon from "@/components/SvgIcon/index.vue"
import 'virtual:svg-icons-register';
import addElementPlus from "@/utils/addElementPlus";
addElementPlus(createApp(App))
.component('svg-icon', SvgIcon)
.use(createPinia())
.use(router)
.mount("#app");

View File

@ -0,0 +1,204 @@
<script lang="ts" setup>
import { reactive, ref, h } from 'vue'
import { ElMessage, ElNotification } from 'element-plus'
const open5 = () => {
ElNotification({
title: 'Title',
message: h('i', { style: 'color: teal' }, 'This is a reminder'),
})
}
const open6 = () => {
ElNotification({
title: 'Prompt',
message: 'This is a message that does not automatically close',
duration: 0,
})
}
const open1 = () => {
ElMessage('this is a message.')
}
const open2 = () => {
ElMessage({
message: 'Congrats, this is a success message.',
type: 'success',
})
}
const open3 = () => {
ElMessage({
message: 'Warning, this is a warning message.',
type: 'warning',
})
}
const open4 = () => {
ElMessage.error('Oops, this is a error message.')
}
const dialogTableVisible = ref(false)
const dialogFormVisible = ref(false)
const formLabelWidth = '140px'
const form = reactive({
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: '',
})
const gridData = [
{
date: '2016-05-02',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District',
},
{
date: '2016-05-04',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District',
},
{
date: '2016-05-01',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District',
},
{
date: '2016-05-03',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District',
},
]
</script>
<template>
<div>
<el-button text @click="dialogTableVisible = true">
open a Table nested Dialog
</el-button>
<el-dialog v-model="dialogTableVisible" draggable class="width" title="购买地址">
<el-table :data="gridData">
<el-table-column property="date" label="Date" width="150" />
<el-table-column property="name" label="Name" width="200" />
<el-table-column property="address" label="Address" />
</el-table>
</el-dialog>
<!-- Form -->
<el-button text @click="dialogFormVisible = true">
open a Form nested Dialog
</el-button>
<el-dialog v-model="dialogFormVisible" draggable title="南京市雨花台区">
<el-form :model="form" label-width="120px">
<el-form-item label="详细地址">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="Activity zone">
<el-select v-model="form.region" placeholder="please select your zone">
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="Activity time">
<el-col :span="11">
<el-date-picker v-model="form.date1" type="date" placeholder="Pick a date"
style="width: 100%" />
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-time-picker v-model="form.date2" placeholder="Pick a time" style="width: 100%" />
</el-col>
</el-form-item>
<el-form-item label="Instant delivery">
<el-switch v-model="form.delivery" />
</el-form-item>
<el-form-item label="Activity type">
<el-checkbox-group v-model="form.type">
<el-checkbox label="Online activities" name="type" />
<el-checkbox label="Promotion activities" name="type" />
<el-checkbox label="Offline activities" name="type" />
<el-checkbox label="Simple brand exposure" name="type" />
</el-checkbox-group>
</el-form-item>
<el-form-item label="Resources">
<el-radio-group v-model="form.resource">
<el-radio label="Sponsor" disabled />
<el-radio label="Venue" />
</el-radio-group>
</el-form-item>
<el-form-item label="Activity form">
<el-input v-model="form.desc" disabled type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">Cancel</el-button>
<el-button type="primary" @click="dialogFormVisible = false">
Confirm
</el-button>
</span>
</template>
</el-dialog>
<div style="margin-top: 20px;">
<el-button :plain="true" @click="open2">success</el-button>
<el-button :plain="true" @click="open3">warning</el-button>
<el-button :plain="true" @click="open1">message</el-button>
<el-button :plain="true" @click="open4">error</el-button>
</div>
<div style="margin-top: 20px;">
<el-button plain @click="open5"> Closes automatically </el-button>
<el-button plain @click="open6"> Won't close automatically </el-button>
</div>
<div style="margin-top: 20px;">
<el-popconfirm title="Are you sure to delete this?">
<template #reference>
<el-button>Delete</el-button>
</template>
</el-popconfirm>
</div>
<div style="margin-top: 20px;">
<el-tooltip class="box-item" effect="dark" content="Top Left prompts info" placement="top-start">
<el-button>top-start</el-button>
</el-tooltip>
<el-tooltip class="box-item" effect="dark" content="Top Center prompts info" placement="top">
<el-button>top</el-button>
</el-tooltip>
<el-tooltip class="box-item" effect="dark" content="Top Right prompts info" placement="top-end">
<el-button>top-end</el-button>
</el-tooltip>
</div>
<div class="row">
<el-tooltip class="box-item" effect="dark" content="Left Top prompts info" placement="left-start">
<el-button>left-start</el-button>
</el-tooltip>
<el-tooltip class="box-item" effect="dark" content="Right Top prompts info" placement="right-start">
<el-button>right-start</el-button>
</el-tooltip>
</div>
</div>
</template>
<style scoped>
.el-button--text {
margin-right: 15px;
}
.el-select {
width: 300px;
}
.el-input {
width: 300px;
}
.dialog-footer button:first-child {
margin-right: 10px;
}
</style>

View File

@ -0,0 +1,362 @@
<script setup>
import Charts from "@/components/Charts/index.vue"
import { reactive, ref, onMounted } from 'vue'
import { getgctj, getlxzb, getrstj, getrywz, getslpm, getyspm } from "@/api/home"
// observationStatistics
const observationStatisticsOptions = ref({})
onMounted(() => {
getgctj().then(res => {
if (res.data.result?.dataset?.source) {
const { source, dimensions } = res.data.result.dataset
const xAxisData = source.map(i => i[dimensions[0]])
const colorList = ["#A5D96C", "#F7CB4A", "#D42D6B"]
const data = source.map((i, idx) => ({
value: i[dimensions[1]],
itemStyle: {
color: colorList[idx % colorList.length]
}
}))
observationStatisticsOptions.value = {
backgroundColor: "#091e4700",
title: {
text: 'HSE观察统计',
textStyle: {
fontSize: 16,
}
},
xAxis: {
type: 'category',
data: xAxisData
},
grid: {
top: "40px",
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
yAxis: {
type: 'value'
},
series: [
{
name: "记录数量",
type: "bar",
label: {
show: true,
position: "top",
color: "#ffffff",
fontSize: 12
},
data,
type: 'bar'
}
]
}
}
})
})
// accountedFor
const accountedForOptions = ref({})
onMounted(() => {
getlxzb().then(res => {
if (res.data.result?.dataset?.source) {
const { source, dimensions } = res.data.result.dataset
const data = source.map((i, idx) => ({
value: i[dimensions[1]],
name: i[dimensions[0]]
}))
accountedForOptions.value = {
backgroundColor: "#091e4700",
title: {
text: '问题对应隐患类型占比',
textStyle: {
fontSize: 16,
}
},
grid: {
top: "40px",
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
series: [
{
name: '问题对应隐患类型占比',
type: 'pie',
radius: ['30%', '70%'],
label: {
formatter: '{txt|{b}:{c}({d}%)}',
rich: {
txt: {
fontSize: 12,
color: "#ffffff"
}
}
},
data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
}
})
})
// headCount
const headCountOptions = ref({})
onMounted(() => {
getrstj().then(res => {
if (res.data.result?.dataset?.source) {
const { source, dimensions } = res.data.result.dataset
const legendData = ['不安全问题数', '被观察人数', '不安全行为人数'];
const data = legendData.map((i, idx) => ({
name: i,
type: 'line',
data: source.map(j => j[dimensions[idx + 1]])
}))
const xAxisData = source.map((i) => i[dimensions[0]])
headCountOptions.value = {
backgroundColor: "#091e4700",
title: {
text: 'HSE人数统计',
textStyle: {
fontSize: 16,
}
},
tooltip: {
trigger: 'axis'
},
legend: {
data: legendData
},
grid: {
top: "40px",
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: true,
data: xAxisData
},
yAxis: {
type: 'value'
},
series: data
}
}
})
})
// personnelLocation
const personnelLocationOptions = ref({})
onMounted(() => {
getrywz().then(res => {
if (res.data.result?.dataset?.source) {
const legendData = ['记录数', '不安全行为人数', '被观察人数', '不安全数']
const { source, dimensions } = res.data.result.dataset
const xAxisData = source.map((i) => i[dimensions[0]])
const series = legendData.map((i, idx) => ({
name: i,
type: 'line',
data: source.map(j => j[dimensions[idx + 1]])
}))
personnelLocationOptions.value = {
backgroundColor: "#091e4700",
title: {
text: '人员位置',
textStyle: {
fontSize: 16,
}
},
tooltip: {
trigger: 'axis',
},
legend: {
data: legendData
},
grid: {
top: "40px",
left: '8%',
right: '8%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: true,
data: xAxisData
},
yAxis: {
type: 'value',
},
series
}
}
})
})
//
const form = reactive({
unit: '',
timeRanges: [],
})
//
const unitList = reactive([
{ key: 1, label: "中化能源" },
{ key: 2, label: "中化能源-1" },
{ key: 3, label: "中化能源-2" },
{ key: 4, label: "中化能源-3" },
{ key: 5, label: "中化能源-4" },
])
//
const factorRankingList = ref([])
onMounted(() => {
getyspm().then(res => {
if (res.data.result?.list?.columns?.length) {
const { source } = res.data.result.list
factorRankingList.value = source.sort((a, b) => b.id - a.id)
}
})
})
//
const observedQuantityRankingList = ref([])
onMounted(() => {
getslpm().then(res => {
if (res.data.result?.list?.columns?.length) {
const { source } = res.data.result.list
observedQuantityRankingList.value = source.sort((a, b) => b.id - a.id)
}
})
})
const getSortNumFormatter = (row, col, cellvalue, index) => index + 1
</script>
<template>
<div class="home">
<!-- <el-form inline :model="form" label-width="100px" class="form">
<el-form-item label="所属单位:">
<el-select :teleported="false" v-model="form.unit" placeholder="请选择">
<el-option v-for="item in unitList" :key="item.key" :label="item.label" :value="item.key" />
</el-select>
</el-form-item>
<el-form-item label="时间:">
<el-date-picker :teleported="false" v-model="form.timeRanges" type="daterange" range-separator="-"
start-placeholder="开始时间" end-placeholder="结束时间" />
</el-form-item>
</el-form> -->
<div class="main-content">
<!-- 观察统计 -->
<div class="content-item observationStatistics">
<Charts :option="observationStatisticsOptions" />
</div>
<div class="content-item">
<Charts :option="accountedForOptions" />
</div>
<!-- 人数统计 -->
<div class="content-item">
<Charts :option="headCountOptions" />
</div>
<!-- HSE要素排名 -->
<div class="content-item">
<h4>HSE要素排名</h4>
<el-table :data="factorRankingList" style="width: 100%;overflow-y: auto;
max-height: calc(100% - 32px);margin-top: 8px;">
<el-table-column prop="yijiyaosu" align="center" label="一级要素" />
<el-table-column prop="id" align="center" label="记录数" />
<el-table-column prop="v3" align="center" label="记录数(排名)" :formatter="getSortNumFormatter" />
</el-table>
</div>
<!-- 企业HSE观察数量排名 -->
<div class="content-item">
<h4>企业HSE观察数量排名</h4>
<el-table :data="observedQuantityRankingList" style="width: 100%;overflow-y: auto;
max-height: calc(100% - 32px);margin-top: 8px;">
<el-table-column prop="suoshuqiye" align="center" label="所属企业" />
<el-table-column prop="id" align="center" label="记录数" />
<el-table-column prop="vo3" align="center" label="记录数(排名)" :formatter="getSortNumFormatter" />
</el-table>
</div>
<!-- 人员位置 -->
<div class="content-item">
<Charts :option="personnelLocationOptions" />
</div>
</div>
</div>
</template>
<style scoped lang="less">
//
.main-content {
// display: grid;
// grid-template-columns: 1fr 1fr 1fr;
// grid-template-rows: 1fr 1fr;
// grid-row-gap: 20px;
// grid-column-gap: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.content-item {
width: calc((100% - 40px) / 3);
height: calc((100vh - 135px) / 2);
padding: 16px 12px 12px 12px;
background-color: var(--select-bg-color-2);
box-shadow: inset 0px 0px 16px 0px rgba(0, 145, 255, 0.3);
background-image: url("@/assets/img/dialog-bg-top-left-1.png"),
url("@/assets/img/dialog-bg-top-left-2.png"),
url("@/assets/img/dialog-bg-right-top.png"),
url("@/assets/img/dialog-bg-right-bottom.png"),
url("@/assets/img/dialog-bg-left-bottom.png");
background-position: 12px top, left 10px, right top, right bottom, left bottom;
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat;
border-radius: 4px;
&:nth-child(4), &:nth-child(5), &:nth-child(6) {
margin-top: 20px;
}
&>div {
width: 100%;
height: 100%;
}
}
}
</style>

View File

@ -0,0 +1,70 @@
<script setup>
const handleClick = () => {
console.log('click')
}
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
]
</script>
<template>
<div class="SCYF">
<el-table :data="tableData" style="width: 100%">
<el-table-column fixed prop="date" label="Date" width="150" />
<el-table-column prop="name" label="Name" width="160" />
<el-table-column prop="state" label="State" width="260" />
<el-table-column prop="city" label="City" width="260" />
<el-table-column prop="address" label="Address" width="600" />
<el-table-column prop="zip" label="Zip" width="160" />
<el-table-column fixed="right" label="Operations" width="120">
<template #default>
<el-button link type="primary" size="small" @click="handleClick">Detail</el-button>
<el-button link type="primary" size="small">Edit</el-button>
</template>
</el-table-column>
</el-table>
<!-- <el-pagination :page-size="20" :pager-count="11" layout="prev, pager, next" :total="1000" /> -->
<el-pagination style="margin-top: 12px;" background layout="total, sizes, prev, pager, next, jumper"
:total="1000" />
</div>
</template>
<style lang="less" scoped>
</style>

View File

@ -0,0 +1,224 @@
<script setup>
import { reactive } from "vue";
import { useRouter } from "vue-router";
import { doLogin } from "@/api/base";
import { ElMessage } from "element-plus";
import userUserStore from '@/store/user'
const userStore = userUserStore()
const router = useRouter();
const formData = reactive({
name: "",
password: "",
captcha: "asdl3",
captcha_id: "asdfa",
});
//
const login = () => {
doLogin(formData).then(res => {
ElMessage({
showClose: true,
message: "登录成功",
type: "success",
});
router.push("/");
localStorage.setItem('token', res.data.data.token)
userStore.getUserInfo()
});
};
//
const forgetPassword = () => {
router.push("/forgetPassword");
};
//
const signUp = () => {
router.push("/register");
};
</script>
<template>
<div class="login">
<div class="box">
<div class="form">
<h2>欢迎回来</h2>
<div class="inputbox">
<input type="text" v-model="formData.name" required="required" />
<span>用户名</span>
<i></i>
</div>
<div class="inputbox">
<input
type="password"
v-model="formData.password"
required="required"
/>
<span>密码</span>
<i></i>
</div>
<div class="links">
<span @click="forgetPassword"></span>
<span @click="signUp"></span>
</div>
<button type="submit" @click="login"></button>
</div>
</div>
</div>
</template>
<style scoped>
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap");
.login {
font-family: "poppins", sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #23242a;
}
.box {
position: relative;
width: 380px;
height: 420px;
background: #1c1c1c;
border-radius: 8px;
overflow: hidden;
}
.box::before {
content: "";
position: absolute;
top: -50%;
left: -50%;
width: 320px;
height: 420px;
background: linear-gradient(0deg, transparent, #45f3ff, transparent, #45f3ff);
transform-origin: bottom right;
animation: animate 6s linear infinite;
}
.box::after {
content: "";
position: absolute;
top: -50%;
left: -50%;
width: 320px;
height: 420px;
background: linear-gradient(
10deg,
transparent,
#45f3ff,
transparent,
#45f3ff
);
transform-origin: bottom right;
animation: animate 6s linear infinite;
animation-delay: -3s;
}
@keyframes animate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.form {
position: absolute;
inset: 2px;
border-radius: 8px;
background: #28292d;
z-index: 10;
padding: 50px 40px;
display: flex;
flex-direction: column;
}
.form h2 {
color: #45f3ff;
font-weight: 500;
text-align: center;
letter-spacing: 0.1em;
}
.inputbox {
position: relative;
width: 300px;
margin-top: 20px;
}
.inputbox + .inputbox {
margin-top: 40px;
}
.inputbox input {
position: relative;
width: 100%;
padding: 20px 10px 10px;
background: transparent;
border: none;
outline: none;
color: #23242a;
font-size: 1em;
letter-spacing: 0.05em;
z-index: 10;
}
.inputbox span {
position: absolute;
left: 0;
padding: 20px 0px 10px;
font-size: 1em;
color: #8f8f8f;
pointer-events: none;
letter-spacing: 0.05em;
transition: 0.5s;
}
.inputbox input:valid ~ span,
.inputbox input:focus ~ span {
color: #45f3ff;
transform: translateX(0px) translateY(-34px);
font-size: 0.75em;
}
.inputbox i {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 2px;
background: #45f3ff;
border-radius: 4px;
transition: 0.5s;
pointer-events: none;
}
.inputbox input:valid ~ i,
.inputbox input:focus ~ i {
height: 44px;
}
.links {
display: flex;
justify-content: space-between;
}
.links span {
cursor: pointer;
margin: 10px 0;
font-size: 0.75em;
color: #8f8f8f;
text-decoration: none;
}
.links span:hover,
.links span:nth-child(2) {
color: #45f3ff;
}
button[type="submit"] {
border: none;
outline: none;
background: #45f3ff;
padding: 6px 25px;
margin-top: 30px;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
}
button[type="submit"]:active {
opacity: 0.8;
}
</style>

57
src/router.js 100644
View File

@ -0,0 +1,57 @@
import { createRouter, createWebHashHistory } from "vue-router";
// 路由配置
const routes = [
{
path: "/",
redirect: "/home",
component: () => import("@/layout/index.vue"),
children: [
{
path: "/home",
name: "home",
meta: {
title: "首页",
},
component: () => import("@/pages/Home/index.vue"),
},
{
path: "/scyf",
name: "scyf",
meta: {
title: "双重预防",
},
component: () => import("@/pages/SCYF/index.vue"),
},
{
path: "/fcgcz",
name: "fcgcz",
meta: {
title: "非常规操作",
},
component: () => import("@/pages/FCGCZ/index.vue"),
},
],
},
{
path: "/login",
name: "login",
component: () => import("@/pages/login/index.vue"),
},
{
path: '/:pathMatch(.*)*',
redirect: '/home'
}
];
const router = createRouter({
history: createWebHashHistory(), // hash路由
routes,
});
// 路由守卫
router.beforeEach((to, from, next) => {
next();
});
export default router;

29
src/store/user.js 100644
View File

@ -0,0 +1,29 @@
import { defineStore } from "pinia";
import { getUserInfo } from "@/api/base";
import router from '@/router'
export default defineStore("user", {
state() {
return {
baseInfo: {},
};
},
getters: {
token: (state) => state.baseInfo.token,
nickName() {
return this.baseInfo.nickName;
},
},
actions: {
getUserInfo() {
getUserInfo().then((res) => {
this.baseInfo = res.data.data;
});
},
logout() {
this.baseInfo = {}
localStorage.removeItem('token')
router.push('/login')
}
},
});

View File

@ -0,0 +1,3 @@
@import "var.less";
@import "reset.less";
@import "reset-elementPlus.less";

View File

@ -0,0 +1,230 @@
// 重置elementPlus样式
// -----表单部分----开始------
.el-form-item__label,
.el-input__inner,
.el-picker-panel__icon-btn,
.el-date-table th,
.el-date-editor .el-range-input,
.el-select-dropdown__item,
.el-checkbox,
.el-radio,
.el-textarea__inner,
.el-time-spinner__item,
.el-time-spinner__item.is-active:not(.is-disabled),
.el-time-panel__btn,
.el-date-picker__header-label,
.el-select-v2__placeholder,
.el-select-dropdown__option-item {
color: #fff;
}
.el-radio__inner,
.el-checkbox__inner,
.el-switch__core {
background-color: transparent;
border-color: #fff;
}
.el-time-spinner__item:hover:not(.is-disabled):not(.is-active) {
background-color: var(--select-bg-color-1);
}
.el-input__wrapper,
.el-textarea__inner {
background-color: var(--select-bg-color);
box-shadow: 0 0 0 1px var(--select-border-color) inset !important;
}
.el-select .el-input.is-focus .el-input__wrapper {
box-shadow: 0 0 0 1px var(--select-border-color) inset !important;
}
.el-select-v2__wrapper.is-focused {
border-color: var(--select-border-color);
}
.el-select-v2__wrapper,
.el-select-v2__wrapper.is-hovering:not(.is-focused) {
background-color: var(--select-bg-color);
border-color: var(--select-border-color);
}
.el-picker-panel {
background-color: var(--select-bg-color);
color: #fff;
}
.el-date-table td.in-range .el-date-table-cell,
.el-date-table td.in-range .el-date-table-cell:hover {
background-color: var(--select-bg-color-1);
}
.el-popper.is-light {
background: var(--select-bg-color);
border-color: var(--select-border-color);
}
.el-popper.is-light .el-popper__arrow::before {
display: none;
}
.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover,
.el-select-dropdown__option-item.is-selected {
background-color: var(--select-bg-color-1);
}
.el-textarea__inner {
background-color: var(--select-bg-color);
}
.el-select-dropdown__option-item.hover {
background-color: var(--select-bg-color-1) !important;
}
.el-date-table th,
.el-time-panel__footer,
.el-time-panel__content::before {
border-color: #fff;
}
// -----表单部分----结束------
// -------表格部分-----开始----
.el-table,
.el-table__inner-wrapper::before {
background-color: transparent;
}
// 表头和其他偶数行区域
.el-table th.el-table__cell,
.el-table.is-scrolling-none th.el-table-fixed-column--left,
.el-table.is-scrolling-none th.el-table-fixed-column--right {
background-color: var(--bg-color);
color: #fff;
}
// 偶数行区域
.el-table tr,
.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell,
.el-table__body-wrapper tr td.el-table-fixed-column--left,
.el-table__body-wrapper tr td.el-table-fixed-column--right,
.el-table__body-wrapper tr th.el-table-fixed-column--left,
.el-table__body-wrapper tr th.el-table-fixed-column--right,
.el-table__footer-wrapper tr td.el-table-fixed-column--left,
.el-table__footer-wrapper tr td.el-table-fixed-column--right,
.el-table__footer-wrapper tr th.el-table-fixed-column--left,
.el-table__footer-wrapper tr th.el-table-fixed-column--right,
.el-table__header-wrapper tr td.el-table-fixed-column--left,
.el-table__header-wrapper tr td.el-table-fixed-column--right,
.el-table__body tr.hover-row.current-row>td.el-table__cell,
.el-table__body tr.hover-row.el-table__row--striped.current-row>td.el-table__cell,
.el-table__body tr.hover-row.el-table__row--striped>td.el-table__cell,
.el-table__body tr.hover-row>td.el-table__cell {
background-color: var(--select-bg-color-2);
color: #fff;
}
.el-table tr:nth-child(2n),
.el-table.is-scrolling-left th.el-table-fixed-column--left,
.el-table--enable-row-hover .el-table__body tr:nth-child(2n):hover>td.el-table__cell,
.el-table__body-wrapper tr:nth-child(2n) td.el-table-fixed-column--left,
.el-table__body-wrapper tr:nth-child(2n) td.el-table-fixed-column--right,
.el-table__body-wrapper tr:nth-child(2n) th.el-table-fixed-column--left,
.el-table__body-wrapper tr:nth-child(2n) th.el-table-fixed-column--right,
.el-table__footer-wrapper tr:nth-child(2n) td.el-table-fixed-column--left,
.el-table__footer-wrapper tr:nth-child(2n) td.el-table-fixed-column--right,
.el-table__footer-wrapper tr:nth-child(2n) th.el-table-fixed-column--left,
.el-table__footer-wrapper tr:nth-child(2n) th.el-table-fixed-column--right,
.el-table__header-wrapper tr:nth-child(2n) td.el-table-fixed-column--left,
.el-table__header-wrapper tr:nth-child(2n) td.el-table-fixed-column--right,
.el-table__header-wrapper tr:nth-child(2n) th.el-table-fixed-column--left,
.el-table__header-wrapper tr:nth-child(2n) th.el-table-fixed-column--right,
.el-table__header-wrapper tr th.el-table-fixed-column--right,
.el-table.is-scrolling-right th.el-table-fixed-column--right,
.el-table__header-wrapper tr th.el-table-fixed-column--left,
.el-table__body tr:nth-child(2n).hover-row.current-row>td.el-table__cell,
.el-table__body tr:nth-child(2n).hover-row.el-table__row--striped.current-row>td.el-table__cell,
.el-table__body tr:nth-child(2n).hover-row.el-table__row--striped>td.el-table__cell,
.el-table__body tr:nth-child(2n).hover-row>td.el-table__cell {
background-color: var(--bg-color);
}
.el-table th.el-table__cell.is-leaf,
.el-table td.el-table__cell {
border-bottom: none;
}
// -------表格部分-----结束----
// -------分页组件------开始-----
.el-pagination button,
.el-pagination button.is-disabled,
.el-pagination button:disabled,
.el-pager li,
.el-pager li.is-disabled,
.el-pager li:disabled {
background-color: transparent;
}
.el-pagination button.is-disabled,
.el-pagination button:disabled {
color: #ccc;
}
.el-pagination button,
.el-pager li,
.el-pagination__jump,
.el-pagination__total {
color: #fff;
}
.el-pagination.is-background .btn-next,
.el-pagination.is-background .btn-prev,
.el-pagination.is-background .el-pager li {
background-color: var(--select-bg-color);
}
.el-pagination.is-background .btn-next.is-disabled,
.el-pagination.is-background .btn-next:disabled,
.el-pagination.is-background .btn-prev.is-disabled,
.el-pagination.is-background .btn-prev:disabled,
.el-pagination.is-background .el-pager li.is-disabled,
.el-pagination.is-background .el-pager li:disabled {
background-color: #cccccc30;
}
.el-pagination.is-background .el-pager li.is-disabled.is-active {
background-color: #cccccc50;
}
// -------分页组件------结束-----
// ---------弹窗-----开始------
.el-dialog {
background-color: var(--select-bg-color-2);
box-shadow: inset 0px 0px 16px 0px rgba(0, 145, 255, 0.3);
background-image: url("@/assets/img/dialog-bg-top-left-1.png"),
url("@/assets/img/dialog-bg-top-left-2.png"),
url("@/assets/img/dialog-bg-right-top.png"),
url("@/assets/img/dialog-bg-right-bottom.png"),
url("@/assets/img/dialog-bg-left-bottom.png");
background-position: 12px top, left 10px, right top, right bottom, left bottom;
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat;
}
.el-dialog__body {
padding-top: 8px;
padding-bottom: 20px;
}
.el-dialog__footer {
padding-top: 0px;
}
// ---------弹窗-----结束------

View File

@ -0,0 +1,76 @@
/*
1. 使用更直观的 box-sizing 模型
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
/*
2. 移除默认 margin
*/
* {
margin: 0;
}
/*
3. 在应用中允许基于百分比的高度
*/
html,
body {
height: 100%;
}
/*
排版调整
4. 添加无障碍行高
5. 改进文本渲染
*/
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/*
6. 改进媒体默认设置
*/
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
/*
7. 删除内置表单排版样式
*/
input,
button,
textarea,
select {
font: inherit;
}
/*
8. 避免文字溢出
*/
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
/*
9. 创建根层叠上下文
*/
#root,
#__next {
isolation: isolate;
}

22
src/style/var.less 100644
View File

@ -0,0 +1,22 @@
/* 颜色变量 */
:root {
/* 主题颜色 */
--theme-color: #0B1944;
/* 文字颜色 */
--txt-color: #01F1FE;
/* 选框和弹窗 */
--select-border-color: #204D6F;
--select-bg-color: #093763;
--select-bg-color-1: #074f73;
--select-bg-color-2: #0A2450;
--bg-color: #093864;
// 选中
---active-color: #FF9309;
}
// 重置elementPlus主题
html.dark {
/* 自定义深色背景颜色 */
--el-bg-color: #080731;
--el-disabled-bg-color: #213d5b;
--el-fill-color-light: #213d5b;
}

View File

@ -0,0 +1,17 @@
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import '@/style/index.less' // 此处顺序需要保持正确
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
export default (app) => {
// 添加elementPlus图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
// 全局加载elementPlus 并设置语言为中文
return app.use(ElementPlus, {
locale: zhCn,
})
}

View File

@ -0,0 +1,53 @@
import axios from "axios";
import { ElMessage } from "element-plus";
import router from "@/router";
const request = axios.create({
baseURL: import.meta.env.VITE_BASE_API_URL,
timeout: 15000,
});
// 添加请求拦截器
request.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
// config.headers["x-token"] = localStorage.getItem("token");
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
request.interceptors.response.use(
function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
// const { data } = response;
// if (data.code !== 200) {
// ElMessage.error({
// showClose: true,
// message: data.msg,
// });
// return Promise.reject(response);
// }
return response;
},
function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
const { response } = error;
ElMessage.error({
showClose: true,
message: response.data.msg,
});
// if (response.status === 401) {
// router.push("/login");
// localStorage.removeItem('token')
// }
return Promise.reject(error);
}
);
export default request;

37
vite.config.js 100644
View File

@ -0,0 +1,37 @@
import { resolve } from "path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default ({ mode }) =>
defineConfig({
plugins: [vue(), vueJsx(),
createSvgIconsPlugin({
iconDirs: [resolve(__dirname, 'src/icons')],
symbolId: 'icon-[dir]-[name]',
}),
],
hmr: true,
//此时把环境打包路径也配置好,避免生产环境打包出现白屏
base: mode === "development" ? "/" : "./",
server: {
port: 3000,
host: "0.0.0.0",
proxy: {
// "/api": {
// target: "http://192.168.1.18",
// rewrite: (path) => path.replace(/^\/api/, ""),
// },
"/api": {
target: "http://10.156.140.7:28000/space-zhonghuacangchu",
rewrite: (path) => path.replace(/^\/api/, "/api"),
},
},
},
resolve: {
alias: {
"@": resolve(__dirname, "src"),
},
},
});

3963
yarn.lock 100644

File diff suppressed because it is too large Load Diff