大屏模板 方案
This commit is contained in:
parent
7302d8cb65
commit
416588ef60
|
@ -8,10 +8,12 @@
|
|||
"name": "management",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@kjgl77/datav-vue3": "^1.7.4",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.8.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.6.0",
|
||||
"event-source-polyfill": "^1.0.31",
|
||||
"js-base64": "^3.7.7",
|
||||
"jsencrypt": "^3.3.2",
|
||||
|
@ -435,6 +437,15 @@
|
|||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.27.1.tgz",
|
||||
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.0.tgz",
|
||||
|
@ -900,6 +911,52 @@
|
|||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/bezier-curve": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz",
|
||||
"integrity": "sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/c-render": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz",
|
||||
"integrity": "sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/bezier-curve": "*",
|
||||
"@jiaminghi/color": "*",
|
||||
"@jiaminghi/transition": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/charts": {
|
||||
"version": "0.2.18",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz",
|
||||
"integrity": "sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/c-render": "^0.4.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/color": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/color/-/color-1.1.3.tgz",
|
||||
"integrity": "sha512-ZY3hdorgODk4OSTbxyXBPxAxHPIVf9rPlKJyK1C1db46a50J0reFKpAvfZG8zMG3lvM60IR7Qawgcu4ZDO3+Hg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jiaminghi/transition": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz",
|
||||
"integrity": "sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.8",
|
||||
"resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||
|
@ -957,6 +1014,86 @@
|
|||
"resolved": "https://registry.npmmirror.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||
},
|
||||
"node_modules/@kjgl77/datav-vue3": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmmirror.com/@kjgl77/datav-vue3/-/datav-vue3-1.7.4.tgz",
|
||||
"integrity": "sha512-zYVTVKkklUxwtiNKS1qPBilm4rTW+WItfp0zVpaRAI8wgXkLSPbDR9xPq2+UcU/Jft7/DVdMfBp709E2ResuPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jiaminghi/c-render": "^0.4.3",
|
||||
"@jiaminghi/charts": "^0.2.18",
|
||||
"@jiaminghi/color": "^1.1.3",
|
||||
"@vueuse/core": "^10.11.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@kjgl77/datav-vue3/node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.20",
|
||||
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
|
||||
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@kjgl77/datav-vue3/node_modules/@vueuse/core": {
|
||||
"version": "10.11.1",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-10.11.1.tgz",
|
||||
"integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/web-bluetooth": "^0.0.20",
|
||||
"@vueuse/metadata": "10.11.1",
|
||||
"@vueuse/shared": "10.11.1",
|
||||
"vue-demi": ">=0.14.8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@kjgl77/datav-vue3/node_modules/@vueuse/metadata": {
|
||||
"version": "10.11.1",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-10.11.1.tgz",
|
||||
"integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@kjgl77/datav-vue3/node_modules/@vueuse/shared": {
|
||||
"version": "10.11.1",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-10.11.1.tgz",
|
||||
"integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"vue-demi": ">=0.14.8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@kjgl77/datav-vue3/node_modules/vue-demi": {
|
||||
"version": "0.14.10",
|
||||
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
|
||||
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
@ -2561,6 +2698,16 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/echarts": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
|
||||
"integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "2.3.0",
|
||||
"zrender": "5.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.125",
|
||||
"resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.125.tgz",
|
||||
|
@ -4415,6 +4562,12 @@
|
|||
"resolved": "https://registry.npmmirror.com/treemate/-/treemate-0.3.11.tgz",
|
||||
"integrity": "sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg=="
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.7.3.tgz",
|
||||
|
@ -5084,6 +5237,15 @@
|
|||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zrender": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",
|
||||
"integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tslib": "2.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,17 @@
|
|||
"type-check": "vue-tsc --build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kjgl77/datav-vue3": "^1.7.4",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.8.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.6.0",
|
||||
"event-source-polyfill": "^1.0.31",
|
||||
"js-base64": "^3.7.7",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"naive-ui": "^2.41.0",
|
||||
"pinia": "^3.0.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"sass": "^1.85.1",
|
||||
|
@ -27,8 +30,7 @@
|
|||
"unplugin-auto-import": "^19.1.1",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0",
|
||||
"naive-ui": "^2.41.0"
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node22": "^22.0.0",
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
// 颜色
|
||||
$colors: (
|
||||
"primary": #db9e3f,
|
||||
"info-1": #4394e4,
|
||||
"info": #4b67af,
|
||||
"white": #ffffff,
|
||||
"light": #f9f9f9,
|
||||
"grey-1": #999999,
|
||||
"grey": #666666,
|
||||
"dark-1": #5f5f5f,
|
||||
"dark": #222222,
|
||||
"black-1": #171823,
|
||||
"black": #000000,
|
||||
);
|
||||
|
||||
// 字体大小
|
||||
$base-font-size: 16px;
|
||||
$font-sizes: (
|
||||
xxs: 0.1,
|
||||
//8px
|
||||
xs: 0.125,
|
||||
//10px
|
||||
sm: 0.2875,
|
||||
//12px
|
||||
md: 0.1625,
|
||||
//13px
|
||||
lg: 0.175,
|
||||
//14px
|
||||
xl: 0.2,
|
||||
//16px
|
||||
xxl: 0.225,
|
||||
//18px
|
||||
xxxl: 0.25 //20px,,,,
|
||||
);
|
||||
|
||||
// 宽高
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
//flex
|
||||
.d-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.flex-nowrap {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
$flex-jc: (
|
||||
start: flex-start,
|
||||
end: flex-end,
|
||||
center: center,
|
||||
between: space-between,
|
||||
around: space-around,
|
||||
evenly: space-evenly,
|
||||
);
|
||||
|
||||
$flex-ai: (
|
||||
start: flex-start,
|
||||
end: flex-end,
|
||||
center: center,
|
||||
stretch: stretch,
|
||||
);
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
//.mt-1 => margin top
|
||||
//spacing
|
||||
$spacing-types: (
|
||||
m: margin,
|
||||
p: padding,
|
||||
);
|
||||
$spacing-directions: (
|
||||
t: top,
|
||||
r: right,
|
||||
b: bottom,
|
||||
l: left,
|
||||
);
|
||||
$spacing-base-size: 16px;
|
||||
$spacing-sizes: (
|
||||
0: 0,
|
||||
1: 0.25,
|
||||
2: 0.5,
|
||||
3: 1,
|
||||
4: 1.5,
|
||||
5: 3,
|
||||
);
|
|
@ -110,24 +110,31 @@
|
|||
.mt#{$i} {
|
||||
margin-top: #{$i}px !important;
|
||||
}
|
||||
|
||||
.mr#{$i} {
|
||||
margin-right: #{$i}px !important;
|
||||
}
|
||||
|
||||
.mb#{$i} {
|
||||
margin-bottom: #{$i}px !important;
|
||||
}
|
||||
|
||||
.ml#{$i} {
|
||||
margin-left: #{$i}px !important;
|
||||
}
|
||||
|
||||
.pt#{$i} {
|
||||
padding-top: #{$i}px !important;
|
||||
}
|
||||
|
||||
.pr#{$i} {
|
||||
padding-right: #{$i}px !important;
|
||||
}
|
||||
|
||||
.pb#{$i} {
|
||||
padding-bottom: #{$i}px !important;
|
||||
}
|
||||
|
||||
.pl#{$i} {
|
||||
padding-left: #{$i}px !important;
|
||||
}
|
||||
|
@ -484,4 +491,4 @@
|
|||
/* 鼠标悬浮手指 */
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
@import "./variables";
|
||||
|
||||
// 全局样式
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
// font-family: Arial, Helvetica, sans-serif;
|
||||
// line-height: 1.2em;
|
||||
// background-color: #f1f1f1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #343440;
|
||||
text-decoration: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
&::after {
|
||||
content: "";
|
||||
display: table;
|
||||
height: 0;
|
||||
line-height: 0;
|
||||
visibility: hidden;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
// 图标
|
||||
.iconfont {
|
||||
font-size: 20px !important;
|
||||
color: #5cd9e8;
|
||||
}
|
||||
|
||||
//浮动
|
||||
.float-r {
|
||||
float: right;
|
||||
}
|
||||
|
||||
//浮动
|
||||
.float-l {
|
||||
float: left;
|
||||
}
|
||||
|
||||
// 字体加粗
|
||||
.fw-b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
//文章一行显示,多余省略号显示
|
||||
.title-item {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bg-color-black {
|
||||
background-color: rgba(19, 25, 47, 0.6);
|
||||
}
|
||||
|
||||
.bg-color-blue {
|
||||
background-color: #1a5cd7;
|
||||
}
|
||||
|
||||
.colorBlack {
|
||||
color: #272727 !important;
|
||||
|
||||
&:hover {
|
||||
color: #272727 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.colorGrass {
|
||||
color: #33cea0;
|
||||
|
||||
&:hover {
|
||||
color: #33cea0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.colorRed {
|
||||
color: #ff5722;
|
||||
|
||||
&:hover {
|
||||
color: #ff5722 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.colorText {
|
||||
color: #d3d6dd !important;
|
||||
|
||||
&:hover {
|
||||
color: #d3d6dd !important;
|
||||
}
|
||||
}
|
||||
|
||||
.colorBlue {
|
||||
color: #257dff !important;
|
||||
|
||||
&:hover {
|
||||
color: #257dff !important;
|
||||
}
|
||||
}
|
||||
|
||||
//颜色
|
||||
@each $colorkey, $color in $colors {
|
||||
.text-#{$colorkey} {
|
||||
color: $color;
|
||||
}
|
||||
|
||||
.bg-#{$colorkey} {
|
||||
background-color: $color;
|
||||
}
|
||||
}
|
||||
|
||||
//对齐
|
||||
@each $var in (left, center, right) {
|
||||
.text-#{$var} {
|
||||
text-align: $var !important;
|
||||
}
|
||||
}
|
||||
|
||||
//flex
|
||||
@each $key, $value in $flex-jc {
|
||||
.jc-#{$key} {
|
||||
justify-content: $value;
|
||||
}
|
||||
}
|
||||
|
||||
@each $key, $value in $flex-ai {
|
||||
.ai-#{$key} {
|
||||
align-items: $value;
|
||||
}
|
||||
}
|
||||
|
||||
//字体
|
||||
@each $fontkey, $fontvalue in $font-sizes {
|
||||
.fs-#{$fontkey} {
|
||||
font-size: $fontvalue * $base-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
//.mt-1 => margin top
|
||||
//spacing
|
||||
|
||||
@each $typekey, $type in $spacing-types {
|
||||
|
||||
//.m-1
|
||||
@each $sizekey, $size in $spacing-sizes {
|
||||
.#{$typekey}-#{$sizekey} {
|
||||
#{$type}: $size * $spacing-base-size;
|
||||
}
|
||||
}
|
||||
|
||||
//.mx-1
|
||||
@each $sizekey, $size in $spacing-sizes {
|
||||
.#{$typekey}x-#{$sizekey} {
|
||||
#{$type}-left: $size * $spacing-base-size;
|
||||
#{$type}-right: $size * $spacing-base-size;
|
||||
}
|
||||
|
||||
.#{$typekey}y-#{$sizekey} {
|
||||
#{$type}-top: $size * $spacing-base-size;
|
||||
#{$type}-bottom: $size * $spacing-base-size;
|
||||
}
|
||||
}
|
||||
|
||||
//.mt-1
|
||||
@each $directionkey, $direction in $spacing-directions {
|
||||
@each $sizekey, $size in $spacing-sizes {
|
||||
.#{$typekey}#{$directionkey}-#{$sizekey} {
|
||||
#{$type}-#{$direction}: $size * $spacing-base-size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.#{$typekey} {
|
||||
#{$type}: 0;
|
||||
}
|
||||
}
|
|
@ -8,9 +8,9 @@ interface OBJ {
|
|||
objectUrl: string;
|
||||
preSignedUrl: string;
|
||||
}
|
||||
// export const getPreSignedUrl = async (fileName: string) => {
|
||||
// const resp = await api.get<OBJ>("/file/getPreSignedUrl", {
|
||||
// fileName,
|
||||
// });
|
||||
// return resp.data as OBJ;
|
||||
// };
|
||||
export const getPreSignedUrl = async (fileName: string) => {
|
||||
const resp = await api.get<OBJ>("/file/getPreSignedUrl", {
|
||||
fileName,
|
||||
});
|
||||
return resp.data as OBJ;
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
>
|
||||
<n-button
|
||||
dashed
|
||||
style="margin-right: 5px;"
|
||||
style="margin-right: 5px"
|
||||
>
|
||||
<Icon name="LineMdUpload" />
|
||||
<span>选择照片上传</span>
|
||||
|
|
15
src/main.ts
15
src/main.ts
|
@ -1,19 +1,16 @@
|
|||
import { createApp } from "vue";
|
||||
|
||||
// pinia store
|
||||
import pinia from "@/stores";
|
||||
import "animate.css";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
import "./assets/scss/common.scss";
|
||||
import './assets/main.scss'
|
||||
// import { initEnums, } from "@/utils/emnus";
|
||||
|
||||
// initEnums();
|
||||
|
||||
import "./assets/main.scss";
|
||||
// import "./assets/scss/_variables.scss";
|
||||
import './assets/scss/style.scss';
|
||||
// @ts-ignore
|
||||
import DataVVue3 from "@kjgl77/datav-vue3";
|
||||
const app = createApp(App);
|
||||
|
||||
app.use(router);
|
||||
app.use(pinia);
|
||||
|
||||
app.use(DataVVue3);
|
||||
app.mount("#app");
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 289 KiB |
|
@ -0,0 +1,146 @@
|
|||
<script setup lang="tsx">
|
||||
import { ref, watch, defineProps, onMounted } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
// 接收 props
|
||||
const props = defineProps<{
|
||||
cdata: {
|
||||
category: string[];
|
||||
rateData: number[];
|
||||
barData: number[];
|
||||
lineData: number[];
|
||||
};
|
||||
}>();
|
||||
|
||||
// 图表容器 DOM 引用
|
||||
const chartContainerRef = ref<HTMLDivElement | null>(null);
|
||||
// echarts 实例
|
||||
let chartInstance: echarts.ECharts | null = null;
|
||||
|
||||
// 初始化图表
|
||||
const initChart = (options: echarts.EChartsOption) => {
|
||||
if (chartContainerRef.value) {
|
||||
if (!chartInstance) {
|
||||
chartInstance = echarts.init(chartContainerRef.value);
|
||||
}
|
||||
chartInstance.setOption(options);
|
||||
}
|
||||
};
|
||||
|
||||
// 构建图表配置项
|
||||
const getOptions = (val: typeof props.cdata): echarts.EChartsOption => {
|
||||
return {
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: "item",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
label: {
|
||||
show: true,
|
||||
backgroundColor: "#7B7DDC",
|
||||
},
|
||||
},
|
||||
},
|
||||
legend: { show: true },
|
||||
grid: {
|
||||
// @ts-ignore
|
||||
x: "8%",
|
||||
width: "88%",
|
||||
top: "5%",
|
||||
bottom: "7%",
|
||||
},
|
||||
xAxis: {
|
||||
data: val.category,
|
||||
axisLine: { lineStyle: { color: "#B4B4B4" } },
|
||||
axisTick: { show: false },
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
splitLine: { show: false },
|
||||
axisLine: { lineStyle: { color: "#B4B4B4" } },
|
||||
axisLabel: { formatter: "{value} " },
|
||||
},
|
||||
{
|
||||
splitLine: { show: false },
|
||||
axisLine: { lineStyle: { color: "#B4B4B4" } },
|
||||
axisLabel: { formatter: "{value} " },
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "贯通率",
|
||||
type: "line",
|
||||
smooth: true,
|
||||
showAllSymbol: true,
|
||||
symbol: "emptyCircle",
|
||||
symbolSize: 8,
|
||||
yAxisIndex: 1,
|
||||
itemStyle: {
|
||||
// @ts-ignore
|
||||
normal: {
|
||||
color: "#F02FC2",
|
||||
},
|
||||
},
|
||||
data: val.rateData,
|
||||
},
|
||||
{
|
||||
name: "已贯通",
|
||||
type: "bar",
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: 5,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: "#956FD4" },
|
||||
{ offset: 1, color: "#3EACE5" },
|
||||
]),
|
||||
},
|
||||
},
|
||||
data: val.barData,
|
||||
},
|
||||
{
|
||||
name: "计划贯通",
|
||||
type: "bar",
|
||||
barGap: "-100%",
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: 5,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: "rgba(156,107,211,0.8)" },
|
||||
{ offset: 0.2, color: "rgba(156,107,211,0.5)" },
|
||||
{ offset: 1, color: "rgba(156,107,211,0.2)" },
|
||||
]),
|
||||
},
|
||||
},
|
||||
z: -12,
|
||||
data: val.lineData,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
// 监听 props 数据变化,更新图表
|
||||
watch(
|
||||
() => props.cdata,
|
||||
(val) => {
|
||||
initChart(getOptions(val));
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
initChart(getOptions(props.cdata));
|
||||
});
|
||||
|
||||
// 渲染
|
||||
const height = "450px";
|
||||
const width = "100%";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="chartContainerRef"
|
||||
:style="{ height, width }"
|
||||
/>
|
||||
</template>
|
|
@ -0,0 +1,71 @@
|
|||
<script setup lang="tsx">
|
||||
import { reactive, onMounted } from "vue";
|
||||
import Draw from "./draw.vue";
|
||||
|
||||
const cdata = reactive({
|
||||
category: [
|
||||
"市区",
|
||||
"万州",
|
||||
"江北",
|
||||
"南岸",
|
||||
"北碚",
|
||||
"綦南",
|
||||
"长寿",
|
||||
"永川",
|
||||
"璧山",
|
||||
"江津",
|
||||
"城口",
|
||||
"大足",
|
||||
"垫江",
|
||||
"丰都",
|
||||
"奉节",
|
||||
"合川",
|
||||
"江津区",
|
||||
"开州",
|
||||
"南川",
|
||||
"彭水",
|
||||
"黔江",
|
||||
"石柱",
|
||||
"铜梁",
|
||||
"潼南",
|
||||
"巫山",
|
||||
"巫溪",
|
||||
"武隆",
|
||||
"秀山",
|
||||
"酉阳",
|
||||
"云阳",
|
||||
"忠县",
|
||||
"川东",
|
||||
"检修",
|
||||
],
|
||||
lineData: [
|
||||
18092, 20728, 24045, 28348, 32808, 36097, 39867, 44715, 48444, 50415,
|
||||
56061, 62677, 59521, 67560, 18092, 20728, 24045, 28348, 32808, 36097,
|
||||
39867, 44715, 48444, 50415, 36097, 39867, 44715, 48444, 50415, 50061,
|
||||
32677, 49521, 32808,
|
||||
],
|
||||
barData: [
|
||||
4600, 5000, 5500, 6500, 7500, 8500, 9900, 12500, 14000, 21500, 23200,
|
||||
24450, 25250, 33300, 4600, 5000, 5500, 6500, 7500, 8500, 9900, 22500,
|
||||
14000, 21500, 8500, 9900, 12500, 14000, 21500, 23200, 24450, 25250, 7500,
|
||||
],
|
||||
rateData: [] as string[],
|
||||
});
|
||||
|
||||
// 自动生成贯通率数据
|
||||
const setData = () => {
|
||||
cdata.rateData = cdata.barData.map((val, i) => {
|
||||
const rate = val / cdata.lineData[i];
|
||||
return rate.toFixed(2);
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
setData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- @vue-ignore -->
|
||||
<Draw :cdata="cdata" />
|
||||
</template>
|
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<div class="bottomLeft">
|
||||
<div class="bg-color-black">
|
||||
<div class="d-flex pt-2 pl-2">
|
||||
<span>
|
||||
<i class="iconfont icon-chart-line" />
|
||||
</span>
|
||||
<div class="d-flex">
|
||||
<span class="fs-xl text mx-2 mt-1">数据统计图</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<chart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Chart from "./chart/index.vue";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$box-height: 520px;
|
||||
$box-width: 100%;
|
||||
.bottomLeft {
|
||||
padding: 20px 16px;
|
||||
height: $box-height;
|
||||
width: $box-width;
|
||||
border-radius: 5px;
|
||||
.bg-color-black {
|
||||
height: $box-height - 35px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.text {
|
||||
color: #c3cbde;
|
||||
}
|
||||
.chart-box {
|
||||
margin-top: 16px;
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
.active-ring-name {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,365 @@
|
|||
import { defineComponent, watch, ref } from 'vue';
|
||||
// 声明类型
|
||||
const PropsType = {
|
||||
cdata: {
|
||||
type: Object,
|
||||
require: true
|
||||
}
|
||||
} as const
|
||||
|
||||
// 定义主体
|
||||
export default defineComponent({
|
||||
props: PropsType,
|
||||
setup(props) {
|
||||
// 定义 ref
|
||||
const chartRef = ref()
|
||||
// 定义颜色
|
||||
const colorList = {
|
||||
linearYtoG: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: "#f5b44d"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#28f8de"
|
||||
}
|
||||
]
|
||||
},
|
||||
linearGtoB: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: "#43dfa2"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#28f8de"
|
||||
}
|
||||
]
|
||||
},
|
||||
linearBtoG: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: "#1c98e8"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#28f8de"
|
||||
}
|
||||
]
|
||||
},
|
||||
areaBtoG: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(35,184,210,.2)"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(35,184,210,0)"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
// 配置项
|
||||
let options ={}
|
||||
|
||||
// 监听
|
||||
watch(
|
||||
() => props.cdata,
|
||||
(val: any) => {
|
||||
options = {
|
||||
title: {
|
||||
text: "",
|
||||
textStyle: {
|
||||
color: "#D3D6DD",
|
||||
fontSize: 24,
|
||||
fontWeight: "normal"
|
||||
},
|
||||
subtext: val.year + "/" + val.weekCategory[6],
|
||||
subtextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 16
|
||||
},
|
||||
top: 50,
|
||||
left: 80
|
||||
},
|
||||
legend: {
|
||||
top: 120,
|
||||
left: 80,
|
||||
orient: "vertical",
|
||||
itemGap: 15,
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
data: ["平均指标", "我的指标"],
|
||||
textStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 14
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item"
|
||||
},
|
||||
radar: {
|
||||
center: ["68%", "27%"],
|
||||
radius: "40%",
|
||||
name: {
|
||||
color: "#fff"
|
||||
},
|
||||
splitNumber: 8,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: colorList.linearYtoG,
|
||||
opacity: 0.6
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: colorList.linearYtoG,
|
||||
opacity: 0.6
|
||||
}
|
||||
},
|
||||
splitArea: {
|
||||
areaStyle: {
|
||||
color: "#fff",
|
||||
opacity: 0.1,
|
||||
shadowBlur: 25,
|
||||
shadowColor: "#000",
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 5
|
||||
}
|
||||
},
|
||||
indicator: [
|
||||
{
|
||||
name: "服务态度",
|
||||
max: val.maxData
|
||||
},
|
||||
{
|
||||
name: "产品质量",
|
||||
max: 10
|
||||
},
|
||||
{
|
||||
name: "任务效率",
|
||||
max: 12
|
||||
},
|
||||
{
|
||||
name: "售后保障",
|
||||
max: 3.5
|
||||
}
|
||||
]
|
||||
},
|
||||
grid: {
|
||||
left: 90,
|
||||
right: 80,
|
||||
bottom: '15%',
|
||||
top: "50%"
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
position: "bottom",
|
||||
axisLine: true,
|
||||
axisLabel: {
|
||||
color: "rgba(255,255,255,.8)",
|
||||
fontSize: 12
|
||||
},
|
||||
data: val.weekCategory
|
||||
},
|
||||
// 下方Y轴
|
||||
yAxis: {
|
||||
name: "工单",
|
||||
nameLocation: "end",
|
||||
nameGap: 24,
|
||||
nameTextStyle: {
|
||||
color: "rgba(255,255,255,.5)",
|
||||
fontSize: 14
|
||||
},
|
||||
max: val.maxData,
|
||||
splitNumber: 4,
|
||||
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#fff",
|
||||
opacity: 0.1
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: "rgba(255,255,255,.8)",
|
||||
fontSize: 12
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "",
|
||||
type: "radar",
|
||||
symbolSize: 0,
|
||||
data: [
|
||||
{
|
||||
value: val.radarDataAvg[6],
|
||||
name: "平均指标",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "#f8d351"
|
||||
}
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: "#f8d351",
|
||||
shadowBlur: 25,
|
||||
shadowColor: "rgba(248,211,81,.3)",
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: -10,
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
value: val.radarData[6],
|
||||
name: "我的指标",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "#43dfa2"
|
||||
}
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: colorList.linearGtoB,
|
||||
shadowBlur: 15,
|
||||
shadowColor: "rgba(0,0,0,.2)",
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 5,
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "",
|
||||
type: "line",
|
||||
smooth: true,
|
||||
symbol: "emptyCircle",
|
||||
symbolSize: 8,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
color: colorList.linearBtoG,
|
||||
width: 3
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: colorList.areaBtoG
|
||||
}
|
||||
},
|
||||
data: val.weekLineData,
|
||||
lineSmooth: true,
|
||||
markLine: {
|
||||
silent: true,
|
||||
data: [
|
||||
{
|
||||
type: "average",
|
||||
name: "平均值"
|
||||
}
|
||||
],
|
||||
precision: 0,
|
||||
label: {
|
||||
normal: {
|
||||
formatter: "平均值: \n {c}"
|
||||
}
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
color: "rgba(248,211,81,.7)"
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
position: "top",
|
||||
formatter: "{c} m",
|
||||
backgroundColor: "rgba(28,152,232,.2)",
|
||||
padding: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "占位背景",
|
||||
type: "bar",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
show: true,
|
||||
color: "#000",
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
silent: true,
|
||||
barWidth: "50%",
|
||||
data: val.weekMaxData,
|
||||
animation: false
|
||||
}
|
||||
]
|
||||
}
|
||||
// 手动触发更新
|
||||
if (chartRef.value) {
|
||||
// 通过初始化参数打入数据
|
||||
chartRef.value.initChart(options)
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
return () => {
|
||||
const height = "480px"
|
||||
const width = "100%"
|
||||
|
||||
return <div>
|
||||
<echart ref={chartRef} height={height} width={width} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
import { defineComponent, reactive, onMounted, ref, onUnmounted } from "vue";
|
||||
import Draw from "./draw";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Draw,
|
||||
},
|
||||
setup() {
|
||||
const drawTiming = ref(0);
|
||||
const cdata = reactive({
|
||||
year: null,
|
||||
weekCategory: [],
|
||||
radarData: [],
|
||||
radarDataAvg: [],
|
||||
maxData: 12000,
|
||||
weekMaxData: [],
|
||||
weekLineData: [],
|
||||
});
|
||||
|
||||
// methods
|
||||
const setData = () => {
|
||||
// 清空轮询数据
|
||||
cdata.weekCategory = [];
|
||||
cdata.weekMaxData = [];
|
||||
cdata.weekLineData = [];
|
||||
cdata.radarData = [];
|
||||
cdata.radarDataAvg = [];
|
||||
|
||||
const dateBase = new Date();
|
||||
cdata.year = dateBase.getFullYear();
|
||||
// 周数据
|
||||
for (let i = 0; i < 7; i++) {
|
||||
// 日期
|
||||
const date = new Date();
|
||||
cdata.weekCategory.unshift(
|
||||
[date.getMonth() + 1, date.getDate() - i].join("/")
|
||||
);
|
||||
|
||||
// 折线图数据
|
||||
cdata.weekMaxData.push(cdata.maxData);
|
||||
const distance = Math.round(Math.random() * 11000 + 500);
|
||||
cdata.weekLineData.push(distance);
|
||||
|
||||
// 雷达图数据
|
||||
// 我的指标
|
||||
const averageSpeed = +(Math.random() * 5 + 3).toFixed(3);
|
||||
const maxSpeed = averageSpeed + +(Math.random() * 3).toFixed(2);
|
||||
const hour = +(distance / 1000 / averageSpeed).toFixed(1);
|
||||
const radarDayData = [distance, averageSpeed, maxSpeed, hour];
|
||||
cdata.radarData.unshift(radarDayData);
|
||||
|
||||
// 平均指标
|
||||
const distanceAvg = Math.round(Math.random() * 8000 + 4000);
|
||||
const averageSpeedAvg = +(Math.random() * 4 + 4).toFixed(3);
|
||||
const maxSpeedAvg = averageSpeedAvg + +(Math.random() * 2).toFixed(2);
|
||||
const hourAvg = +(distance / 1000 / averageSpeed).toFixed(1);
|
||||
const radarDayDataAvg = [
|
||||
distanceAvg,
|
||||
averageSpeedAvg,
|
||||
maxSpeedAvg,
|
||||
hourAvg,
|
||||
];
|
||||
cdata.radarDataAvg.unshift(radarDayDataAvg);
|
||||
}
|
||||
};
|
||||
|
||||
// 定时函数
|
||||
const drawTimingFn = () => {
|
||||
setData();
|
||||
drawTiming.value = setInterval(() => {
|
||||
setData();
|
||||
}, 6000);
|
||||
};
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
drawTimingFn();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(drawTiming.value);
|
||||
});
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<div>
|
||||
<Draw cdata={cdata} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<div class="bottomRight">
|
||||
<div class="bg-color-black">
|
||||
<div class="d-flex pt-2 pl-2">
|
||||
<span>
|
||||
<i class="iconfont icon-chart-area" />
|
||||
</span>
|
||||
<div class="d-flex">
|
||||
<span class="fs-xl text mx-2 mt-1">数据统计图</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<chart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Chart from "./chart/index";
|
||||
</script>
|
||||
|
||||
<style lang="scss" class>
|
||||
$box-height: 520px;
|
||||
$box-width: 100%;
|
||||
.bottomRight {
|
||||
padding: 14px 16px;
|
||||
height: $box-height;
|
||||
width: $box-width;
|
||||
border-radius: 5px;
|
||||
.bg-color-black {
|
||||
height: $box-height - 30px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.text {
|
||||
color: #c3cbde;
|
||||
}
|
||||
.chart-box {
|
||||
margin-top: 16px;
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
.active-ring-name {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,92 @@
|
|||
import { defineComponent, watch, shallowReactive } from 'vue'
|
||||
|
||||
// 声明类型
|
||||
const PropsType = {
|
||||
tips: {
|
||||
type: Number,
|
||||
default: 50,
|
||||
require: true
|
||||
},
|
||||
colorObj: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
textStyle: "#3fc0fb",
|
||||
series: {
|
||||
color: ["#00bcd44a", "transparent"],
|
||||
dataColor: {
|
||||
normal: "#03a9f4",
|
||||
shadowColor: "#97e2f5"
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} as const
|
||||
|
||||
// 定义主体
|
||||
export default defineComponent({
|
||||
props: PropsType,
|
||||
setup(props) {
|
||||
// 配置项
|
||||
let options = shallowReactive({title:null,series:null})
|
||||
|
||||
watch(
|
||||
() => props.tips,
|
||||
(val: any) => {
|
||||
options = {
|
||||
title: {
|
||||
text: val * 1 + "%",
|
||||
x: "center",
|
||||
y: "center",
|
||||
textStyle: {
|
||||
color: props.colorObj.textStyle,
|
||||
fontSize: 16
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "pie",
|
||||
radius: ["75%", "80%"],
|
||||
center: ["50%", "50%"],
|
||||
hoverAnimation: false,
|
||||
color: props.colorObj.series.color,
|
||||
label: {
|
||||
normal: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: val,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: props.colorObj.series.dataColor.normal,
|
||||
shadowBlur: 10,
|
||||
shadowColor: props.colorObj.series.dataColor.shadowColor
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
value: 100 - val
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
return () => {
|
||||
const height = "100px"
|
||||
const width = "120px"
|
||||
|
||||
return <div>
|
||||
<echart options={options} height={height} width={width} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
<template>
|
||||
<div class="center">
|
||||
<div class="up">
|
||||
<div
|
||||
class="bg-color-black item"
|
||||
v-for="item in titleItem"
|
||||
:key="item.title"
|
||||
>
|
||||
<p class="ml-3 colorBlue fw-b">{{ item.title }}</p>
|
||||
<div>
|
||||
<dv-digital-flop
|
||||
class="dv-dig-flop ml-1 mt-1 pl-3"
|
||||
:config="item.config"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="down">
|
||||
<div class="ranking bg-color-black">
|
||||
<span>
|
||||
<i class="iconfont icon-tongji2"></i>
|
||||
</span>
|
||||
<span class="fs-xl text mx-2 mb-1">年度负责人组件达标榜</span>
|
||||
<dv-scroll-ranking-board
|
||||
class="dv-scr-rank-board"
|
||||
:config="ranking"
|
||||
/>
|
||||
</div>
|
||||
<div class="percent">
|
||||
<div class="item bg-color-black">
|
||||
<span>今日任务通过率</span>
|
||||
<chart
|
||||
:tips="rate[0].tips"
|
||||
:colorObj="rate[0].colorData"
|
||||
/>
|
||||
</div>
|
||||
<div class="item bg-color-black">
|
||||
<span>今日任务达标率</span>
|
||||
<chart
|
||||
:tips="rate[1].tips"
|
||||
:colorObj="rate[1].colorData"
|
||||
/>
|
||||
</div>
|
||||
<div class="water">
|
||||
<dv-water-level-pond
|
||||
class="dv-wa-le-po"
|
||||
:config="water"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted } from "vue";
|
||||
import Chart from "../center/chart/draw";
|
||||
|
||||
// 下层数据
|
||||
const titleDate = [
|
||||
{
|
||||
number: 1020,
|
||||
text: "今年累计任务建次数",
|
||||
},
|
||||
{
|
||||
number: 18,
|
||||
text: "本月累计任务次数",
|
||||
},
|
||||
{
|
||||
number: 4,
|
||||
text: "今日累计任务次数",
|
||||
},
|
||||
{
|
||||
number: 71,
|
||||
text: "今年失败任务次数",
|
||||
},
|
||||
{
|
||||
number: 949,
|
||||
text: "今年失败成功次数",
|
||||
},
|
||||
{
|
||||
number: 811,
|
||||
text: "今年达标任务个数",
|
||||
},
|
||||
];
|
||||
|
||||
const titleItem = reactive<any[]>([]);
|
||||
|
||||
// 初始化数据
|
||||
onMounted(() => {
|
||||
setData();
|
||||
});
|
||||
|
||||
// 设置数据
|
||||
const setData = () => {
|
||||
titleDate.forEach((e) => {
|
||||
titleItem.push({
|
||||
title: e.text,
|
||||
config: {
|
||||
number: [e.number],
|
||||
toFixed: 1,
|
||||
textAlign: "left",
|
||||
content: "{nt}",
|
||||
style: {
|
||||
fontSize: 26,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 排名数据
|
||||
const ranking = reactive({
|
||||
data: [
|
||||
{ name: "周口", value: 55 },
|
||||
{ name: "南阳", value: 120 },
|
||||
{ name: "西峡", value: 78 },
|
||||
{ name: "驻马店", value: 66 },
|
||||
{ name: "新乡", value: 80 },
|
||||
{ name: "新乡2", value: 80 },
|
||||
{ name: "新乡3", value: 80 },
|
||||
{ name: "新乡4", value: 80 },
|
||||
{ name: "新乡5", value: 80 },
|
||||
{ name: "新乡6", value: 80 },
|
||||
],
|
||||
carousel: "single",
|
||||
unit: "人",
|
||||
});
|
||||
|
||||
// 水球图数据
|
||||
const water = reactive({
|
||||
data: [24, 45],
|
||||
shape: "roundRect",
|
||||
formatter: "{value}%",
|
||||
waveNum: 3,
|
||||
});
|
||||
|
||||
// 仪表盘数据
|
||||
const rate = reactive([
|
||||
{
|
||||
id: "centerRate1",
|
||||
tips: 60,
|
||||
colorData: {
|
||||
textStyle: "#3fc0fb",
|
||||
series: {
|
||||
color: ["#00bcd44a", "transparent"],
|
||||
dataColor: {
|
||||
normal: "#03a9f4",
|
||||
shadowColor: "#97e2f5",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "centerRate2",
|
||||
tips: 40,
|
||||
colorData: {
|
||||
textStyle: "#67e0e3",
|
||||
series: {
|
||||
color: ["#faf3a378", "transparent"],
|
||||
dataColor: {
|
||||
normal: "#ff9800",
|
||||
shadowColor: "#fcebad",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.up {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
.item {
|
||||
border-radius: 6px;
|
||||
padding-top: 8px;
|
||||
margin-top: 8px;
|
||||
width: 32%;
|
||||
height: 70px;
|
||||
.dv-dig-flop {
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.down {
|
||||
padding: 6px 4px;
|
||||
padding-bottom: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
height: 255px;
|
||||
justify-content: space-between;
|
||||
.bg-color-black {
|
||||
border-radius: 5px;
|
||||
}
|
||||
.ranking {
|
||||
padding: 10px;
|
||||
width: 59%;
|
||||
.dv-scr-rank-board {
|
||||
height: 220px;
|
||||
}
|
||||
}
|
||||
.percent {
|
||||
width: 40%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.item {
|
||||
width: 50%;
|
||||
height: 120px;
|
||||
span {
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
.water {
|
||||
width: 100%;
|
||||
.dv-wa-le-po {
|
||||
height: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,97 @@
|
|||
import { defineComponent, ref, watch, shallowReactive } from 'vue'
|
||||
|
||||
// 声明类型
|
||||
const PropsType = {
|
||||
cdata: {
|
||||
type: Object,
|
||||
require: true
|
||||
}
|
||||
} as const
|
||||
|
||||
// 定义主体
|
||||
export default defineComponent({
|
||||
props: PropsType,
|
||||
setup(props) {
|
||||
// 定义 ref
|
||||
const chartRef = ref()
|
||||
// 配置项
|
||||
let options = shallowReactive({color:null,tooltip:null,toolbox:null,calculable:null,legend:null,series:null})
|
||||
|
||||
watch(
|
||||
() => props.cdata,
|
||||
(val: any) => {
|
||||
options = {
|
||||
color: [
|
||||
'#37a2da',
|
||||
'#32c5e9',
|
||||
'#9fe6b8',
|
||||
'#ffdb5c',
|
||||
'#ff9f7f',
|
||||
'#fb7293',
|
||||
'#e7bcf3',
|
||||
'#8378ea'
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
||||
},
|
||||
toolbox: {
|
||||
show: true
|
||||
},
|
||||
calculable: true,
|
||||
legend: {
|
||||
orient: 'horizontal',
|
||||
icon: 'circle',
|
||||
bottom: 0,
|
||||
x: 'center',
|
||||
data: val.xData,
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '通过率统计',
|
||||
type: 'pie',
|
||||
radius: [10, 50],
|
||||
roseType: 'area',
|
||||
center: ['50%', '40%'],
|
||||
itemStyle: {
|
||||
borderRadius: 5
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
color: "#fff",
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
data: val.seriesData
|
||||
}
|
||||
]
|
||||
}
|
||||
// 手动触发更新
|
||||
if (chartRef.value) {
|
||||
// 通过初始化参数打入数据
|
||||
chartRef.value.initChart(options)
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
return () => {
|
||||
const height = "220px"
|
||||
const width = "260px"
|
||||
|
||||
return <div>
|
||||
<echart ref={chartRef} options={options} height={height} width={width} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import { defineComponent, onUnmounted, reactive } from 'vue'
|
||||
import Draw from './draw'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Draw,
|
||||
},
|
||||
setup() {
|
||||
let intervalInstance = null
|
||||
const cdata = reactive({
|
||||
xData: ['数据1', '数据2', '数据3', '数据4', '数据5', '数据6'],
|
||||
seriesData: [
|
||||
{ value: 10, name: '数据1' },
|
||||
{ value: 5, name: '数据2' },
|
||||
{ value: 15, name: '数据3' },
|
||||
{ value: 25, name: '数据4' },
|
||||
{ value: 20, name: '数据5' },
|
||||
{ value: 35, name: '数据6' },
|
||||
],
|
||||
})
|
||||
intervalInstance = setInterval(() => {
|
||||
const data = cdata.seriesData
|
||||
cdata.seriesData = data.map((e) => {
|
||||
return { value: e.value + 10, name: e.name }
|
||||
})
|
||||
}, 1000)
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(intervalInstance)
|
||||
})
|
||||
return () => {
|
||||
return (
|
||||
<div>
|
||||
<Draw cdata={cdata} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
})
|
|
@ -0,0 +1,171 @@
|
|||
<template>
|
||||
<div class="centreLeft1">
|
||||
<div class="bg-color-black">
|
||||
<div class="d-flex pt-2 pl-2">
|
||||
<span>
|
||||
<i class="iconfont icon-tongji4" />
|
||||
</span>
|
||||
<div class="d-flex">
|
||||
<span class="fs-xl text mx-2">任务通过率</span>
|
||||
<dv-decoration-3 class="dv-dec-3" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex jc-center">
|
||||
<chart />
|
||||
</div>
|
||||
<!-- 4个主要的数据 -->
|
||||
<div class="bottom-data">
|
||||
<div
|
||||
class="item-box mt-2"
|
||||
v-for="(item, index) in numberData"
|
||||
:key="index"
|
||||
>
|
||||
<div class="d-flex jc-end">
|
||||
<i
|
||||
class="iconfont"
|
||||
:class="[iconFont[index]]"
|
||||
/>
|
||||
<dv-digital-flop
|
||||
class="dv-digital-flop"
|
||||
:config="item.config"
|
||||
/>
|
||||
</div>
|
||||
<p>
|
||||
<span>{{ item.text }}</span>
|
||||
<span class="colorYellow">(件)</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, onUnmounted, reactive } from "vue";
|
||||
import Chart from "./chart/index";
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Chart,
|
||||
},
|
||||
setup() {
|
||||
// 下层数据
|
||||
const dataArr = [
|
||||
{
|
||||
number: 150,
|
||||
text: "今日构建总量",
|
||||
},
|
||||
{
|
||||
number: 144,
|
||||
text: "总共完成数量",
|
||||
},
|
||||
{
|
||||
number: 361,
|
||||
text: "正在编译数量",
|
||||
},
|
||||
{
|
||||
number: 571,
|
||||
text: "未通过数量",
|
||||
},
|
||||
];
|
||||
// 对应图标
|
||||
const iconFont = [
|
||||
"icon-diagnose",
|
||||
"icon-monitoring",
|
||||
"icon-cloudupload",
|
||||
"icon-clouddownload",
|
||||
];
|
||||
const numberData = reactive([]);
|
||||
let intervalInstance = null;
|
||||
onMounted(() => {
|
||||
setData();
|
||||
changeTiming();
|
||||
});
|
||||
|
||||
const setData = () => {
|
||||
dataArr.forEach((e) => {
|
||||
numberData.push({
|
||||
config: {
|
||||
number: [e.number],
|
||||
toFixed: 1,
|
||||
content: "{nt}",
|
||||
style: {
|
||||
fontSize: 24,
|
||||
},
|
||||
},
|
||||
text: e.text,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const changeTiming = () => {
|
||||
intervalInstance = setInterval(() => {
|
||||
changeNumber();
|
||||
}, 2000);
|
||||
};
|
||||
const changeNumber = () => {
|
||||
numberData.forEach((item, index) => {
|
||||
item.config.number[0] += ++index;
|
||||
item.config = { ...item.config };
|
||||
});
|
||||
};
|
||||
onUnmounted(() => {
|
||||
clearInterval(intervalInstance);
|
||||
});
|
||||
|
||||
return { numberData, iconFont };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$box-width: 300px;
|
||||
$box-height: 410px;
|
||||
|
||||
.centreLeft1 {
|
||||
padding: 16px;
|
||||
height: $box-height;
|
||||
width: $box-width;
|
||||
border-radius: 10px;
|
||||
.bg-color-black {
|
||||
height: $box-height - 30px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.text {
|
||||
color: #c3cbde;
|
||||
}
|
||||
.dv-dec-3 {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.bottom-data {
|
||||
.item-box {
|
||||
& > div {
|
||||
padding-right: 5px;
|
||||
}
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
position: relative;
|
||||
width: 50%;
|
||||
color: #d3d6dd;
|
||||
.dv-digital-flop {
|
||||
width: 120px;
|
||||
height: 30px;
|
||||
}
|
||||
i {
|
||||
font-size: 20px;
|
||||
line-height: 30px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.colorYellow {
|
||||
color: yellowgreen;
|
||||
}
|
||||
p {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,217 @@
|
|||
import { defineComponent, watch, shallowReactive, nextTick, ref, onUnmounted } from 'vue';
|
||||
|
||||
// 声明类型
|
||||
const PropsType = {
|
||||
cdata: {
|
||||
type: Array,
|
||||
require: true
|
||||
}
|
||||
} as const
|
||||
|
||||
// 定义主体
|
||||
export default defineComponent({
|
||||
props: PropsType,
|
||||
setup(props) {
|
||||
// 配置项
|
||||
let options = shallowReactive({showLegendSymbol:null,tooltip:null,geo:null,series:null})
|
||||
// 设置点的位置(经纬度)
|
||||
const geoCoordMap = {
|
||||
厦门市: [118.11022, 24.490474, 20],
|
||||
福州市: [119.206239, 26.275302, 20],
|
||||
泉州市: [118.589421, 24.908853, 20],
|
||||
漳州市: [117.561801, 24.510897, 20],
|
||||
龙岩市: [116.82978, 25.391603, 20],
|
||||
莆田市: [119.007558, 25.591011, 20],
|
||||
三明市: [117.435001, 26.465444, 20],
|
||||
南平市: [118.178459, 27.535627, 20],
|
||||
宁德市: [119.527082, 27.15924, 20],
|
||||
}
|
||||
const seriesData = [
|
||||
{
|
||||
name: '厦门市',
|
||||
},
|
||||
{
|
||||
name: '福州市',
|
||||
},
|
||||
{
|
||||
name: '泉州市',
|
||||
},
|
||||
{
|
||||
name: '漳州市',
|
||||
},
|
||||
{
|
||||
name: '龙岩市',
|
||||
},
|
||||
{
|
||||
name: '莆田市',
|
||||
},
|
||||
{
|
||||
name: '三明市',
|
||||
},
|
||||
{
|
||||
name: '南平市',
|
||||
},
|
||||
{
|
||||
name: '宁德市',
|
||||
},
|
||||
]
|
||||
const convertData = function (data) {
|
||||
const scatterData = [];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const geoCoord = geoCoordMap[data[i].name];
|
||||
if (geoCoord) {
|
||||
scatterData.push({
|
||||
name: data[i].name,
|
||||
value: geoCoord.concat(data[i].value),
|
||||
});
|
||||
}
|
||||
}
|
||||
return scatterData;
|
||||
}
|
||||
// 监听
|
||||
watch(
|
||||
() => props.cdata,
|
||||
(val: any) => {
|
||||
options = {
|
||||
showLegendSymbol: true,
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
lineHeight: 22,
|
||||
},
|
||||
position: point => {
|
||||
// 固定在顶部
|
||||
return [point[0] + 50, point[1] - 20];
|
||||
},
|
||||
// 如果需要自定义 tooltip样式,需要使用formatter
|
||||
/*
|
||||
formatter: params => {
|
||||
return `<div style=""> ... </div>`
|
||||
}
|
||||
*/
|
||||
},
|
||||
// 如果需要根据不同的数据展示深浅不一的颜色,则把这里打开
|
||||
// visualMap: {
|
||||
// min: 0,
|
||||
// max: 10,
|
||||
// show: false,
|
||||
// seriesIndex: 0,
|
||||
// // 颜色
|
||||
// inRange: {
|
||||
// color: ['rgba(41,166,206, .5)', 'rgba(69,117,245, .9)'],
|
||||
// },
|
||||
// },
|
||||
// 底部背景
|
||||
geo: [{
|
||||
show: true,
|
||||
aspectScale: 0.85, //长宽比
|
||||
zoom: 1.16,
|
||||
top: '10%',
|
||||
left: '17%',
|
||||
map: '福建',
|
||||
roam: false,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
borderColor: '#7ad5ff7f',
|
||||
shadowOffsetY: 5,
|
||||
shadowBlur: 15,
|
||||
areaColor: 'rgba(5,21,35,0.1)'
|
||||
}
|
||||
}
|
||||
}],
|
||||
series: [
|
||||
{
|
||||
name: '相关指数',
|
||||
type: 'map',
|
||||
aspectScale: 0.85, //长宽比
|
||||
zoom: 1.16, //缩放
|
||||
mapType: '福建', // 自定义扩展图表类型
|
||||
top: '9%',
|
||||
left: '16%',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
// 背景渐变色
|
||||
areaColor: {
|
||||
type: 'linear-gradient',
|
||||
x: 0,
|
||||
y: 300,
|
||||
x2: 0,
|
||||
y2: 0,
|
||||
colorStops: [{
|
||||
offset: 0,
|
||||
color: 'RGBA(19,96,187,1)' // 0% 处的颜色
|
||||
}, {
|
||||
offset: 1,
|
||||
color: 'RGBA(7,193,223,1)' // 50% 处的颜色
|
||||
}],
|
||||
global: true // 缺省为 false
|
||||
},
|
||||
borderColor: '#4ECEE6',
|
||||
borderWidth: 1,
|
||||
},
|
||||
emphasis: {
|
||||
areaColor: '#4f7fff',
|
||||
borderColor: 'rgba(0,242,252,.6)',
|
||||
borderWidth: 2,
|
||||
shadowBlur: 10,
|
||||
shadowColor: '#00f2fc',
|
||||
},
|
||||
},
|
||||
label: {
|
||||
formatter: params => `${params.name}`,
|
||||
show: true,
|
||||
position: 'insideRight',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
color: '#efefef',
|
||||
},
|
||||
emphasis: {
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
},
|
||||
},
|
||||
},
|
||||
data: val,
|
||||
},
|
||||
{
|
||||
type: 'effectScatter',
|
||||
coordinateSystem: 'geo',
|
||||
symbolSize: 7,
|
||||
effectType: 'ripple',
|
||||
legendHoverLink: false,
|
||||
showEffectOn: 'render',
|
||||
rippleEffect: {
|
||||
period: 4,
|
||||
scale: 2.5,
|
||||
brushType: 'stroke',
|
||||
},
|
||||
zlevel: 1,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#99FBFE',
|
||||
shadowBlur: 5,
|
||||
shadowColor: '#fff',
|
||||
},
|
||||
},
|
||||
data: convertData(seriesData),
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
return () => {
|
||||
const height = "360px"
|
||||
const width = "330px"
|
||||
|
||||
return <div>
|
||||
<echart options={options} height={height} width={width} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { defineComponent, reactive } from 'vue'
|
||||
import Draw from './draw'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Draw
|
||||
},
|
||||
setup() {
|
||||
const cdata = reactive([
|
||||
{
|
||||
// 名字需要与 “common/map/fujian.js” 地图数据文件里面定义的一一对应,不能是 “福州” 或者 “闽” 之类的缩写
|
||||
name: '福州市',
|
||||
value: 10,
|
||||
elseData: {
|
||||
// 这里放置地图 tooltip 里想显示的数据
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '厦门市',
|
||||
value: 9,
|
||||
},
|
||||
{
|
||||
name: '漳州市',
|
||||
value: 8,
|
||||
},
|
||||
{
|
||||
name: '泉州市',
|
||||
value: 7,
|
||||
},
|
||||
{
|
||||
name: '三明市',
|
||||
value: 6,
|
||||
},
|
||||
{
|
||||
name: '莆田市',
|
||||
value: 5,
|
||||
},
|
||||
{
|
||||
name: '南平市',
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
name: '龙岩市',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
name: '宁德市',
|
||||
value: 2,
|
||||
}
|
||||
])
|
||||
|
||||
return () => {
|
||||
return <div>
|
||||
<Draw cdata={cdata} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div class="centreLeft1">
|
||||
<div class="bg-color-black">
|
||||
<div class="d-flex pt-2 pl-2">
|
||||
<span>
|
||||
<i class="iconfont icon-layer-group" />
|
||||
</span>
|
||||
<div class="d-flex">
|
||||
<span class="fs-xl text mx-2">地图数据</span>
|
||||
<dv-decoration-1 class="dv-dec-1" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex jc-center">
|
||||
<chart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Chart from "./chart/index";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.centreLeft1 {
|
||||
$box-width: 300px;
|
||||
$box-height: 410px;
|
||||
padding: 16px;
|
||||
height: $box-height;
|
||||
min-width: $box-width;
|
||||
border-radius: 5px;
|
||||
.bg-color-black {
|
||||
height: $box-height - 30px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.text {
|
||||
color: #c3cbde;
|
||||
}
|
||||
.dv-dec-1 {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
top: -3px;
|
||||
}
|
||||
.chart-box {
|
||||
margin-top: 16px;
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
.active-ring-name {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,131 @@
|
|||
import { defineComponent, watch, shallowReactive } from 'vue'
|
||||
|
||||
// 声明类型
|
||||
const PropsType = {
|
||||
cdata: {
|
||||
type: Object,
|
||||
require: true
|
||||
}
|
||||
} as const
|
||||
|
||||
// 定义主体
|
||||
export default defineComponent({
|
||||
props: PropsType,
|
||||
setup(props) {
|
||||
// 定义固定配置项
|
||||
const lineStyle = {
|
||||
normal: {
|
||||
width: 1,
|
||||
opacity: 0.5
|
||||
}
|
||||
};
|
||||
// 配置项
|
||||
let options = shallowReactive({radar:null,series:null})
|
||||
|
||||
watch(
|
||||
() => props.cdata,
|
||||
(val: any) => {
|
||||
options = {
|
||||
radar: {
|
||||
indicator: val.indicatorData,
|
||||
shape: "circle",
|
||||
splitNumber: 5,
|
||||
radius: ["0%", "65%"],
|
||||
name: {
|
||||
textStyle: {
|
||||
color: "rgb(238, 197, 102)"
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: [
|
||||
"rgba(238, 197, 102, 0.1)",
|
||||
"rgba(238, 197, 102, 0.2)",
|
||||
"rgba(238, 197, 102, 0.4)",
|
||||
"rgba(238, 197, 102, 0.6)",
|
||||
"rgba(238, 197, 102, 0.8)",
|
||||
"rgba(238, 197, 102, 1)"
|
||||
].reverse()
|
||||
}
|
||||
},
|
||||
splitArea: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "rgba(238, 197, 102, 0.5)"
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "北京",
|
||||
type: "radar",
|
||||
lineStyle: lineStyle,
|
||||
data: val.dataBJ,
|
||||
symbol: "none",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "#F9713C"
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
opacity: 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "上海",
|
||||
type: "radar",
|
||||
lineStyle: lineStyle,
|
||||
data: val.dataSH,
|
||||
symbol: "none",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "#B3E4A1"
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
opacity: 0.05
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "广州",
|
||||
type: "radar",
|
||||
lineStyle: lineStyle,
|
||||
data: val.dataGZ,
|
||||
symbol: "none",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: "rgb(238, 197, 102)"
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
opacity: 0.05
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
return () => {
|
||||
const height = "200px"
|
||||
const width = "260px"
|
||||
|
||||
return <div>
|
||||
<echart options={options} height={height} width={width} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import { defineComponent, reactive } from 'vue'
|
||||
import Draw from './draw'
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Draw
|
||||
},
|
||||
setup() {
|
||||
const cdata = reactive({
|
||||
indicatorData: [
|
||||
{ name: "数据1", max: 300 },
|
||||
{ name: "数据2", max: 250 },
|
||||
{ name: "数据3", max: 300 },
|
||||
{ name: "数据4", max: 5 },
|
||||
{ name: "数据5", max: 200 },
|
||||
{ name: "数据6", max: 100 }
|
||||
],
|
||||
dataBJ: [
|
||||
[94, 69, 114, 2.08, 73, 39, 22],
|
||||
[99, 73, 110, 2.43, 76, 48, 23],
|
||||
[31, 12, 30, 0.5, 32, 16, 24],
|
||||
[42, 27, 43, 1, 53, 22, 25],
|
||||
[154, 117, 157, 3.05, 92, 58, 26],
|
||||
[234, 185, 230, 4.09, 123, 69, 27],
|
||||
[160, 120, 186, 2.77, 91, 50, 28]
|
||||
],
|
||||
dataGZ: [
|
||||
[84, 94, 140, 2.238, 68, 18, 22],
|
||||
[93, 77, 104, 1.165, 53, 7, 23],
|
||||
[99, 130, 227, 3.97, 55, 15, 24],
|
||||
[146, 84, 139, 1.094, 40, 17, 25],
|
||||
[113, 108, 137, 1.481, 48, 15, 26],
|
||||
[81, 48, 62, 1.619, 26, 3, 27],
|
||||
[56, 48, 68, 1.336, 37, 9, 28]
|
||||
],
|
||||
dataSH: [
|
||||
[91, 45, 125, 0.82, 34, 23, 1],
|
||||
[65, 27, 78, 0.86, 45, 29, 2],
|
||||
[83, 60, 84, 1.09, 73, 27, 3],
|
||||
[109, 81, 121, 1.28, 68, 51, 4],
|
||||
[106, 77, 114, 1.07, 55, 51, 5],
|
||||
[109, 81, 121, 1.28, 68, 51, 6],
|
||||
[106, 77, 114, 1.07, 55, 51, 7]
|
||||
]
|
||||
})
|
||||
return () => {
|
||||
return <div>
|
||||
<draw cdata={cdata} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<div class="centerRight1">
|
||||
<div class="bg-color-black">
|
||||
<div class="d-flex pt-2 pl-2">
|
||||
<span>
|
||||
<i class="iconfont icon-align-left" />
|
||||
</span>
|
||||
<span class="fs-xl text mx-2">产品销售渠道分析</span>
|
||||
</div>
|
||||
<div class="d-flex ai-center flex-column body-box">
|
||||
<dv-capsule-chart
|
||||
class="dv-cap-chart"
|
||||
:config="config"
|
||||
/>
|
||||
<Chart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from "vue";
|
||||
import Chart from "./chart/index.tsx";
|
||||
|
||||
const config = reactive({
|
||||
data: [
|
||||
{ name: "南阳", value: 167 },
|
||||
{ name: "周口", value: 67 },
|
||||
{ name: "漯河", value: 123 },
|
||||
{ name: "郑州", value: 55 },
|
||||
{ name: "西峡", value: 98 },
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$box-height: 400px;
|
||||
$box-width: 340px;
|
||||
|
||||
.centerRight1 {
|
||||
padding: 5px;
|
||||
height: $box-height;
|
||||
width: $box-width;
|
||||
border-radius: 5px;
|
||||
|
||||
.bg-color-black {
|
||||
padding: 5px;
|
||||
height: $box-height;
|
||||
width: $box-width;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #c3cbde;
|
||||
}
|
||||
|
||||
.body-box {
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
|
||||
.dv-cap-chart {
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<div class="centerRight2">
|
||||
<div class="bg-color-black">
|
||||
<div class="d-flex pt-2 pl-2">
|
||||
<span>
|
||||
<i class="iconfont icon-vector" />
|
||||
</span>
|
||||
<div class="d-flex">
|
||||
<span class="fs-xl text mx-2">任务完成排行榜</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex mt-1 jc-center body-box">
|
||||
<dv-scroll-board
|
||||
class="dv-scr-board"
|
||||
:config="config"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from "vue";
|
||||
|
||||
const config = reactive({
|
||||
header: ["组件", "分支", "覆盖率"],
|
||||
data: [
|
||||
["组件1", "dev-1", "<span class='colorGrass'>↑75%</span>"],
|
||||
["组件2", "dev-2", "<span class='colorRed'>↓33%</span>"],
|
||||
["组件3", "dev-3", "<span class='colorGrass'>↑100%</span>"],
|
||||
["组件4", "rea-1", "<span class='colorGrass'>↑94%</span>"],
|
||||
["组件5", "rea-2", "<span class='colorGrass'>↑95%</span>"],
|
||||
["组件6", "fix-2", "<span class='colorGrass'>↑63%</span>"],
|
||||
["组件7", "fix-4", "<span class='colorGrass'>↑84%</span>"],
|
||||
["组件8", "fix-7", "<span class='colorRed'>↓46%</span>"],
|
||||
["组件9", "dev-2", "<span class='colorRed'>↓13%</span>"],
|
||||
["组件10", "dev-9", "<span class='colorGrass'>↑76%</span>"],
|
||||
],
|
||||
rowNum: 7, // 表格行数
|
||||
headerHeight: 35,
|
||||
headerBGC: "#0f1325", // 表头
|
||||
oddRowBGC: "#0f1325", // 奇数行
|
||||
evenRowBGC: "#171c33", // 偶数行
|
||||
index: true,
|
||||
columnWidth: [50],
|
||||
align: ["center"],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$box-height: 410px;
|
||||
$box-width: 300px;
|
||||
.centerRight2 {
|
||||
padding: 16px;
|
||||
padding-top: 20px;
|
||||
height: $box-height;
|
||||
width: $box-width;
|
||||
border-radius: 5px;
|
||||
.bg-color-black {
|
||||
height: $box-height - 30px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.text {
|
||||
color: #c3cbde;
|
||||
}
|
||||
.body-box {
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
.dv-scr-board {
|
||||
width: 270px;
|
||||
height: 340px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,39 @@
|
|||
type ModuleInfo = {
|
||||
name: string;
|
||||
icon: string;
|
||||
}[];
|
||||
// 星期
|
||||
export const WEEK = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
|
||||
|
||||
// 主题名称与副标题名称
|
||||
export const title = "大数据可视化平台";
|
||||
export const subtitle = ["数据分析1", "数据分析2", "vue-big-screen"];
|
||||
|
||||
export const moduleInfo: ModuleInfo = [
|
||||
// 中间的几个模块
|
||||
{
|
||||
name: "任务通过率",
|
||||
icon: "icon-chart-bar",
|
||||
},
|
||||
{
|
||||
name: "地图数据",
|
||||
icon: "icon-tongji4",
|
||||
},
|
||||
{
|
||||
name: "产品销售渠道分析",
|
||||
icon: "icon-align-left",
|
||||
},
|
||||
{
|
||||
name: "任务完成排行榜",
|
||||
icon: "icon-zhibiao2",
|
||||
},
|
||||
// 底部两个模块
|
||||
{
|
||||
name: "数据统计图",
|
||||
icon: "icon-vector",
|
||||
},
|
||||
{
|
||||
name: "工单修复以及满意度统计图",
|
||||
icon: "icon-fenxi7",
|
||||
},
|
||||
];
|
|
@ -1,9 +1,323 @@
|
|||
<template>
|
||||
<div>总览大屏</div>
|
||||
<div class="app">
|
||||
<div
|
||||
id="index"
|
||||
ref="appRef"
|
||||
>
|
||||
<div class="bg">
|
||||
<dv-loading v-if="loading">Loading ...</dv-loading>
|
||||
<div
|
||||
v-else
|
||||
class="host-body"
|
||||
>
|
||||
<div class="d-flex jc-center">
|
||||
<dv-decoration-10 class="dv-dec-10" />
|
||||
<div class="d-flex jc-center">
|
||||
<dv-decoration-8
|
||||
class="dv-dec-8"
|
||||
:color="decorationColors"
|
||||
/>
|
||||
<div class="title">
|
||||
<span class="title-text">{{ title }}</span>
|
||||
<dv-decoration-6
|
||||
class="dv-dec-6"
|
||||
:reverse="true"
|
||||
:color="['#50e3c2', '#67a1e5']"
|
||||
/>
|
||||
</div>
|
||||
<dv-decoration-8
|
||||
class="dv-dec-8"
|
||||
:reverse="true"
|
||||
:color="decorationColors"
|
||||
/>
|
||||
</div>
|
||||
<dv-decoration-10 class="dv-dec-10-s" />
|
||||
</div>
|
||||
|
||||
<!-- 第二行 -->
|
||||
<div class="d-flex jc-between px-2">
|
||||
<div class="d-flex aside-width">
|
||||
<div class="react-left ml-4 react-l-s">
|
||||
<span class="react-before"></span>
|
||||
<span class="text">{{ subtitle[0] }}</span>
|
||||
</div>
|
||||
<div class="react-left ml-3">
|
||||
<span class="text">{{ subtitle[1] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex aside-width">
|
||||
<div class="react-right bg-color-blue mr-3">
|
||||
<span class="text fw-b">{{ subtitle[2] }}</span>
|
||||
</div>
|
||||
<div class="react-right mr-4 react-l-s">
|
||||
<span class="react-after"></span>
|
||||
<span class="text">
|
||||
{{ timeInfo.dateYear }} {{ timeInfo.dateWeek }}
|
||||
{{ timeInfo.dateDay }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-box">
|
||||
<!-- 第三行数据 -->
|
||||
<div class="content-box">
|
||||
<div>
|
||||
<dv-border-box-12>
|
||||
<!-- <CenterLeft1 /> -->
|
||||
</dv-border-box-12>
|
||||
</div>
|
||||
<div>
|
||||
<dv-border-box-12>
|
||||
<!-- <CenterLeft2 /> -->
|
||||
</dv-border-box-12>
|
||||
</div>
|
||||
<!-- 中间 -->
|
||||
<div>
|
||||
<!-- <Center /> -->
|
||||
</div>
|
||||
<!-- 中间 -->
|
||||
<div>
|
||||
<!-- <CenterRight1 /> -->
|
||||
</div>
|
||||
<div>
|
||||
<dv-border-box-13>
|
||||
<CenterRight2 />
|
||||
</dv-border-box-13>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第四行数据 -->
|
||||
<div class="bototm-box">
|
||||
<dv-border-box-13>
|
||||
<BottomLeft />
|
||||
</dv-border-box-13>
|
||||
<dv-border-box-12>
|
||||
<!-- <BottomRight /> -->
|
||||
</dv-border-box-12>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, onUnmounted } from "vue";
|
||||
import { formatTime } from "./utils/index";
|
||||
import { WEEK } from "./constant/index";
|
||||
import useDraw from "./utils/useDraw.ts";
|
||||
import { title, subtitle, moduleInfo } from "./constant/index";
|
||||
|
||||
// 有用的 已修改的组件
|
||||
import BottomLeft from "./components/bottomLeft/index.vue";
|
||||
import CenterRight2 from "./components/centerRight2/index.vue";
|
||||
|
||||
// 未修改的组件
|
||||
import CenterLeft1 from "./components/centerLeft1/index.vue";
|
||||
import CenterLeft2 from "./components/centerLeft2/index.vue";
|
||||
import Center from "./components/center/index.vue";
|
||||
import CenterRight1 from "./components/centerRight1/index.vue";
|
||||
import BottomRight from "./components/bottomRight/index.vue";
|
||||
|
||||
// * 颜色
|
||||
const decorationColors = ["#568aea", "#000000"];
|
||||
|
||||
// * 加载标识
|
||||
const loading = ref<boolean>(true);
|
||||
|
||||
// * 时间内容
|
||||
const timeInfo = reactive({
|
||||
setInterval: 0,
|
||||
dateDay: "",
|
||||
dateYear: "",
|
||||
dateWeek: "",
|
||||
});
|
||||
|
||||
// * 适配处理
|
||||
const { appRef, calcRate, windowDraw, unWindowDraw } = useDraw();
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
cancelLoading();
|
||||
handleTime();
|
||||
windowDraw();
|
||||
calcRate();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
unWindowDraw();
|
||||
clearInterval(timeInfo.setInterval);
|
||||
});
|
||||
|
||||
// 处理 loading 展示
|
||||
const cancelLoading = () => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 500);
|
||||
};
|
||||
|
||||
// 处理时间监听
|
||||
const handleTime = () => {
|
||||
timeInfo.setInterval = setInterval(() => {
|
||||
const date = new Date();
|
||||
timeInfo.dateDay = formatTime(date, "HH: mm: ss");
|
||||
timeInfo.dateYear = formatTime(date, "yyyy-MM-dd");
|
||||
timeInfo.dateWeek = WEEK[date.getDay()];
|
||||
}, 1000);
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.app {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: #020308;
|
||||
overflow: hidden;
|
||||
#index {
|
||||
color: #d3d6dd;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transform-origin: left top;
|
||||
/* transform-origin: center center; */
|
||||
.bg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 16px 16px 0 16px;
|
||||
background-image: url("./assets/pageBg.png");
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.host-body {
|
||||
.dv-dec-10,
|
||||
.dv-dec-10-s {
|
||||
width: 33.3%;
|
||||
height: 5px;
|
||||
}
|
||||
.dv-dec-10-s {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
.dv-dec-8 {
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
}
|
||||
.title {
|
||||
position: relative;
|
||||
width: 500px;
|
||||
text-align: center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
.title-text {
|
||||
font-size: 24px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%);
|
||||
}
|
||||
|
||||
.dv-dec-6 {
|
||||
position: absolute;
|
||||
bottom: -30px;
|
||||
left: 50%;
|
||||
width: 250px;
|
||||
height: 8px;
|
||||
transform: translate(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
// 第二行
|
||||
.aside-width {
|
||||
width: 40%;
|
||||
}
|
||||
.react-r-s,
|
||||
.react-l-s {
|
||||
background-color: #0f1325;
|
||||
}
|
||||
|
||||
// 平行四边形
|
||||
.react-right {
|
||||
&.react-l-s {
|
||||
text-align: right;
|
||||
width: 500px;
|
||||
}
|
||||
font-size: 18px;
|
||||
width: 300px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
transform: skewX(-45deg);
|
||||
|
||||
.react-after {
|
||||
position: absolute;
|
||||
right: -25px;
|
||||
top: 0;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
background-color: #0f1325;
|
||||
transform: skewX(45deg);
|
||||
}
|
||||
|
||||
.text {
|
||||
display: inline-block;
|
||||
transform: skewX(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.react-left {
|
||||
&.react-l-s {
|
||||
width: 500px;
|
||||
text-align: left;
|
||||
}
|
||||
font-size: 18px;
|
||||
width: 300px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
transform: skewX(45deg);
|
||||
background-color: #0f1325;
|
||||
|
||||
.react-before {
|
||||
position: absolute;
|
||||
left: -25px;
|
||||
top: 0;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
background-color: #0f1325;
|
||||
transform: skewX(-45deg);
|
||||
}
|
||||
|
||||
.text {
|
||||
display: inline-block;
|
||||
transform: skewX(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.body-box {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
//下方区域的布局
|
||||
.content-box {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 3fr 5fr 3fr 2fr;
|
||||
}
|
||||
|
||||
// 底部数据
|
||||
.bototm-box {
|
||||
margin-top: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* @param {date} time 需要转换的时间
|
||||
* @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
|
||||
* @returns {String}
|
||||
*/
|
||||
export const formatTime = (
|
||||
time: string | number | Date,
|
||||
fmt: string
|
||||
): string => {
|
||||
if (!time) return ''
|
||||
const date = new Date(time)
|
||||
const o = {
|
||||
'M+': date.getMonth() + 1,
|
||||
'd+': date.getDate(),
|
||||
'H+': date.getHours(),
|
||||
'm+': date.getMinutes(),
|
||||
's+': date.getSeconds(),
|
||||
'q+': Math.floor((date.getMonth() + 3) / 3),
|
||||
S: date.getMilliseconds(),
|
||||
}
|
||||
if (/(y+)/.test(fmt))
|
||||
fmt = fmt.replace(
|
||||
RegExp.$1,
|
||||
(date.getFullYear() + '').substr(4 - RegExp.$1.length)
|
||||
)
|
||||
for (const k in o) {
|
||||
if (new RegExp('(' + k + ')').test(fmt)) {
|
||||
fmt = fmt.replace(
|
||||
RegExp.$1,
|
||||
// @ts-ignore: Unreachable code error
|
||||
RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
|
||||
)
|
||||
}
|
||||
}
|
||||
return fmt
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
import { ref } from "vue";
|
||||
|
||||
export default function useDraw() {
|
||||
// * 指向最外层容器
|
||||
const appRef = ref();
|
||||
// * 定时函数
|
||||
const timer = ref(0);
|
||||
// * 默认缩放值
|
||||
const scale = {
|
||||
width: "1",
|
||||
height: "1",
|
||||
};
|
||||
// * 设计稿尺寸(px)
|
||||
const baseWidth = 1920;
|
||||
const baseHeight = 1080;
|
||||
|
||||
// * 需保持的比例(默认1.77778)
|
||||
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5));
|
||||
const calcRate = () => {
|
||||
// 当前宽高比
|
||||
const currentRate = parseFloat(
|
||||
(window.innerWidth / window.innerHeight).toFixed(5)
|
||||
);
|
||||
if (appRef.value) {
|
||||
if (currentRate > baseProportion) {
|
||||
// 表示更宽
|
||||
scale.width = (
|
||||
(window.innerHeight * baseProportion) /
|
||||
baseWidth
|
||||
).toFixed(5);
|
||||
scale.height = (window.innerHeight / baseHeight).toFixed(5);
|
||||
appRef.value.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`;
|
||||
} else {
|
||||
// 表示更高
|
||||
scale.height = (
|
||||
window.innerWidth /
|
||||
baseProportion /
|
||||
baseHeight
|
||||
).toFixed(5);
|
||||
scale.width = (window.innerWidth / baseWidth).toFixed(5);
|
||||
appRef.value.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const resize = () => {
|
||||
clearTimeout(timer.value);
|
||||
timer.value = setTimeout(() => {
|
||||
calcRate();
|
||||
}, 200);
|
||||
};
|
||||
|
||||
// 改变窗口大小重新绘制
|
||||
const windowDraw = () => {
|
||||
window.addEventListener("resize", resize);
|
||||
};
|
||||
|
||||
// 改变窗口大小重新绘制
|
||||
const unWindowDraw = () => {
|
||||
window.removeEventListener("resize", resize);
|
||||
};
|
||||
|
||||
return {
|
||||
appRef,
|
||||
calcRate,
|
||||
windowDraw,
|
||||
unWindowDraw,
|
||||
};
|
||||
}
|
|
@ -1,15 +1,28 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["src/**/*", "src/**/*.vue", "src/**/*.d.ts"],
|
||||
"exclude": ["src/**/__tests__/*", "node_modules", "dist", "management"],
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"src/**/*.vue",
|
||||
"src/**/*.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"src/**/__tests__/*",
|
||||
"node_modules",
|
||||
"dist",
|
||||
"management"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
},
|
||||
"jsx": "preserve",
|
||||
"jsxImportSource": "vue",
|
||||
"verbatimModuleSyntax": true,
|
||||
"types": ["naive-ui/volar.d.ts"]
|
||||
"types": [
|
||||
"naive-ui/volar.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue