Compare commits

..

No commits in common. "efd1f341818da411a791bdffc33b8cca276e1a09" and "9c0572453505f22d1986d4ad6c48a3af06ff532b" have entirely different histories.

60 changed files with 3028 additions and 13487 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
node_modules

View File

@ -1,3 +0,0 @@
{
"git.ignoreLimitWarning": true
}

Binary file not shown.

50
package-lock.json generated
View File

@ -11,8 +11,7 @@
"@jiaminghi/data-view": "^2.7.3",
"@types/echarts": "^4.4.3",
"core-js": "^3.6.4",
"echarts": "^4.9.0",
"v-charts": "^1.19.0",
"echarts": "^4.6.0",
"vue": "^2.6.11",
"vue-awesome": "^4.0.2",
"vue-router": "^3.1.5",
@ -6715,31 +6714,12 @@
},
"node_modules/echarts": {
"version": "4.9.0",
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-4.9.0.tgz",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-4.9.0.tgz",
"integrity": "sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==",
"dependencies": {
"zrender": "4.3.2"
}
},
"node_modules/echarts-amap": {
"version": "1.0.0-rc.6",
"resolved": "https://registry.npmmirror.com/echarts-amap/-/echarts-amap-1.0.0-rc.6.tgz",
"integrity": "sha512-cYJCKoQdnkZXrGweYrveU1HruZd1c0KmsF1U8o3FtsvgR2jVL5ZUpGFjMmFtpolHOUFqxizk+s+QBLkYuOWL6Q=="
},
"node_modules/echarts-liquidfill": {
"version": "2.0.6",
"resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-2.0.6.tgz",
"integrity": "sha512-p+AH0O9/BtwXMQQyhjJbMZo+GwRAgWG/DCyK5r27PQzpS0UWrgXu57MyEFc0A8Ub3sRuqEu08BuxwHICBkSWSQ==",
"peerDependencies": {
"echarts": "^4.8.0",
"zrender": "^4.3.1"
}
},
"node_modules/echarts-wordcloud": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/echarts-wordcloud/-/echarts-wordcloud-1.1.3.tgz",
"integrity": "sha512-Et8D5xEAoYkidmHun+hEH+2lF9dhCt6D0JJ390vlr2r/1zwhhZAbcL01CEvG93QcMcJpSvSPK8vRiGkTbMHRxg=="
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -10563,11 +10543,6 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/numerify": {
"version": "1.2.9",
"resolved": "https://registry.npmmirror.com/numerify/-/numerify-1.2.9.tgz",
"integrity": "sha512-X4QzQiytV5ZN3TVLhzbtFzjTarUNnaa1pgNDFqt7u7Nqhxe7FvY2eYrGt4WYHlYXDqgtfC/n/a5nJ2y0LijV8w=="
},
"node_modules/oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@ -14581,11 +14556,6 @@
"integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
"dev": true
},
"node_modules/utils-lite": {
"version": "0.1.10",
"resolved": "https://registry.npmmirror.com/utils-lite/-/utils-lite-0.1.10.tgz",
"integrity": "sha512-jlHvdtI8MyWURF/3u+ufIjf1Cs5WjN6WZl9qO8dEkZsVjaI7X5YMUhaCFzkvB69ljt6fo4Dd7V/Oj2NJOFDFOQ=="
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@ -14605,22 +14575,6 @@
"uuid": "bin/uuid"
}
},
"node_modules/v-charts": {
"version": "1.19.0",
"resolved": "https://registry.npmmirror.com/v-charts/-/v-charts-1.19.0.tgz",
"integrity": "sha512-vm2HBUmxAsXK0ivwce9LytcpqrItDA5JSPLYVxZXtiuoyhcn80XX1/3dPJd/1GqG1OYv3jfBo1s9ra4q8GowqA==",
"dependencies": {
"echarts-amap": "1.0.0-rc.6",
"echarts-liquidfill": "^2.0.2",
"echarts-wordcloud": "^1.1.3",
"numerify": "1.2.9",
"utils-lite": "0.1.10"
},
"peerDependencies": {
"echarts": ">3.0.0",
"vue": ">2.0.0"
}
},
"node_modules/v8-compile-cache": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz",

View File

@ -11,10 +11,7 @@
"@jiaminghi/data-view": "^2.7.3",
"@types/echarts": "^4.4.3",
"core-js": "^3.6.4",
"echarts": "^4.9.0",
"element-ui": "^2.15.0",
"lodash": "^4.17.21",
"v-charts": "^1.19.0",
"echarts": "^4.6.0",
"vue": "^2.6.11",
"vue-awesome": "^4.0.2",
"vue-router": "^3.1.5",
@ -49,4 +46,4 @@
"> 1%",
"last 2 versions"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 657 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

View File

@ -96,76 +96,3 @@ $spacing-sizes: (
4: 2,
5: 2.5,
);
// 颜色系统
$primary-color: #409EFF;
$success-color: #67C23A;
$warning-color: #E6A23C;
$danger-color: #F56C6C;
$info-color: #909399;
$text-color: #303133;
$text-color-secondary: #606266;
$text-color-placeholder: #C0C4CC;
$border-color: #DCDFE6;
$border-color-light: #E4E7ED;
$border-color-lighter: #EBEEF5;
$body-bg: #ffffff;
$component-bg: #f5f7fa;
// 字体
$font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
$font-size-base: 14px;
$font-size-lg: 16px;
$font-size-sm: 13px;
$line-height-base: 1.5;
// 间距
$spacing-base: 16px;
$spacing-lg: 24px;
$spacing-sm: 8px;
// 边框
$border-radius: 4px;
$border-radius-lg: 6px;
$border-radius-sm: 2px;
// 断点
$breakpoint-xs: 480px;
$breakpoint-sm: 576px;
$breakpoint-md: 768px;
$breakpoint-lg: 992px;
$breakpoint-xl: 1200px;
// 容器
$container-max-width: 1200px;
// z-index管理
$zindex-dropdown: 1000;
$zindex-sticky: 1020;
$zindex-fixed: 1030;
$zindex-modal-backdrop: 1040;
$zindex-modal: 1050;
$zindex-popover: 1060;
$zindex-tooltip: 1070;
// 阴影
$box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
$box-shadow-light: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
$box-shadow-dark: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12);
// 过渡
$transition-base: all .3s cubic-bezier(.645,.045,.355,1);
$transition-fade: opacity .3s ease;
$transition-transform: transform .3s ease;
// 表格相关
$table-cell-padding: 12px;
$table-border-color: $border-color-lighter;
$table-hover-bg: $component-bg;
$table-header-bg: $component-bg;
// 响应式表格
$table-breakpoint-scroll: $breakpoint-md;

View File

@ -13,14 +13,12 @@
width: 100%;
height: 100%;
padding: 16px 16px 0 16px;
background-image: url("../assets/bg.jpg");
background-image: url("../assets/pageBg.png");
background-size: cover;
background-position: center center;
}
.host-body {
width: 100%;
height: 100%;
.dv-dec-10,
.dv-dec-10-s {
width: 33.3%;
@ -39,92 +37,108 @@
text-align: center;
background-size: cover;
background-repeat: no-repeat;
img{
width: 25%;
position: absolute;
bottom: 10px;
left: 22%;
transform: translate(-22%);
}
.title-text {
font-size: 40px;
font-size: 24px;
position: absolute;
bottom: 0;
left: 65%;
transform: translate(-65%);
font-weight: bold;
left: 50%;
transform: translate(-50%);
}
.dv-dec-6 {
position: absolute;
bottom: -10px;
bottom: -30px;
left: 50%;
width: 250px;
height: 8px;
transform: translate(-50%);
}
}
}
}
}
// 添加响应式样式
.data-table-wrapper {
width: 100%;
overflow-x: auto;
.data-table {
width: 100%;
border-collapse: collapse;
th, td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
@media screen and (max-width: 768px) {
padding: 8px;
font-size: 14px;
// 第二行
.aside-width {
width: 40%;
}
.react-r-s,
.react-l-s {
background-color: #0f1325;
}
// 平行四边形
.react-right {
&.react-l-s {
text-align: right;
width: 500px;
}
@media screen and (max-width: 480px) {
padding: 6px;
font-size: 12px;
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);
}
}
input {
width: 100%;
padding: 4px;
border: 1px solid #ddd;
border-radius: 4px;
&:focus {
outline: none;
border-color: #409EFF;
.react-left {
&.react-l-s {
width: 500px;
text-align: left;
}
@media screen and (max-width: 768px) {
padding: 2px;
font-size: 18px;
width: 300px;
height: 50px;
line-height: 50px;
text-align: center;
transform: skewX(45deg);
background-color: #0f1325;
.react-left {
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;
}
// 底部数据
.bottom-box {
margin-top: 10px;
display: grid;
grid-template-columns: repeat(2, 50%);
}
}
}
}
// 响应式布局基础样式
@media screen and (max-width: 1200px) {
.container {
width: 95%;
margin: 0 auto;
}
}
@media screen and (max-width: 768px) {
.row {
flex-direction: column;
}
.col {
width: 100%;
margin-bottom: 15px;
}
}

View File

@ -9,16 +9,15 @@
box-sizing: border-box;
}
html, body {
height: 100%;
font-family: $font-family-base;
font-size: $font-size-base;
line-height: $line-height-base;
color: $text-color;
background-color: $body-bg;
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;
@ -185,73 +184,3 @@ a {
#{$type}: 0;
}
}
// 布局系统
.container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $spacing-base;
@media screen and (max-width: $breakpoint-lg) {
max-width: 100%;
}
}
.row {
display: flex;
flex-wrap: wrap;
margin: 0 (-$spacing-base);
@media screen and (max-width: $breakpoint-md) {
flex-direction: column;
}
}
// 栅格系统
@for $i from 1 through 12 {
.col-#{$i} {
flex: 0 0 percentage($i / 12);
max-width: percentage($i / 12);
padding: 0 $spacing-base;
@media screen and (max-width: $breakpoint-md) {
flex: 0 0 100%;
max-width: 100%;
}
}
}
// 通用工具类
.text-center { text-align: center; }
.text-left { text-align: left; }
.text-right { text-align: right; }
.mt-1 { margin-top: $spacing-base; }
.mb-1 { margin-bottom: $spacing-base; }
.ml-1 { margin-left: $spacing-base; }
.mr-1 { margin-right: $spacing-base; }
// 响应式工具类
@media screen and (max-width: $breakpoint-md) {
.hidden-mobile {
display: none !important;
}
}
@media screen and (min-width: $breakpoint-md) {
.hidden-desktop {
display: none !important;
}
}
// 动画
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}

View File

@ -0,0 +1,66 @@
<template>
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import tdTheme from './theme.json' //
import '../map/fujian.js'
export default {
name: 'echart',
props: {
className: {
type: String,
default: 'chart'
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '2.5rem'
},
options: {
type: Object,
default: ()=>({})
}
},
data () {
return {
chart: null
}
},
watch: {
options: {
handler (options) {
// trueechart
this.chart.setOption(options, true)
},
deep: true
}
},
mounted () {
this.$echarts.registerTheme('tdTheme', tdTheme); //
this.initChart();
},
beforeDestroy () {
this.chart.dispose()
this.chart = null
},
methods: {
initChart () {
// echart
this.chart = this.$echarts.init(this.$el, 'tdTheme')
this.chart.setOption(this.options, true)
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,490 @@
{
"color": [
"#2d8cf0",
"#19be6b",
"#ff9900",
"#E46CBB",
"#9A66E4",
"#ed3f14"
],
"backgroundColor": "rgba(0,0,0,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#516b91"
},
"subtextStyle": {
"color": "#93b7e3"
}
},
"line": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"radar": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"bar": {
"itemStyle": {
"normal": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"normal": {
"color": "#edafda",
"color0": "transparent",
"borderColor": "#d680bc",
"borderColor0": "#8fd3e8",
"borderWidth": "2"
}
}
},
"graph": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"lineStyle": {
"normal": {
"width": 1,
"color": "#aaa"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true,
"color": [
"#2d8cf0",
"#19be6b",
"#f5ae4a",
"#9189d5",
"#56cae2",
"#cbb0e3"
],
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
}
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#fff"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#fff"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999"
},
"emphasis": {
"borderColor": "#666"
}
}
},
"legend": {
"textStyle": {
"color": "#fff"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#ccc",
"width": 1
},
"crossStyle": {
"color": "#ccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#8fd3e8",
"width": 1
},
"itemStyle": {
"normal": {
"color": "#8fd3e8",
"borderWidth": 1
},
"emphasis": {
"color": "#8fd3e8"
}
},
"controlStyle": {
"normal": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
},
"emphasis": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
}
},
"checkpointStyle": {
"color": "#8fd3e8",
"borderColor": "rgba(138,124,168,0.37)"
},
"label": {
"normal": {
"textStyle": {
"color": "#8fd3e8"
}
},
"emphasis": {
"textStyle": {
"color": "#8fd3e8"
}
}
}
},
"visualMap": {
"color": [
"#516b91",
"#59c4e6",
"#a5e7f0"
]
},
"dataZoom": {
"backgroundColor": "rgba(0,0,0,0)",
"dataBackgroundColor": "rgba(255,255,255,0.3)",
"fillerColor": "rgba(167,183,204,0.4)",
"handleColor": "#a7b7cc",
"handleSize": "100%",
"textStyle": {
"color": "#333"
}
},
"markPoint": {
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
},
"emphasis": {
"textStyle": {
"color": "#eee"
}
}
}
}
}

48
src/common/map/fujian.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,271 +0,0 @@
<template>
<div class="asset-overview">
<div class="content">
<div class="asset-summary">
<div class="total-assets">
<div class="value">{{ formatCurrency(assetData.totalAssets) }}</div>
<div class="label">总资产万元</div>
</div>
<div class="asset-categories">
<div
class="category-item"
v-for="(item, index) in assetData.assetCategories"
:key="index"
>
<span class="label">{{ item.name }}</span>
<span class="value">{{ formatNumber(item.value) }}</span>
</div>
</div>
</div>
<div class="table-container">
<el-table
:data="displayData"
style="width: 100%"
class="animated-table custom-table"
:row-class-name="tableRowClassName"
:header-cell-style="{
background: 'transparent',
color: '#4a90e2',
height: '40px',
fontWeight: 'bold',
fontSize: '14px',
}"
:row-style="{ height: '35px' }"
:cell-style="{ padding: '0' }"
>
<el-table-column
prop="月份"
label="月份"
width="180"
align="center"
/>
<el-table-column
prop="资产总值"
label="资产总值(万元)"
align="center"
>
<template #default="scope">
{{ formatNumber(scope.row.资产总值) }}
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import { assetData } from "../data/dashboardData";
import { formatNumber, formatCurrency } from "../utils/format";
export default {
name: "AssetOverview",
components: {},
data() {
return {
assetData,
};
},
computed: {
displayData() {
return [
...this.assetData.assetTrendData.rows,
...this.assetData.assetTrendData.rows,
];
},
},
methods: {
formatNumber,
formatCurrency,
tableRowClassName({ rowIndex }) {
return `row-${rowIndex}`;
},
},
};
</script>
<style lang="scss" scoped>
.asset-overview {
height: 100%;
color: #fff;
.content {
height: calc(100% - 80px);
margin-top: 15px;
.asset-summary {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.total-assets {
text-align: center;
&:hover {
transform: translateY(-2px);
.label {
color: rgba(255, 255, 255, 0.9);
}
}
.value {
font-size: 24px;
font-weight: bold;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.label {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
margin-top: 5px;
}
}
.asset-categories {
display: flex;
gap: 20px;
.category-item {
text-align: center;
.label {
display: block;
font-size: 12px;
color: rgba(255, 255, 255, 0.7);
}
.value {
display: block;
font-size: 16px;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-top: 5px;
}
}
}
}
.table-container {
height: 160px;
position: relative;
overflow: hidden;
border-radius: 8px;
background: rgba(74, 144, 226, 0.05);
backdrop-filter: blur(5px);
.custom-table {
::v-deep {
.el-table__cell {
border: none !important;
transition: all 0.3s ease;
}
.el-table__header-wrapper {
th {
background: transparent;
border: none;
position: relative;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 10%;
width: 80%;
height: 2px;
background: linear-gradient(
90deg,
transparent 0%,
rgba(74, 144, 226, 0.5) 50%,
transparent 100%
);
}
.cell {
font-weight: bold;
background: linear-gradient(to top, #4a90e2, #ffffff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
}
.el-table__body-wrapper {
background: transparent;
overflow: hidden;
td {
background: transparent;
border: none;
position: relative;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 5%;
width: 90%;
height: 1px;
background: linear-gradient(
90deg,
transparent 0%,
rgba(74, 144, 226, 0.1) 50%,
transparent 100%
);
}
}
.el-table__row {
transition: all 0.3s ease;
&:hover {
background: rgba(74, 144, 226, 0.1);
transform: scale(1.01);
td {
color: #4a90e2;
}
}
}
.el-table__body {
animation: scroll 20s linear infinite;
&:hover {
animation-play-state: paused;
}
}
}
@keyframes scroll {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-50%);
}
}
.el-table__inner-wrapper::after,
.el-table--border::after {
display: none;
}
}
}
}
}
.el-table {
background-color: transparent;
}
::v-deep .el-table th,
::v-deep .el-table tr,
::v-deep .el-table td {
background-color: transparent;
border: none;
color: rgba(255, 255, 255, 0.8);
}
}
</style>

View File

@ -1,302 +0,0 @@
<template>
<div class="card-overview">
<div class="content">
<div class="statistics">
<div class="stat-item">
<div class="icon-wrapper">
<i class="el-icon-bank-card"></i>
</div>
<div class="stat-content">
<div class="value">{{ formatNumber(cardData.totalCards) }}</div>
<div class="label">发卡总量</div>
</div>
</div>
<div class="stat-item">
<div class="icon-wrapper">
<i class="el-icon-data-line"></i>
</div>
<div class="stat-content">
<div class="value">{{ formatNumber(cardData.dailyUsage) }}</div>
<div class="label">日均使用量</div>
</div>
</div>
</div>
<div class="usage-scenes">
<div class="scene-header">
<i class="el-icon-place"></i>
<h4>使用场景分布</h4>
</div>
<div class="scene-list">
<div
class="scene-item"
v-for="(item, index) in cardData.usageScenes"
:key="index"
>
<div class="scene-info">
<div class="icon-box" :style="getSceneStyle(index)">
<i :class="getSceneIcon(item.name)"></i>
</div>
<div class="scene-details">
<span class="name">{{ item.name }}</span>
<el-progress
:percentage="getPercentage(item.count)"
:color="getSceneColor(index)"
:show-text="false"
:stroke-width="4"
/>
</div>
</div>
<span class="value">{{ formatNumber(item.count) }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { cardData } from "../data/dashboardData";
import { formatNumber } from "../utils/format";
export default {
name: "CardOverview",
components: {},
data() {
return {
cardData,
};
},
methods: {
formatNumber,
getSceneIcon(name) {
const iconMap = {
食堂: "el-icon-food",
图书馆: "el-icon-reading",
宿舍: "el-icon-house",
教学楼: "el-icon-school",
超市: "el-icon-shopping-cart-full",
其他: "el-icon-more",
};
return iconMap[name] || "el-icon-place";
},
getSceneColor(index) {
const colors = [
"#4a90e2", //
"#00CED1", //
"#9561e2", //
"#64B5F6", //
"#ff9f43", //
"#4CAF50", // 绿
];
return colors[index % colors.length];
},
getSceneStyle(index) {
const color = this.getSceneColor(index);
return {
background: `linear-gradient(135deg, ${color}22, ${color}44)`,
borderColor: `${color}66`,
};
},
getPercentage(count) {
const max = Math.max(
...this.cardData.usageScenes.map((scene) => scene.count)
);
return (count / max) * 100;
},
},
};
</script>
<style lang="scss" scoped>
.card-overview {
height: 100%;
color: #fff;
.content {
height: 100%;
display: flex;
flex-direction: column;
gap: 20px;
padding: 5px;
.statistics {
display: flex;
justify-content: space-around;
gap: 20px;
.stat-item {
flex: 1;
display: flex;
align-items: center;
gap: 15px;
// padding: 15px;
// background: rgba(74, 144, 226, 0.05);
// border-radius: 10px;
// border: 1px solid rgba(74, 144, 226, 0.1);
backdrop-filter: blur(5px);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
border-color: rgba(74, 144, 226, 0.2);
box-shadow: 0 4px 12px rgba(74, 144, 226, 0.1);
.icon-wrapper {
i {
transform: scale(1.1);
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
}
.icon-wrapper {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
// border-radius: 12px;
// background: rgba(74, 144, 226, 0.1);
i {
font-size: 24px;
color: #4a90e2;
transition: all 0.3s ease;
}
}
.stat-content {
flex: 1;
.value {
font-size: 22px;
font-weight: bold;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
transition: all 0.3s ease;
}
.label {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
margin-top: 4px;
}
}
}
}
.usage-scenes {
flex: 1;
background: rgba(74, 144, 226, 0.05);
border-radius: 10px;
border: 1px solid rgba(74, 144, 226, 0.1);
backdrop-filter: blur(5px);
padding: 15px;
.scene-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
i {
font-size: 18px;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
h4 {
font-size: 14px;
font-weight: 500;
color: rgba(255, 255, 255, 0.9);
margin: 0;
}
}
.scene-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
.scene-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
// background: rgba(255, 255, 255, 0.03);
// border-radius: 8px;
transition: all 0.3s ease;
&:hover {
background: rgba(255, 255, 255, 0.05);
transform: translateX(2px);
.icon-box {
transform: scale(1.05);
}
.value {
}
}
.scene-info {
display: flex;
align-items: center;
gap: 12px;
flex: 1;
.icon-box {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
border: 1px solid;
transition: all 0.3s ease;
i {
font-size: 16px;
color: rgba(255, 255, 255, 0.9);
}
}
.scene-details {
flex: 1;
min-width: 0;
.name {
display: block;
font-size: 13px;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 6px;
}
.el-progress {
margin-top: 4px;
}
}
}
.value {
font-size: 13px;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
transition: all 0.3s ease;
margin-left: 8px;
white-space: nowrap;
}
}
}
}
}
}
</style>

View File

@ -1,86 +0,0 @@
<template>
<div class="common-header">
<div class="title-wrapper">
<div class="title-decoration"></div>
<h3 class="gradient-text" @click="$emit('click-more')">{{ title }}</h3>
</div>
<!-- <el-button type="text" @click="$emit('click-more')">更多</el-button> -->
</div>
</template>
<script>
export default {
name: "CommonHeader",
props: {
title: {
type: String,
required: true,
},
},
};
</script>
<style lang="scss" scoped>
.common-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
// padding: 10px;
.title-wrapper {
display: flex;
align-items: center;
gap: 8px;
position: relative;
.title-decoration {
width: 3px;
height: 16px;
background: linear-gradient(to bottom, #4a90e2, #36d1dc);
border-radius: 2px;
position: relative;
&::after {
content: "";
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(to bottom, #4a90e2, #36d1dc);
filter: blur(4px);
opacity: 0.5;
border-radius: 2px;
z-index: -1;
}
}
h3 {
margin: 0;
font-size: 22px;
background: linear-gradient(to bottom, #ffffff, #4a90e2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(74, 144, 226, 0.2);
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
transform: translateX(2px);
background: linear-gradient(to bottom, #ffffff, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 15px rgba(54, 209, 220, 0.3);
}
}
}
.el-button {
color: #4a90e2;
font-size: 12px;
font-weight: bold;
}
}
</style>

View File

@ -1,86 +0,0 @@
<template>
<div class="education-overview">
<div class="charts">
<ve-line
:data="educationData.evaluationData"
:settings="educationData.chartSettings"
:extend="chartStyles.education.extend"
height="200px"
/>
<div class="info-cards">
<div class="info-card">
<div class="label">课程通过率</div>
<div class="value pass-rate">
{{ educationData.statistics.passRate }}%
</div>
</div>
<div class="info-card">
<div class="label">毕业率</div>
<div class="value graduation-rate">
{{ educationData.statistics.graduationRate }}%
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { educationData, chartStyles } from "../data/dashboardData";
export default {
name: "EducationOverview",
components: {},
data() {
return {
educationData,
chartStyles,
};
},
methods: {},
};
</script>
<style lang="scss" scoped>
.education-overview {
height: 100%;
color: #fff;
padding: 10px;
.charts {
height: calc(100% - 80px);
margin-top: 10px;
.info-cards {
display: flex;
justify-content: space-around;
margin-top: -40px;
.info-card {
text-align: center;
padding: 15px 25px;
&:hover {
transform: translateY(-2px);
.label {
color: rgba(255, 255, 255, 0.9);
}
}
.label {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
margin-bottom: 8px;
}
.value {
font-size: 24px;
font-weight: bold;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
transition: all 0.3s ease;
}
}
}
}
}
</style>

View File

@ -1,265 +0,0 @@
<template>
<div class="literature-overview">
<div class="content">
<div class="total-info">
<div class="total-number">
{{ formatNumber(literatureData.totalLiterature) }}
</div>
<div class="label">馆藏总量</div>
</div>
<el-carousel
ref="carousel"
:interval="6000"
indicator-position="none"
height="180px"
@mouseenter="pauseCarousel"
@mouseleave="startCarousel"
>
<el-carousel-item>
<ve-histogram
ref="histogram"
:data="literatureData.chartData"
:settings="literatureData.chartSettings"
:extend="extendChartOptions"
height="200px"
:after-config="handleAfterConfig"
/>
</el-carousel-item>
<el-carousel-item>
<div class="subject-distribution">
<h4>学科分布 TOP5</h4>
<div class="distribution-list">
<div
class="distribution-item"
v-for="(item, index) in literatureData.subjectDistribution"
:key="index"
>
<span class="name">{{ item.name }}</span>
<el-progress
:percentage="item.percentage"
:color="getProgressColor(index)"
:show-text="false"
/>
<span class="value">{{ formatNumber(item.count) }}</span>
</div>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
import { literatureData, chartStyles } from "../data/dashboardData";
import { formatNumber } from "../utils/format";
export default {
name: "LiteratureOverview",
components: {},
data() {
return {
literatureData,
chartStyles,
carousel: null,
};
},
computed: {
extendChartOptions() {
return {
...this.chartStyles.research.extend,
grid: {
top: "10%",
left: "3%",
right: "4%",
bottom: "8%",
containLabel: true,
},
animation: {
duration: 2000,
easing: "cubicInOut",
},
};
},
},
methods: {
formatNumber,
pauseCarousel() {
if (this.carousel) {
this.carousel.pause();
}
},
startCarousel() {
if (this.carousel) {
this.carousel.start();
}
},
handleAfterConfig(options) {
//
this.$nextTick(() => {
if (this.$refs.histogram) {
this.$refs.histogram.echarts.resize();
}
});
return options;
},
getProgressColor(index) {
// 5
const colors = [
'#4a90e2', //
'#00CED1', //
'#9561e2', //
'#64B5F6', //
'#ff9f43' //
];
return colors[index % colors.length];
},
},
mounted() {
this.carousel = this.$refs.carousel;
//
this.$nextTick(() => {
if (this.$refs.histogram) {
this.$refs.histogram.echarts.resize();
}
});
},
activated() {
// keep-alive
if (this.$refs.histogram) {
this.$refs.histogram.echarts.resize();
}
},
};
</script>
<style lang="scss" scoped>
.literature-overview {
height: 100%;
color: #fff;
.content {
height: calc(100% - 80px);
margin-top: 20px;
.total-info {
text-align: center;
margin-bottom: 15px;
margin-top: -15px;
.total-number {
font-size: 24px;
font-weight: bold;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.label {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
margin-top: 5px;
}
}
.subject-distribution {
padding: 0 10px;
h4 {
font-size: 14px;
margin-bottom: 15px;
color: rgba(255, 255, 255, 0.9);
font-weight: 500;
}
.distribution-list {
.distribution-item {
display: flex;
align-items: center;
margin-bottom: 12px;
transition: all 0.3s ease;
&:hover {
transform: translateX(5px);
.name {
color: rgba(255, 255, 255, 0.9);
}
.value {
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.name {
width: 70px;
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
transition: color 0.3s ease;
}
.el-progress {
flex: 1;
margin: 0 12px;
::v-deep .el-progress-bar__outer {
background-color: rgba(255, 255, 255, 0.1);
border-radius: 4px;
height: 12px !important;
background-image: repeating-linear-gradient(
to right,
transparent,
transparent 4px,
rgba(255, 255, 255, 0.1) 4px,
rgba(255, 255, 255, 0.1) 6px
);
}
::v-deep .el-progress-bar__inner {
border-radius: 4px;
transition: all 0.3s ease;
position: relative;
background-image: repeating-linear-gradient(
to right,
transparent,
transparent 4px,
rgba(255, 255, 255, 0.2) 4px,
rgba(255, 255, 255, 0.2) 6px
);
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: inherit;
filter: brightness(1.2);
border-radius: 4px;
opacity: 0;
transition: opacity 0.3s ease;
}
}
&:hover {
::v-deep .el-progress-bar__inner::after {
opacity: 1;
}
}
}
.value {
width: 60px;
font-size: 13px;
color: #4a90e2;
text-align: right;
transition: all 0.3s ease;
}
}
}
}
}
}
</style>

View File

@ -1,89 +0,0 @@
<template>
<div class="research-overview">
<div class="content">
<ve-histogram
:data="chartData"
:settings="researchData.chartSettings"
:extend="chartStyles.research.extend"
height="260px"
/>
<div class="statistics">
<div
class="stat-item"
v-for="(item, index) in researchData.statistics"
:key="index"
>
<div class="number">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { researchData, chartStyles } from "../data/dashboardData";
export default {
name: "ResearchOverview",
components: {},
data() {
return {
researchData,
chartStyles,
chartData: researchData.chartData,
};
},
methods: {},
};
</script>
<style lang="scss" scoped>
.research-overview {
height: 100%;
color: #fff;
.content {
height: calc(100% - 80px);
margin-top: 20px;
padding: 0 10px;
.statistics {
display: flex;
justify-content: space-between;
margin-top: -30px;
padding: 0 20px;
.stat-item {
text-align: center;
min-width: 120px;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
.label {
color: rgba(255, 255, 255, 0.9);
}
}
.number {
font-size: 24px;
font-weight: bold;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
transition: all 0.3s ease;
}
.label {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
margin-top: 8px;
transition: all 0.3s ease;
}
}
}
}
}
</style>

View File

@ -1,148 +0,0 @@
<template>
<div class="staff-overview">
<div class="content">
<div class="total-info">
<span class="number">{{ formatNumber(staffData.totalStaff) }}</span>
<span class="label">教职工总数</span>
</div>
<div class="chart-and-structure">
<div class="charts">
<ve-ring
:data="titleChartData"
:settings="staffData.chartSettings"
:extend="staffData.chartSettings"
height="240px"
/>
</div>
<div class="education-structure">
<h4>学历结构</h4>
<div class="structure-items">
<div
class="structure-item"
v-for="(item, index) in staffData.educationStructure"
:key="index"
>
<span class="label">{{ item.label }}</span>
<span class="value">{{ item.value }}%</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { staffData } from "../data/dashboardData";
import { formatNumber } from "../utils/format";
export default {
name: "StaffOverview",
data() {
return {
staffData,
};
},
methods: {
formatNumber,
},
computed: {
titleChartData() {
return {
columns: ["职称", "人数"],
rows: this.staffData.titleData.rows,
};
},
},
};
</script>
<style lang="scss" scoped>
.staff-overview {
height: 100%;
color: #fff;
.content {
height: calc(100% - 80px);
margin-top: 20px;
.total-info {
text-align: center;
margin-bottom: 15px;
margin-top: -15px;
&:hover {
transform: translateY(-2px);
.label {
color: rgba(255, 255, 255, 0.9);
}
}
.number {
font-size: 24px;
font-weight: bold;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.label {
font-size: 14px;
margin-left: 10px;
color: rgba(255, 255, 255, 0.7);
}
}
.chart-and-structure {
display: flex;
align-items: center;
.charts {
width: 75%;
}
.education-structure {
width: 20%;
margin-left: 5%;
h4 {
font-size: 14px;
margin-bottom: 15px;
text-align: center;
color: rgba(255, 255, 255, 0.9);
}
.structure-items {
display: flex;
flex-wrap: wrap;
.structure-item {
width: 100%;
margin-bottom: 12px;
display: flex;
justify-content: space-between;
padding: 8px 12px;
transition: all 0.3s ease;
&:hover {
transform: translateX(4px);
}
.label {
color: rgba(255, 255, 255, 0.7);
font-size: 13px;
}
.value {
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 13px;
font-weight: 500;
transition: all 0.3s ease;
}
}
}
}
}
}
}
</style>

View File

@ -1,254 +0,0 @@
<template>
<div class="student-overview">
<common-header
:title="'学生概况'"
:total="localStudentData.totalStudents"
:unit="'人'"
@more-click="handleMoreClick"
/>
<div class="content">
<div class="map-container">
<three-map
:marker-position="localStudentData.location"
:marker-label="localStudentData.location.name"
/>
<div class="info-overlay">
<div class="info-panel total-panel">
<div class="total-students">
<i class="el-icon-user-solid"></i>
<div class="total-details">
<div class="total-label">在校学生总数</div>
<div class="total-value">
{{ localStudentData.totalStudents }}
</div>
</div>
</div>
</div>
<div class="info-panel grade-panel">
<h3>
<i class="el-icon-reading"></i>
年级分布
</h3>
<div class="info-grid">
<div
v-for="item in localStudentData.gradeData"
:key="item.name"
class="info-item"
>
<div class="info-details">
<div class="info-label">{{ item.name }}</div>
<div class="info-value">{{ item.value }}</div>
</div>
</div>
</div>
</div>
<div class="info-panel gender-panel">
<h3>
<i class="el-icon-user"></i>
性别比例
</h3>
<div class="info-grid">
<div
v-for="item in localStudentData.genderData"
:key="item.name"
class="info-item"
>
<div class="info-details">
<div class="info-label">
<i
:class="
item.name === '男' ? 'el-icon-male' : 'el-icon-female'
"
></i>
{{ item.name }}
</div>
<div class="info-value">{{ item.value }}</div>
<div class="info-percentage">
{{
Math.round(
(item.value / localStudentData.totalStudents) * 100
)
}}%
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import CommonHeader from "./CommonHeader.vue";
// import ThreeMap from "./ThreeMap.vue";
import { studentData } from "../data/dashboardData";
export default {
name: "StudentOverview",
components: {
CommonHeader,
// ThreeMap,
},
data() {
return {
localStudentData: JSON.parse(JSON.stringify(studentData)),
};
},
computed: {
totalStudents() {
return this.localStudentData.totalStudents;
},
},
methods: {
handleMoreClick() {
this.$router.push("/student/detail");
},
handleDataChange(newData) {
this.localStudentData = JSON.parse(JSON.stringify(newData));
},
},
};
</script>
<style scoped>
.student-overview {
height: 100%;
display: flex;
flex-direction: column;
background: rgba(0, 20, 40, 0.7);
border-radius: 4px;
padding: 16px;
}
.content {
flex: 1;
margin-top: 16px;
min-height: 400px;
}
.map-container {
position: relative;
width: 100%;
height: 100%;
min-height: 400px;
background: rgba(0, 30, 60, 0.5);
border-radius: 4px;
overflow: hidden;
}
.info-overlay {
position: absolute;
top: 20px;
right: 20px;
display: flex;
flex-direction: column;
gap: 16px;
max-width: 300px;
pointer-events: none;
}
.info-panel {
background: rgba(0, 0, 0, 0.7);
border-radius: 8px;
padding: 16px;
backdrop-filter: blur(10px);
}
.info-panel h3 {
color: #fff;
font-size: 16px;
margin: 0 0 16px;
display: flex;
align-items: center;
gap: 8px;
}
.info-panel h3 i {
font-size: 18px;
color: #409eff;
}
.info-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.info-item {
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
padding: 10px;
transition: all 0.3s ease;
}
.info-details {
text-align: center;
}
.info-label {
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
margin-bottom: 4px;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
}
.info-label i {
font-size: 16px;
}
.el-icon-male {
color: #409eff;
}
.el-icon-female {
color: #f56c6c;
}
.info-value {
color: #fff;
font-size: 18px;
font-weight: bold;
margin-bottom: 2px;
}
.info-percentage {
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
}
.total-panel {
background: rgba(0, 0, 0, 0.8);
}
.total-students {
display: flex;
align-items: center;
gap: 16px;
}
.total-students i {
font-size: 32px;
color: #409eff;
}
.total-details {
flex: 1;
}
.total-label {
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
margin-bottom: 4px;
}
.total-value {
color: #fff;
font-size: 24px;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,150 @@
<template>
<div>
<!-- 年度开工率 -->
<Echart
:options="options"
id="bottomLeftChart"
height="480px"
width="100%"
></Echart>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
data () {
return {
options: {},
};
},
components: {
Echart,
},
props: {
cdata: {
type: Object,
default: () => ({})
},
},
watch: {
cdata: {
handler (newData) {
this.options = {
tooltip: {
trigger: "axis",
backgroundColor: "rgba(255,255,255,0.1)",
axisPointer: {
type: "shadow",
label: {
show: true,
backgroundColor: "#7B7DDC"
}
}
},
legend: {
data: ["论文", "获奖", "专利",],
textStyle: {
color: "#B4B4B4"
},
top: "0%"
},
grid: {
x: "8%",
width: "88%",
y: "4%"
},
xAxis: {
data: newData.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: {
normal: {
color: "#F02FC2"
}
},
data: newData.rateData
},
{
name: "获奖",
type: "bar",
barWidth: 10,
itemStyle: {
normal: {
barBorderRadius: 5,
color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#956FD4" },
{ offset: 1, color: "#3EACE5" }
])
}
},
data: newData.barData
},
{
name: "专利",
type: "bar",
barGap: "-100%",
barWidth: 10,
itemStyle: {
normal: {
barBorderRadius: 5,
color: new this.$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: newData.lineData
}
]
}
},
immediate: true,
deep: true
},
},
}
</script>

View File

@ -0,0 +1,84 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue'
export default {
data () {
return {
cdata: {
category: [
"2012",
"2013",
"2014",
"2015",
"2016",
"2017",
"2018",
"2019",
"2020",
"2021",
"2022",
"2023",
"2024",
"2025",
],
lineData: [
18092,
20728,
24045,
28348,
32808,
36097,
39867,
44715,
48444,
50415,
56061,
62677,
59521,
67560,
],
barData: [
4600,
5000,
5500,
6500,
7500,
8500,
9900,
12500,
14000,
21500,
23200,
24450,
25250,
33300,
],
rateData: []
}
};
},
components: {
Chart,
},
mounted () {
this.setData();
},
methods: {
//
setData () {
for (let i = 0; i < this.cdata.barData.length -1; i++) {
let rate = this.cdata.barData[i] / this.cdata.lineData[i];
this.cdata.rateData.push(rate.toFixed(2));
}
},
}
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,358 @@
<template>
<div>
<Echart
:options="options"
id="centreLeft1Chart"
height="480px"
width="100%"
></Echart>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
data() {
return {
options: {},
//
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)'
}
]
}
}
}
},
components: {
Echart
},
props: {
cdata: {
type: Object,
default: () => ({})
}
},
watch: {
cdata: {
handler(newData) {
this.options = {
title: {
text: '',
textStyle: {
color: '#D3D6DD',
fontSize: 24,
fontWeight: 'normal'
},
subtext: newData.year + '/' + newData.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: this.colorList.linearYtoG,
opacity: 0.6
}
},
splitLine: {
lineStyle: {
color: this.colorList.linearYtoG,
opacity: 0.6
}
},
splitArea: {
areaStyle: {
color: '#fff',
opacity: 0.1,
shadowBlur: 25,
shadowColor: '#000',
shadowOffsetX: 0,
shadowOffsetY: 5
}
},
indicator: [
{
name: '服务态度',
max: newData.maxData
},
{
name: '产品质量',
max: 10
},
{
name: '任务效率',
max: 12
},
{
name: '售后保障',
max: 3.5
}
]
},
grid: {
left: 90,
right: 80,
bottom: 40,
top: '60%'
},
xAxis: {
type: 'category',
position: 'bottom',
axisLine: true,
axisLabel: {
color: 'rgba(255,255,255,.8)',
fontSize: 12
},
data: newData.weekCategory
},
// Y
yAxis: {
name: '工单',
nameLocation: 'end',
nameGap: 24,
nameTextStyle: {
color: 'rgba(255,255,255,.5)',
fontSize: 14
},
max: newData.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: newData.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: newData.radarData[6],
name: '我的指标',
itemStyle: {
normal: {
color: '#43dfa2'
}
},
lineStyle: {
normal: {
opacity: 0
}
},
areaStyle: {
normal: {
color: this.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: this.colorList.linearBtoG,
width: 3
}
},
areaStyle: {
normal: {
color: this.colorList.areaBtoG
}
},
data: newData.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: newData.weekMaxData,
animation: false
}
]
}
},
immediate: true,
deep: true
}
}
}
</script>

View File

@ -0,0 +1,89 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue'
export default {
data () {
return {
drawTiming: null,
cdata: {
year: null,
weekCategory: [],
radarData: [],
radarDataAvg: [],
maxData: 12000,
weekMaxData: [],
weekLineData: []
}
}
},
components: {
Chart,
},
mounted () {
this.drawTimingFn();
},
beforeDestroy () {
clearInterval(this.drawTiming);
},
methods: {
drawTimingFn () {
this.setData();
this.drawTiming = setInterval(() => {
this.setData();
}, 6000);
},
setData () {
//
this.cdata.weekCategory = [];
this.cdata.weekMaxData = [];
this.cdata.weekLineData = [];
this.cdata.radarData = [];
this.cdata.radarDataAvg = [];
let dateBase = new Date();
this.cdata.year = dateBase.getFullYear();
//
for (let i = 0; i < 7; i++) {
//
let date = new Date();
this.cdata.weekCategory.unshift([date.getMonth() + 1, date.getDate()-i].join("/"));
// 线
this.cdata.weekMaxData.push(this.cdata.maxData);
let distance = Math.round(Math.random() * 11000 + 500);
this.cdata.weekLineData.push(distance);
//
//
let averageSpeed = +(Math.random() * 5 + 3).toFixed(3);
let maxSpeed = averageSpeed + +(Math.random() * 3).toFixed(2);
let hour = +(distance / 1000 / averageSpeed).toFixed(1);
let radarDayData = [distance, averageSpeed, maxSpeed, hour];
this.cdata.radarData.unshift(radarDayData);
//
let distanceAvg = Math.round(Math.random() * 8000 + 4000);
let averageSpeedAvg = +(Math.random() * 4 + 4).toFixed(3);
let maxSpeedAvg = averageSpeedAvg + +(Math.random() * 2).toFixed(2);
let hourAvg = +(distance / 1000 / averageSpeed).toFixed(1);
let radarDayDataAvg = [
distanceAvg,
averageSpeedAvg,
maxSpeedAvg,
hourAvg
];
this.cdata.radarDataAvg.unshift(radarDayDataAvg);
}
}
}
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,104 @@
<template>
<div>
<!-- 通过率/达标率 -->
<Echart
:options="options"
:id="id"
height="100px"
width="100px"
></Echart>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
data () {
return {
options: {},
};
},
components: {
Echart,
},
props: {
id: {
type: String,
required: true,
default: "chartRate"
},
tips: {
type: Number,
required: true,
default: 50
},
colorObj: {
type: Object,
default: function () {
return {
textStyle: "#3fc0fb",
series: {
color: ["#00bcd44a", "transparent"],
dataColor: {
normal: "#03a9f4",
shadowColor: "#97e2f5"
}
}
};
}
}
},
watch: {
// tips
tips: {
handler (newData) {
this.options = {
title:{
text: newData * 1 + "%",
x: "center",
y: "center",
textStyle: {
color: this.colorObj.textStyle,
fontSize: 16
}
},
series: [
{
type: "pie",
radius: ["75%", "80%"],
center: ["50%", "50%"],
hoverAnimation: false,
color: this.colorObj.series.color,
label: {
normal: {
show: false
}
},
data: [
{
value: newData,
itemStyle: {
normal: {
color: this.colorObj.series.dataColor.normal,
shadowBlur: 10,
shadowColor: this.colorObj.series.dataColor.shadowColor
}
}
},
{
value: 100 - newData
}
]
}
]
}
},
immediate: true,
deep: true
}
}
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,81 @@
<template>
<div>
<Echart
:options="options"
id="centreLeft1Chart"
height="220px"
width="260px"
></Echart>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
data () {
return {
options: {},
};
},
components: {
Echart,
},
props: {
cdata: {
type: Object,
default: () => ({})
},
},
watch: {
cdata: {
handler (newData) {
this.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: newData.xData,
textStyle: {
color: "#fff"
}
},
series: [
{
name: "通过率统计",
type: "pie",
radius: [10, 50],
roseType: "area",
center: ["50%", "40%"],
data: newData.seriesData
}
]
}
},
immediate: true,
deep: true
}
}
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,36 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue';
export default {
data () {
return {
cdata: {
xData: ["data1", "data2", "data3", "data4", "data5", "data6"],
seriesData: [
{ value: 10, name: "data1" },
{ value: 5, name: "data2" },
{ value: 15, name: "data3" },
{ value: 25, name: "data4" },
{ value: 20, name: "data5" },
{ value: 35, name: "data6" }
]
}
}
},
components: {
Chart,
},
mounted () {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,290 @@
<template>
<div>
<Echart
id="centreLeft2Chart"
ref="centreLeft2ChartRef"
:options="options"
height="360px"
width="330px"
></Echart>
</div>
</template>
<script>
import Echart from '@/common/echart';
export default {
data() {
return {
options: {},
};
},
components: {
Echart,
},
props: {
cdata: {
type: Array,
default: () => [],
},
},
watch: {
cdata: {
handler(newData) {
// ()
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],
};
let seriesData = [
{
name: '厦门市',
},
{
name: '福州市',
},
{
name: '泉州市',
},
{
name: '漳州市',
},
{
name: '龙岩市',
},
{
name: '莆田市',
},
{
name: '三明市',
},
{
name: '南平市',
},
{
name: '宁德市',
},
];
let convertData = function (data) {
let scatterData = [];
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name];
if (geoCoord) {
scatterData.push({
name: data[i].name,
value: geoCoord.concat(data[i].value),
});
}
}
return scatterData;
};
this.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.2,
top: '10%',
left: '16%',
map: '福建',
roam: false,
itemStyle: {
normal: {
areaColor: 'rgba(0,0,0,0)',
shadowColor: 'rgba(7,114,204, .8)',
shadowOffsetX: 5,
shadowOffsetY: 5,
},
emphasis: {
areaColor: '#00aeef',
},
},
},
series: [
{
name: '相关指数',
type: 'map',
aspectScale: 0.85, //
zoom: 1.2,
mapType: '福建', //
top: '10%',
left: '16%',
itemStyle: {
normal: {
color: 'red',
areaColor: 'rgba(19,54,162, .5)',
borderColor: 'rgba(0,242,252,.3)',
borderWidth: 1,
shadowBlur: 7,
shadowColor: '#00f2fc',
},
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: newData,
},
{
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),
},
],
};
//
this.handleMapRandomSelect();
},
immediate: true,
deep: true,
},
},
methods: {
//
startInterval() {
const _self = this;
// 5s
const time = 2000;
if (this.intervalId !== null) {
clearInterval(this.intervalId);
}
this.intervalId = setInterval(() => {
_self.reSelectMapRandomArea();
}, time);
},
//
reSelectMapRandomArea() {
const length = 9;
this.$nextTick(() => {
try {
const map = this.$refs.centreLeft2ChartRef.chart;
let index = Math.floor(Math.random() * length);
while (index === this.preSelectMapIndex || index >= length) {
index = Math.floor(Math.random() * length);
}
map.dispatchAction({
type: 'mapUnSelect',
seriesIndex: 0,
dataIndex: this.preSelectMapIndex,
});
map.dispatchAction({
type: 'showTip',
seriesIndex: 0,
dataIndex: index,
});
map.dispatchAction({
type: 'mapSelect',
seriesIndex: 0,
dataIndex: index,
});
this.preSelectMapIndex = index;
} catch (error) {
console.log(error)
}
});
},
handleMapRandomSelect() {
this.$nextTick(() => {
try {
const map = this.$refs.centreLeft2ChartRef.chart;
const _self = this;
setTimeout(() => {
_self.reSelectMapRandomArea();
}, 0);
//
map.on('mouseover', function (params) {
clearInterval(_self.intervalId);
map.dispatchAction({
type: 'mapUnSelect',
seriesIndex: 0,
dataIndex: _self.preSelectMapIndex,
});
map.dispatchAction({
type: 'mapSelect',
seriesIndex: 0,
dataIndex: params.dataIndex,
});
_self.preSelectMapIndex = params.dataIndex;
});
//
map.on('globalout', function () {
_self.reSelectMapRandomArea();
_self.startInterval();
});
this.startInterval();
} catch (error) {
console.log(error)
}
});
},
},
};
</script>

View File

@ -0,0 +1,67 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue';
export default {
data () {
return {
cdata: [
{
// 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,
}
]
}
},
components: {
Chart,
},
mounted () {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,132 @@
<template>
<div>
<Echart
:options="options"
id="centreRight2Chart1"
height="200px"
width="260px"
></Echart>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
data () {
return {
options: {},
};
},
components: {
Echart,
},
props: {
cdata: {
type: Object,
default: () => ({})
},
},
watch: {
cdata: {
handler (newData) {
//
let lineStyle = {
normal: {
width: 1,
opacity: 0.5
}
};
this.options = {
radar: {
indicator: newData.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: newData.dataBJ,
symbol: "none",
itemStyle: {
normal: {
color: "#F9713C"
}
},
areaStyle: {
normal: {
opacity: 0.1
}
}
},
{
name: "上海",
type: "radar",
lineStyle: lineStyle,
data: newData.dataSH,
symbol: "none",
itemStyle: {
normal: {
color: "#B3E4A1"
}
},
areaStyle: {
normal: {
opacity: 0.05
}
}
},
{
name: "广州",
type: "radar",
lineStyle: lineStyle,
data: newData.dataGZ,
symbol: "none",
itemStyle: {
normal: {
color: "rgb(238, 197, 102)"
}
},
areaStyle: {
normal: {
opacity: 0.05
}
}
} //end
]
}
},
immediate: true,
deep: true
}
}
};
</script>

View File

@ -0,0 +1,55 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue';
export default {
data () {
return {
cdata: {
indicatorData: [
{ name: "data1", max: 300 },
{ name: "data2", max: 250 },
{ name: "data3", max: 300 },
{ name: "data4", max: 5},
{ name: "data5", max: 200 },
{ name: "data6", 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]
]
}
}
},
components: {
Chart,
}
}
</script>

View File

@ -1,419 +0,0 @@
// 科研概况数据
export const researchData = {
chartSettings: {
dimension: ["季度"],
metrics: ["论文", "专利", "获奖", "著作"],
legend: {
show: true,
textStyle: {
color: "#fff",
},
},
grid: {
show: true,
borderColor: "rgba(255, 255, 255, 0.1)",
backgroundColor: "transparent",
},
backgroundColor: "rgba(0, 0, 0, 0.5)",
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
},
chartData: {
columns: ["季度", "论文", "专利", "获奖", "著作"],
rows: [
{ 季度: "Q1", 论文: 20, 专利: 15, 获奖: 5, 著作: 3 },
{ 季度: "Q2", 论文: 25, 专利: 18, 获奖: 8, 著作: 4 },
{ 季度: "Q3", 论文: 30, 专利: 20, 获奖: 10, 著作: 5 },
{ 季度: "Q4", 论文: 35, 专利: 25, 获奖: 12, 著作: 6 },
],
},
statistics: [
{ label: "论文总数", value: 110 },
{ label: "专利数量", value: 78 },
{ label: "获奖数量", value: 35 },
{ label: "著作数量", value: 18 },
],
};
// 教务概况数据
export const educationData = {
chartSettings: {
area: true,
axisSite: { right: ["评教得分"] },
yAxisName: ["得分"],
},
evaluationData: {
columns: ["月份", "评教得分"],
rows: [
{ 月份: "1月", 评教得分: 85 },
{ 月份: "2月", 评教得分: 93 },
{ 月份: "3月", 评教得分: 90 },
{ 月份: "4月", 评教得分: 74 },
{ 月份: "5月", 评教得分: 95 },
{ 月份: "6月", 评教得分: 92 },
],
},
statistics: {
passRate: 95.6,
graduationRate: 98.2,
},
};
// 图表样式配置
export const chartStyles = {
research: {
colors: [
"rgba(64, 158, 255, 0.95)", // 亮蓝色
"rgba(0, 206, 209, 0.95)", // 青色
"rgba(149, 97, 226, 0.95)", // 紫色
"rgba(100, 181, 246, 0.95)", // 天蓝色
],
extend: {
series: (v) => {
if (!v) return [];
const gradientColors = [
["rgba(64, 158, 255, 0.95)", "rgba(64, 158, 255, 0.2)"], // 亮蓝色
["rgba(0, 206, 209, 0.95)", "rgba(0, 206, 209, 0.2)"], // 青色
["rgba(149, 97, 226, 0.95)", "rgba(149, 97, 226, 0.2)"], // 紫色
["rgba(100, 181, 246, 0.95)", "rgba(100, 181, 246, 0.2)"], // 天蓝色
];
return v.map((series, index) => ({
...series,
itemStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: gradientColors[index][0] },
{ offset: 1, color: gradientColors[index][1] },
],
},
borderRadius: [10, 10, 0, 0],
shadowColor: "rgba(0, 0, 0, 0.5)",
shadowBlur: 10,
shadowOffsetY: 5,
},
emphasis: {
itemStyle: {
color: gradientColors[index][0],
shadowBlur: 20,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.8)",
},
},
animationDuration: 2000,
animationEasing: "elasticOut",
}));
},
yAxis: {
axisLabel: {
color: "#fff",
fontSize: 12,
},
splitLine: {
lineStyle: {
color: "rgba(255, 255, 255, 0.1)",
},
},
},
xAxis: {
axisLabel: {
color: "#fff",
fontSize: 12,
},
},
legend: {
textStyle: {
color: "#fff",
},
emphasis: {
textStyle: {
color: "#4a90e2",
},
},
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
shadowStyle: {
color: "rgba(74, 144, 226, 0.1)",
},
},
textStyle: {
color: "#fff",
fontSize: 12,
},
},
},
},
education: {
extend: {
yAxis: {
min: 60,
max: 100,
axisLabel: {
color: "#fff",
fontSize: 12,
},
splitLine: {
show: false
},
},
xAxis: {
axisLabel: {
color: "#fff",
fontSize: 12,
},
splitLine: {
show: false
}
},
legend: {
textStyle: {
color: "#fff",
}
},
series: {
smooth: true,
lineStyle: {
width: 2,
color: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: "#4a90e2",
},
{
offset: 1,
color: "#36d1dc",
},
],
global: false,
},
},
areaStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(74, 144, 226, 0.3)",
},
{
offset: 1,
color: "rgba(54, 209, 220, 0.05)",
},
],
global: false,
},
},
animationDuration: 200,
animationEasing: "cubicOut",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "line",
lineStyle: {
color: "#4a90e2",
type: "dashed",
shadowColor: "rgba(0, 0, 0, 0.3)",
shadowBlur: 5,
},
},
textStyle: {
color: "#fff",
fontSize: 12,
},
formatter: function (params) {
const param = params[0];
return `${param.name}<br/>${param.seriesName}<span style="color:${param.color}">${param.value}</span>`;
}
},
},
},
};
// 资产概况数据
export const assetData = {
totalAssets: 580000,
assetTrendData: {
columns: ["月份", "资产总值"],
rows: [
{ 月份: "1月", 资产总值: 380000 },
{ 月份: "2月", 资产总值: 535000 },
{ 月份: "3月", 资产总值: 445000 },
{ 月份: "4月", 资产总值: 520000 },
{ 月份: "5月", 资产总值: 570000 },
{ 月份: "6月", 资产总值: 480000 },
],
},
assetCategories: [
{ name: "固定资产", value: 420000 },
{ name: "流动资产", value: 120000 },
{ name: "无形资产", value: 40000 },
],
};
// 一卡通概况数据
export const cardData = {
totalCards: 28500,
dailyUsage: 85600,
chartSettings: {
area: true,
axisSite: { right: ["使用次数"] },
yAxisName: ["次数"],
},
usageData: {
columns: ["时间", "使用次数"],
rows: [
{ 时间: "6:00", 使用次数: 2000 },
{ 时间: "9:00", 使用次数: 15000 },
{ 时间: "12:00", 使用次数: 25000 },
{ 时间: "15:00", 使用次数: 18000 },
{ 时间: "18:00", 使用次数: 20000 },
{ 时间: "21:00", 使用次数: 5600 },
],
},
usageScenes: [
{ name: "食堂消费", count: 35000 },
{ name: "门禁通行", count: 28000 },
{ name: "图书借阅", count: 12000 },
{ name: "水电缴费", count: 8000 },
],
};
// 文献概况数据
export const literatureData = {
totalLiterature: 1250000,
chartSettings: {
dimension: ["类型"],
metrics: ["纸质", "电子"],
legend: {
show: true,
textStyle: { color: "#fff" },
},
grid: {
show: true,
borderColor: "rgba(255, 255, 255, 0.1)",
backgroundColor: "transparent",
},
backgroundColor: "rgba(0, 0, 0, 0.5)",
tooltip: {
trigger: "axis",
axisPointer: { type: "shadow" },
},
},
chartData: {
columns: ["类型", "纸质", "电子"],
rows: [
{ 类型: "图书", 纸质: 450000, 电子: 350000 },
{ 类型: "期刊", 纸质: 120000, 电子: 180000 },
{ 类型: "论文", 纸质: 50000, 电子: 100000 },
],
},
subjectDistribution: [
{ name: "工学", count: 320000, percentage: 85, color: "#409EFF" },
{ name: "理学", count: 280000, percentage: 75, color: "#67C23A" },
{ name: "经管", count: 220000, percentage: 65, color: "#E6A23C" },
{ name: "文学", count: 180000, percentage: 55, color: "#F56C6C" },
{ name: "艺术", count: 150000, percentage: 45, color: "#909399" },
],
};
// 教职工概况数据
export const staffData = {
totalStaff: 1256,
chartSettings: {
radius: ["35%", "65%"],
offsetY: "60%",
color: [
"#4a90e2", // 亮蓝色
"#00CED1", // 青色
"#64B5F6", // 天蓝色
"#9561e2", // 紫色
],
label: {
show: true,
position: "outside",
formatter: "{b}:{c}({d}%)",
color: "#fff",
fontSize: 12,
},
legend: {
show: true,
textStyle: {
color: "#fff",
fontSize: 12
}
},
itemStyle: {
borderRadius: 4,
borderColor: "#fff",
borderWidth: 2
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
},
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
},
titleData: {
columns: ["职称", "人数"],
rows: [
{ 职称: "正高", 人数: 180 },
{ 职称: "副高", 人数: 320 },
{ 职称: "中级", 人数: 450 },
{ 职称: "初级", 人数: 306 },
],
},
educationStructure: [
{ label: "博士", value: 35 },
{ label: "硕士", value: 45 },
{ label: "学士", value: 18 },
{ label: "其他", value: 2 },
],
};
export const studentData = {
totalStudents: 12000,
location: {
name: "唐山师范学院",
coordinates: [118.154, 39.630],
address: "河北省唐山市路北区建设路156号"
},
gradeData: [
{ name: "大一", value: 3200 },
{ name: "大二", value: 3100 },
{ name: "大三", value: 2900 },
{ name: "大四", value: 2800 }
],
genderData: [
{ name: "男", value: 5500 },
{ name: "女", value: 6500 }
]
};

View File

@ -1,10 +1,7 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import VCharts from 'v-charts'
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import dataV from '@jiaminghi/data-view';
// 引入全局css
import './assets/scss/style.scss';
@ -19,8 +16,8 @@ import 'vue-awesome/icons/align-left.js';
//引入echart
//4.x 引用方式
import echarts from 'echarts'
// //5.x 引用方式为按需引用
// //希望使用5.x版本的话,需要在package.json中更新版本号,并切换引用方式
//5.x 引用方式为按需引用
//希望使用5.x版本的话,需要在package.json中更新版本号,并切换引用方式
//import * as echarts from 'echarts'
Vue.prototype.$echarts = echarts
Vue.config.productionTip = false;
@ -28,11 +25,9 @@ Vue.config.productionTip = false;
// 全局注册
Vue.component('icon', Icon);
Vue.use(dataV);
Vue.use(ElementUI);
Vue.use(VCharts);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
render: (h) => h(App),
}).$mount('#app');

View File

@ -3,55 +3,11 @@ import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'index',
component: () => import('../views/index.vue')
},
// 教务详情
{
path: '/education-detail',
name: 'EducationDetail',
component: () => import('@/views/detail/EducationDetail.vue')
},
// 科研详情
{
path: '/research-detail',
name: 'ResearchDetail',
component: () => import('@/views/detail/ResearchDetail.vue')
},
// 学生详情
{
path: '/student-detail',
name: 'StudentDetail',
component: () => import('@/views/detail/StudentDetail.vue')
},
// 教职工详情
{
path: '/staff-detail',
name: 'StaffDetail',
component: () => import('@/views/detail/StaffDetail.vue')
},
// 资产详情
{
path: '/asset-detail',
name: 'AssetDetail',
component: () => import('@/views/detail/AssetDetail.vue')
},
// 文献详情
{
path: '/literature-detail',
name: 'LiteratureDetail',
component: () => import('@/views/detail/LiteratureDetail.vue')
},
// 一卡通详情页面
{
path: '/card-detail',
name: 'CardDetail',
component: () => import('@/views/detail/CardDetail.vue')
},
]
const routes = [{
path: '/',
name: 'index',
component: () => import('../views/index.vue')
}]
const router = new VueRouter({
routes
})

View File

@ -1,56 +0,0 @@
export default {
data() {
return {
// 通用图表配置
baseChartExtend: {
yAxis: {
axisLabel: {
color: '#fff',
fontSize: 12
},
splitLine: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.1)'
}
}
},
xAxis: {
axisLabel: {
color: '#fff',
fontSize: 12
}
},
legend: {
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
lineStyle: {
color: '#e1e2e2',
type: 'dashed',
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 5
}
},
textStyle: {
color: '#fff',
fontSize: 12
}
}
}
}
},
methods: {
// 合并图表配置
mergeChartExtend(customExtend) {
return {
...this.baseChartExtend,
...customExtend
}
}
}
}

View File

@ -1,18 +0,0 @@
/**
* 格式化数字添加千位分隔符
* @param {number} num - 要格式化的数字
* @returns {string} - 格式化后的字符串
*/
export const formatNumber = (num) => {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
/**
* 格式化金额添加千位分隔符和货币符号
* @param {number} amount - 要格式化的金额
* @param {string} symbol - 货币符号默认为 ¥
* @returns {string} - 格式化后的金额字符串
*/
export const formatCurrency = (amount, symbol = '¥') => {
return `${symbol} ${formatNumber(amount)}`;
};

52
src/views/bottomLeft.vue Normal file
View File

@ -0,0 +1,52 @@
<template>
<div id="bottomLeft">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<icon name="chart-bar" class="text-icon"></icon>
</span>
<div class="d-flex">
<span class="fs-xl text mx-2">科研概况</span>
</div>
</div>
<div>
<BottomLeftChart />
</div>
</div>
</div>
</template>
<script>
import BottomLeftChart from '@/components/echart/bottom/bottomLeftChart'
export default {
components: {
BottomLeftChart
}
}
</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>

60
src/views/bottomRight.vue Normal file
View File

@ -0,0 +1,60 @@
<template>
<div id="bottomRight">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<icon name="chart-area" class="text-icon"></icon>
</span>
<div class="d-flex">
<span class="fs-xl text mx-2">工单修复以及满意度统计图</span>
<div class="decoration2">
<dv-decoration-2 :reverse="true" style="width:5px;height:6rem;" />
</div>
</div>
</div>
<div>
<BottomRightChart />
</div>
</div>
</div>
</template>
<script>
import BottomRightChart from "@/components/echart/bottom/bottomRightChart";
export default {
components: {
BottomRightChart
}
};
</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;
}
//线
.decoration2 {
position: absolute;
right: 0.125rem;
}
.chart-box {
margin-top: 16px;
width: 170px;
height: 170px;
.active-ring-name {
padding-top: 10px;
}
}
}
</style>

283
src/views/center.vue Normal file
View File

@ -0,0 +1,283 @@
<template>
<div id="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 fs-xl">{{ item.title }}</p>
<div>
<dv-digital-flop
class="dv-dig-flop ml-1 mt-2 pl-3"
:config="item.number"
/>
</div>
</div>
</div>
<div class="down">
<div class="ranking bg-color-black">
<span>
<icon name="chart-pie" class="text-icon"></icon>
</span>
<span class="fs-xl text mx-2 mb-1 pl-3">年度负责人组件达标榜</span>
<dv-scroll-ranking-board class="dv-scr-rank-board mt-1" :config="ranking" />
</div>
<div class="percent">
<div class="item bg-color-black">
<span>今日任务通过率</span>
<CenterChart
:id="rate[0].id"
:tips="rate[0].tips"
:colorObj="rate[0].colorData"
/>
</div>
<div class="item bg-color-black">
<span>今日任务达标率</span>
<CenterChart
:id="rate[1].id"
: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>
import CenterChart from '@/components/echart/center/centerChartRate'
export default {
data() {
return {
titleItem: [
{
title: '今年累计任务建次数',
number: {
number: [120],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '本月累计任务次数',
number: {
number: [18],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '今日累计任务次数',
number: {
number: [2],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '今年失败任务次数',
number: {
number: [14],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '今年成功任务次数',
number: {
number: [106],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '今年达标任务个数',
number: {
number: [100],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
}
],
ranking: {
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: '人'
},
water: {
data: [24, 45],
shape: 'roundRect',
formatter: '{value}%',
waveNum: 3
},
//
rate: [
{
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'
}
}
}
}
]
}
},
components: {
CenterChart
}
}
</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: 225px;
}
}
.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>

169
src/views/centerLeft1.vue Normal file
View File

@ -0,0 +1,169 @@
<template>
<div id="centerLeft1">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<icon name="chart-bar" class="text-icon"></icon>
</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">
<CenterLeft1Chart />
</div>
<!-- 4个主要的数据 -->
<div class="bottom-data">
<div
class="item-box mt-2"
v-for="(item, index) in numberData"
:key="index"
>
<div class="d-flex">
<span class="coin"></span>
<dv-digital-flop class="dv-digital-flop" :config="item.number" />
</div>
<p class="text" style="text-align: center;">
{{ item.text }}
<span class="colorYellow">()</span>
</p>
</div>
</div>
</div>
</div>
</template>
<script>
import CenterLeft1Chart from '@/components/echart/centerLeft/centerLeft1Chart'
export default {
data() {
return {
numberData: [
{
number: {
number: [15],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '教务概况'
},
{
number: {
number: [1144],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '科研概况'
},
{
number: {
number: [361],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '学生概况'
},
{
number: {
number: [157],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '教职工概况'
}
]
}
},
components: {
CenterLeft1Chart
},
mounted() {
this.changeTiming()
},
methods: {
changeTiming() {
setInterval(() => {
this.changeNumber()
}, 3000)
},
changeNumber() {
this.numberData.forEach((item, index) => {
item.number.number[0] += ++index
item.number = { ...item.number }
})
}
}
}
</script>
<style lang="scss" scoped>
$box-width: 300px;
$box-height: 410px;
#centerLeft1 {
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;
}
//
.coin {
position: relative;
top: 6px;
font-size: 20px;
color: #ffc107;
}
.colorYellow {
color: yellowgreen;
}
p {
text-align: center;
}
}
}
}
</style>

59
src/views/centerLeft2.vue Normal file
View File

@ -0,0 +1,59 @@
<template>
<div id="centerLeft1">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<icon name="chart-pie" class="text-icon"></icon>
</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">
<CenterLeft2Chart />
</div>
</div>
</div>
</template>
<script>
import CenterLeft2Chart from "@/components/echart/centerLeft/centerLeft2Chart";
export default {
components: {
CenterLeft2Chart
},
};
</script>
<style lang="scss" scoped>
#centerLeft1 {
$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>

View File

@ -0,0 +1,76 @@
<template>
<div id="centerRight1">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<icon name="chart-line" class="text-icon"></icon>
</span>
<div class="d-flex">
<span class="fs-xl text mx-2">任务完成排行榜</span>
</div>
</div>
<div class="d-flex jc-center body-box">
<dv-scroll-board class="dv-scr-board" :config="config" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
config: {
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;
#centerRight1 {
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>

View File

@ -0,0 +1,80 @@
<template>
<div id="centerRight2">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<icon name="align-left" class="text-icon"></icon>
</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" />
<centerRight2Chart1 />
</div>
</div>
</div>
</template>
<script>
import centerRight2Chart1 from '@/components/echart/centerRight/centerRightChart'
export default {
data() {
return {
config: {
data: [
{
name: '南阳',
value: 167
},
{
name: '周口',
value: 67
},
{
name: '漯河',
value: 123
},
{
name: '郑州',
value: 55
},
{
name: '西峡',
value: 98
}
]
}
}
},
components: { centerRight2Chart1 }
}
</script>
<style lang="scss" scoped>
#centerRight2 {
$box-height: 410px;
$box-width: 340px;
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>

View File

@ -1,291 +0,0 @@
<template>
<div class="asset-detail">
<div class="header">
<el-page-header @back="goBack" content="资产详情" />
<div class="filters">
<el-select v-model="selectedYear" placeholder="选择年份">
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
</div>
</div>
<el-row :gutter="20" class="overview-cards">
<el-col :span="6" v-for="(item, index) in overviewData" :key="index">
<el-card shadow="hover" class="overview-card">
<div class="card-content">
<div class="value">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
<div class="trend" :class="item.trend">
{{ item.trendValue }}%
<i
:class="item.trend === 'up' ? 'el-icon-top' : 'el-icon-bottom'"
></i>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>资产类型分布</span>
</div>
<ve-pie
:data="assetTypeData"
:settings="pieSettings"
height="300px"
/>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>资产价值趋势</span>
</div>
<ve-line
:data="assetValueData"
:settings="lineSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>设备使用率</span>
</div>
<ve-gauge
:data="equipmentUsageData"
:settings="gaugeSettings"
height="300px"
/>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>预算执行情况</span>
</div>
<ve-histogram
:data="budgetData"
:settings="histogramSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-card class="table-card">
<div slot="header">
<span>资产采购计划</span>
<el-button style="float: right" type="text">查看全部</el-button>
</div>
<el-table :data="purchaseData" style="width: 100%">
<el-table-column prop="name" label="采购项目" />
<el-table-column prop="department" label="申请部门" />
<el-table-column prop="budget" label="预算金额(万)" />
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="progress" label="进度">
<template slot-scope="scope">
<el-progress :percentage="scope.row.progress" />
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: "AssetDetail",
data() {
return {
selectedYear: "2024",
years: ["2024", "2023", "2022", "2021"],
overviewData: [
{ label: "总资产(万元)", value: "580,000", trend: "up", trendValue: 8 },
{ label: "设备数量(台)", value: "12,586", trend: "up", trendValue: 5 },
{ label: "设备完好率", value: "96.8%", trend: "up", trendValue: 2 },
{ label: "预算执行率", value: "85.2%", trend: "up", trendValue: 10 },
],
assetTypeData: {
columns: ["类型", "金额"],
rows: [
{ 类型: "房屋建筑", 金额: 280000 },
{ 类型: "教学设备", 金额: 150000 },
{ 类型: "科研设备", 金额: 100000 },
{ 类型: "办公设备", 金额: 30000 },
{ 类型: "其他资产", 金额: 20000 },
],
},
pieSettings: {
radius: "65%",
offsetY: "60%",
},
assetValueData: {
columns: ["月份", "资产总值"],
rows: [
{ 月份: "1月", 资产总值: 550000 },
{ 月份: "2月", 资产总值: 555000 },
{ 月份: "3月", 资产总值: 562000 },
{ 月份: "4月", 资产总值: 568000 },
{ 月份: "5月", 资产总值: 575000 },
{ 月份: "6月", 资产总值: 580000 },
],
},
lineSettings: {
area: true,
},
equipmentUsageData: {
columns: ["type", "value"],
rows: [{ type: "设备使用率", value: 85.6 }],
},
gaugeSettings: {
dataName: {
设备使用率: "使用率",
},
seriesMap: {
设备使用率: {
min: 0,
max: 100,
splitNumber: 10,
},
},
},
budgetData: {
columns: ["月份", "预算金额", "实际支出"],
rows: [
{ 月份: "1月", 预算金额: 1000, 实际支出: 850 },
{ 月份: "2月", 预算金额: 1200, 实际支出: 1000 },
{ 月份: "3月", 预算金额: 1500, 实际支出: 1300 },
{ 月份: "4月", 预算金额: 1800, 实际支出: 1600 },
{ 月份: "5月", 预算金额: 2000, 实际支出: 1750 },
{ 月份: "6月", 预算金额: 2200, 实际支出: 1900 },
],
},
histogramSettings: {
metrics: ["预算金额", "实际支出"],
},
purchaseData: [
{
name: "实验室设备更新",
department: "物理学院",
budget: 500,
status: "审批中",
progress: 30,
},
{
name: "智慧教室建设",
department: "教务处",
budget: 800,
status: "已立项",
progress: 10,
},
{
name: "图书馆设备采购",
department: "图书馆",
budget: 300,
status: "采购中",
progress: 60,
},
{
name: "体育场地维护",
department: "体育部",
budget: 200,
status: "已完成",
progress: 100,
},
],
};
},
methods: {
goBack() {
this.$router.push("/");
},
getStatusType(status) {
const types = {
审批中: "warning",
已立项: "primary",
采购中: "success",
已完成: "info",
};
return types[status] || "info";
},
},
};
</script>
<style lang="scss" scoped>
.asset-detail {
padding: 20px;
background: #f0f2f5;
min-height: 100vh;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.overview-cards {
margin-bottom: 20px;
.overview-card {
.card-content {
text-align: center;
.value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.label {
font-size: 14px;
color: #909399;
margin: 8px 0;
}
.trend {
font-size: 12px;
&.up {
color: #67c23a;
}
&.down {
color: #f56c6c;
}
}
}
}
}
.charts-row {
margin-bottom: 20px;
.chart-card {
height: 400px;
}
}
.table-card {
margin-bottom: 20px;
}
}
</style>

View File

@ -1,305 +0,0 @@
<template>
<div class="card-detail">
<div class="header">
<el-page-header @back="goBack" content="一卡通详情" />
<div class="filters">
<el-select v-model="selectedYear" placeholder="选择年份">
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
<el-date-picker
v-model="selectedDate"
type="date"
placeholder="选择日期"
size="small"
/>
</div>
</div>
<el-row :gutter="20" class="overview-cards">
<el-col :span="6" v-for="(item, index) in overviewData" :key="index">
<el-card shadow="hover" class="overview-card">
<div class="card-content">
<div class="value">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
<div class="trend" :class="item.trend">
{{ item.trendValue }}%
<i
:class="item.trend === 'up' ? 'el-icon-top' : 'el-icon-bottom'"
></i>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>消费趋势分析</span>
</div>
<ve-line
:data="consumptionData"
:settings="lineSettings"
height="300px"
/>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>消费场所分布</span>
</div>
<ve-pie :data="locationData" :settings="pieSettings" height="300px" />
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>门禁使用分析</span>
</div>
<ve-histogram
:data="accessData"
:settings="histogramSettings"
height="300px"
/>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>卡务办理统计</span>
</div>
<ve-bar :data="cardServiceData" height="300px" />
</el-card>
</el-col>
</el-row>
<el-card class="table-card">
<div slot="header">
<span>异常记录</span>
<el-button style="float: right" type="text">查看全部</el-button>
</div>
<el-table :data="abnormalRecords" style="width: 100%">
<el-table-column prop="time" label="时间" width="180" />
<el-table-column prop="cardNo" label="卡号" width="120" />
<el-table-column prop="location" label="地点" />
<el-table-column prop="type" label="类型" width="120">
<template slot-scope="scope">
<el-tag :type="getAbnormalType(scope.row.type)">
{{ scope.row.type }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="处理状态" width="120">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: "CardDetail",
data() {
return {
selectedYear: "2024",
selectedDate: new Date(),
years: ["2024", "2023", "2022", "2021"],
overviewData: [
{ label: "发卡总量", value: "28,586", trend: "up", trendValue: 3 },
{
label: "日均消费额(元)",
value: "256,890",
trend: "up",
trendValue: 5,
},
{ label: "日均使用次数", value: "85,630", trend: "up", trendValue: 8 },
{ label: "卡片完好率", value: "99.2%", trend: "up", trendValue: 0.5 },
],
consumptionData: {
columns: ["时间", "消费金额", "消费笔数"],
rows: [
{ 时间: "6:00", 消费金额: 5000, 消费笔数: 500 },
{ 时间: "8:00", 消费金额: 25000, 消费笔数: 2500 },
{ 时间: "12:00", 消费金额: 85000, 消费笔数: 8500 },
{ 时间: "15:00", 消费金额: 45000, 消费笔数: 4500 },
{ 时间: "18:00", 消费金额: 65000, 消费笔数: 6500 },
{ 时间: "21:00", 消费金额: 35000, 消费笔数: 3500 },
],
},
lineSettings: {
axisSite: { right: ["消费笔数"] },
yAxisType: ["normal", "normal"],
yAxisName: ["金额", "笔数"],
},
locationData: {
columns: ["场所", "消费额"],
rows: [
{ 场所: "食堂", 消费额: 150000 },
{ 场所: "超市", 消费额: 50000 },
{ 场所: "图书馆", 消费额: 20000 },
{ 场所: "浴室", 消费额: 25000 },
{ 场所: "其他", 消费额: 10000 },
],
},
pieSettings: {
radius: "65%",
offsetY: "60%",
},
accessData: {
columns: ["时间段", "图书馆", "宿舍", "教学楼"],
rows: [
{ 时间段: "6:00-9:00", 图书馆: 500, 宿舍: 2500, 教学楼: 1500 },
{ 时间段: "9:00-12:00", 图书馆: 2500, 宿舍: 1000, 教学楼: 3500 },
{ 时间段: "12:00-15:00", 图书馆: 1800, 宿舍: 1800, 教学楼: 2500 },
{ 时间段: "15:00-18:00", 图书馆: 2000, 宿舍: 1500, 教学楼: 2000 },
{ 时间段: "18:00-22:00", 图书馆: 1500, 宿舍: 3500, 教学楼: 1000 },
],
},
histogramSettings: {
stack: { 类型: ["图书馆", "宿舍", "教学楼"] },
},
cardServiceData: {
columns: ["服务类型", "数量"],
rows: [
{ 服务类型: "新卡办理", 数量: 256 },
{ 服务类型: "挂失", 数量: 158 },
{ 服务类型: "解挂", 数量: 142 },
{ 服务类型: "补办", 数量: 86 },
{ 服务类型: "注销", 数量: 35 },
],
},
abnormalRecords: [
{
time: "2023-06-20 08:25:36",
cardNo: "2023001",
location: "图书馆",
type: "重复刷卡",
status: "已处理",
},
{
time: "2023-06-20 12:15:42",
cardNo: "2023158",
location: "食堂",
type: "余额异常",
status: "处理中",
},
{
time: "2023-06-20 15:30:18",
cardNo: "2023286",
location: "宿舍",
type: "刷卡失败",
status: "未处理",
},
{
time: "2023-06-20 18:45:55",
cardNo: "2023425",
location: "超市",
type: "重复消费",
status: "已处理",
},
],
};
},
methods: {
goBack() {
this.$router.push("/");
},
getAbnormalType(type) {
const types = {
重复刷卡: "warning",
余额异常: "danger",
刷卡失败: "info",
重复消费: "warning",
};
return types[type] || "info";
},
getStatusType(status) {
const types = {
已处理: "success",
处理中: "primary",
未处理: "danger",
};
return types[status] || "info";
},
},
};
</script>
<style lang="scss" scoped>
.card-detail {
padding: 20px;
background: #f0f2f5;
min-height: 100vh;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.filters {
display: flex;
gap: 10px;
}
}
.overview-cards {
margin-bottom: 20px;
.overview-card {
.card-content {
text-align: center;
.value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.label {
font-size: 14px;
color: #909399;
margin: 8px 0;
}
.trend {
font-size: 12px;
&.up {
color: #67c23a;
}
&.down {
color: #f56c6c;
}
}
}
}
}
.charts-row {
margin-bottom: 20px;
.chart-card {
height: 400px;
}
}
.table-card {
margin-bottom: 20px;
}
}
</style>

View File

@ -1,235 +0,0 @@
<template>
<div class="education-detail">
<div class="header">
<el-page-header @back="goBack" content="教务详情" />
<div class="filter">
<el-select v-model="selectedYear" placeholder="选择年份">
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
<el-select v-model="selectedSemester" placeholder="选择学期">
<el-option
v-for="item in semesters"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<el-row :gutter="20" class="data-overview">
<el-col :span="8" v-for="(item, index) in overviewData" :key="index">
<el-card shadow="hover">
<div class="data-item">
<div class="icon">
<i :class="item.icon"></i>
</div>
<div class="info">
<div class="value">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-container">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>课程通过率趋势</span>
</div>
<ve-line
:data="passRateData"
:settings="passRateSettings"
height="300px"
/>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>学生评教分布</span>
</div>
<ve-histogram
:data="evaluationData"
:settings="evaluationSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-card class="resource-usage">
<div slot="header">
<span>教学资源使用情况</span>
</div>
<el-table :data="resourceData" style="width: 100%">
<el-table-column prop="name" label="资源名称" />
<el-table-column prop="total" label="总量" />
<el-table-column prop="used" label="已使用" />
<el-table-column prop="usage" label="使用率">
<template slot-scope="scope">
<el-progress
:percentage="scope.row.usage"
:color="getProgressColor(scope.row.usage)"
/>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: "EducationDetail",
data() {
return {
selectedYear: "2024",
selectedSemester: "1",
years: ["2024", "2023", "2022", "2021"],
semesters: [
{ label: "第一学期", value: "1" },
{ label: "第二学期", value: "2" },
],
overviewData: JSON.parse(JSON.stringify([
{ label: "课程总数", value: "1,256", icon: "el-icon-reading" },
{ label: "在线课程数", value: "368", icon: "el-icon-monitor" },
{ label: "授课教师数", value: "526", icon: "el-icon-user" },
])),
passRateData: JSON.parse(JSON.stringify({
columns: ["月份", "通过率"],
rows: [
{ 月份: "1月", 通过率: 92 },
{ 月份: "2月", 通过率: 93 },
{ 月份: "3月", 通过率: 95 },
{ 月份: "4月", 通过率: 94 },
{ 月份: "5月", 通过率: 96 },
{ 月份: "6月", 通过率: 95 },
],
})),
passRateSettings: {
area: true,
yAxisName: ["通过率(%)"],
},
evaluationData: {
columns: ["分数段", "课程数"],
rows: [
{ 分数段: "90-100", 课程数: 320 },
{ 分数段: "80-89", 课程数: 580 },
{ 分数段: "70-79", 课程数: 250 },
{ 分数段: "60-69", 课程数: 80 },
{ 分数段: "60以下", 课程数: 26 },
],
},
evaluationSettings: {
yAxisName: ["课程数量"],
},
resourceData: JSON.parse(JSON.stringify([
{ name: "多媒体教室", total: 120, used: 98, usage: 82 },
{ name: "实验室", total: 45, used: 35, usage: 78 },
{ name: "在线课程平台", total: 368, used: 320, usage: 87 },
{ name: "教学软件", total: 50, used: 42, usage: 84 },
])),
};
},
created() {
this.initializeData();
},
methods: {
initializeData() {
// Add any additional initialization logic here
},
goBack() {
this.$router.push("/");
},
getProgressColor(percentage) {
if (percentage < 60) return "#F56C6C";
if (percentage < 80) return "#E6A23C";
return "#67C23A";
},
handleDataChange(newData) {
this.resourceData = JSON.parse(JSON.stringify(newData.resourceData));
this.passRateData = JSON.parse(JSON.stringify(newData.passRateData));
this.overviewData = JSON.parse(JSON.stringify(newData.overviewData));
},
},
watch: {
selectedYear() {
this.initializeData();
},
selectedSemester() {
this.initializeData();
},
},
};
</script>
<style lang="scss" scoped>
.education-detail {
padding: 20px;
background: #f0f2f5;
min-height: 100vh;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.filter {
display: flex;
gap: 10px;
}
}
.data-overview {
margin-bottom: 20px;
.data-item {
display: flex;
align-items: center;
.icon {
font-size: 48px;
color: #409eff;
margin-right: 20px;
}
.info {
.value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.label {
font-size: 14px;
color: #909399;
margin-top: 5px;
}
}
}
}
.charts-container {
margin-bottom: 20px;
.chart-card {
height: 400px;
}
}
.resource-usage {
.el-progress {
margin-top: 8px;
}
}
}
</style>

View File

@ -1,272 +0,0 @@
<template>
<div class="literature-detail">
<div class="header">
<el-page-header @back="goBack" content="文献详情" />
<div class="filters">
<el-select v-model="selectedYear" placeholder="选择年份">
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
</div>
</div>
<el-row :gutter="20" class="overview-cards">
<el-col :span="6" v-for="(item, index) in overviewData" :key="index">
<el-card shadow="hover" class="overview-card">
<div class="card-content">
<div class="value">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
<div class="trend" :class="item.trend">
{{ item.trendValue }}%
<i
:class="item.trend === 'up' ? 'el-icon-top' : 'el-icon-bottom'"
></i>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>馆藏资源分布</span>
</div>
<ve-pie :data="resourceData" :settings="pieSettings" height="300px" />
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>借阅趋势分析</span>
</div>
<ve-line
:data="borrowingData"
:settings="lineSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>学科分布</span>
</div>
<ve-radar :data="subjectData" height="300px" />
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>数据库访问量</span>
</div>
<ve-histogram
:data="databaseData"
:settings="histogramSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-card class="table-card">
<div slot="header">
<span>热门借阅排行</span>
<el-button style="float: right" type="text">查看全部</el-button>
</div>
<el-table :data="popularBooks" style="width: 100%">
<el-table-column prop="rank" label="排名" width="80" />
<el-table-column prop="name" label="书名" />
<el-table-column prop="author" label="作者" width="150" />
<el-table-column prop="category" label="分类" width="120" />
<el-table-column prop="borrowCount" label="借阅次数" width="120" />
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: "LiteratureDetail",
data() {
return {
selectedYear: "2024",
years: ["2024", "2023", "2022", "2021"],
overviewData: [
{ label: "馆藏总量", value: "1,256,890", trend: "up", trendValue: 5 },
{ label: "电子资源量", value: "856,230", trend: "up", trendValue: 12 },
{ label: "年度借阅量", value: "286,530", trend: "up", trendValue: 8 },
{ label: "数据库数量", value: "168", trend: "up", trendValue: 3 },
],
resourceData: {
columns: ["类型", "数量"],
rows: [
{ 类型: "纸质图书", 数量: 580000 },
{ 类型: "电子图书", 数量: 420000 },
{ 类型: "期刊", 数量: 156000 },
{ 类型: "学位论文", 数量: 85000 },
{ 类型: "其他资源", 数量: 15890 },
],
},
pieSettings: {
radius: "65%",
offsetY: "60%",
},
borrowingData: {
columns: ["月份", "纸质借阅", "电子访问"],
rows: [
{ 月份: "1月", 纸质借阅: 15000, 电子访问: 45000 },
{ 月份: "2月", 纸质借阅: 18000, 电子访问: 52000 },
{ 月份: "3月", 纸质借阅: 22000, 电子访问: 58000 },
{ 月份: "4月", 纸质借阅: 25000, 电子访问: 65000 },
{ 月份: "5月", 纸质借阅: 28000, 电子访问: 72000 },
{ 月份: "6月", 纸质借阅: 30000, 电子访问: 78000 },
],
},
lineSettings: {
area: true,
},
subjectData: {
columns: ["学科", "藏书量"],
rows: [
{ 学科: "理学", 藏书量: 250000 },
{ 学科: "工学", 藏书量: 320000 },
{ 学科: "文学", 藏书量: 180000 },
{ 学科: "经管", 藏书量: 150000 },
{ 学科: "医学", 藏书量: 120000 },
{ 学科: "其他", 藏书量: 80000 },
],
},
databaseData: {
columns: ["数据库", "访问量"],
rows: [
{ 数据库: "CNKI", 访问量: 85000 },
{ 数据库: "Web of Science", 访问量: 52000 },
{ 数据库: "ScienceDirect", 访问量: 48000 },
{ 数据库: "Springer", 访问量: 35000 },
{ 数据库: "IEEE", 访问量: 32000 },
],
},
histogramSettings: {
metrics: ["访问量"],
},
popularBooks: [
{
rank: 1,
name: "人工智能导论",
author: "李明",
category: "计算机",
borrowCount: 256,
status: "可借",
},
{
rank: 2,
name: "高等数学",
author: "张三",
category: "数学",
borrowCount: 235,
status: "已借出",
},
{
rank: 3,
name: "经济学原理",
author: "王五",
category: "经济",
borrowCount: 198,
status: "可借",
},
{
rank: 4,
name: "大学物理",
author: "刘六",
category: "物理",
borrowCount: 186,
status: "已借出",
},
],
};
},
methods: {
goBack() {
this.$router.push("/");
},
getStatusType(status) {
return status === "可借" ? "success" : "warning";
},
},
};
</script>
<style lang="scss" scoped>
.literature-detail {
padding: 20px;
background: #f0f2f5;
min-height: 100vh;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.overview-cards {
margin-bottom: 20px;
.overview-card {
.card-content {
text-align: center;
.value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.label {
font-size: 14px;
color: #909399;
margin: 8px 0;
}
.trend {
font-size: 12px;
&.up {
color: #67c23a;
}
&.down {
color: #f56c6c;
}
}
}
}
}
.charts-row {
margin-bottom: 20px;
.chart-card {
height: 400px;
}
}
.table-card {
margin-bottom: 20px;
}
}
</style>

View File

@ -1,228 +0,0 @@
<template>
<div class="research-detail">
<div class="header">
<el-page-header @back="goBack" content="科研详情" />
<el-select v-model="selectedYear" placeholder="选择年份">
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
</div>
<el-row :gutter="20" class="statistics">
<el-col :span="6" v-for="(item, index) in statisticsData" :key="index">
<el-card shadow="hover" class="stat-card">
<div class="stat-content">
<div class="value">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
<div class="trend" :class="item.trend">
{{ item.trendValue }}%
<i
:class="item.trend === 'up' ? 'el-icon-top' : 'el-icon-bottom'"
></i>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>项目经费分布</span>
</div>
<ve-pie :data="fundingData" :settings="pieSettings" height="300px" />
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>成果发表趋势</span>
</div>
<ve-line
:data="publicationData"
:settings="lineSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-card class="project-list">
<div slot="header">
<span>重点项目进展</span>
<el-button style="float: right" type="text">查看全部</el-button>
</div>
<el-table :data="projectData" style="width: 100%">
<el-table-column prop="name" label="项目名称" />
<el-table-column prop="leader" label="负责人" width="120" />
<el-table-column prop="funding" label="经费(万)" width="120" />
<el-table-column prop="status" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="progress" label="进度" width="180">
<template slot-scope="scope">
<el-progress :percentage="scope.row.progress" />
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: "ResearchDetail",
data() {
return {
selectedYear: "2024",
years: ["2024", "2023", "2022", "2021"],
statisticsData: [
{ label: "项目总数", value: "186", trend: "up", trendValue: 15 },
{ label: "发表论文", value: "253", trend: "up", trendValue: 8 },
{ label: "授权专利", value: "68", trend: "up", trendValue: 12 },
{ label: "科研经费(万)", value: "2,860", trend: "up", trendValue: 20 },
],
fundingData: {
columns: ["类型", "金额"],
rows: [
{ 类型: "国家级", 金额: 1200 },
{ 类型: "省部级", 金额: 800 },
{ 类型: "横向项目", 金额: 600 },
{ 类型: "其他", 金额: 260 },
],
},
pieSettings: {
radius: "65%",
offsetY: "60%",
},
publicationData: {
columns: ["月份", "SCI论文", "EI论文", "核心期刊"],
rows: [
{ 月份: "1月", SCI论文: 8, EI论文: 12, 核心期刊: 15 },
{ 月份: "2月", SCI论文: 10, EI论文: 15, 核心期刊: 18 },
{ 月份: "3月", SCI论文: 12, EI论文: 18, 核心期刊: 20 },
{ 月份: "4月", SCI论文: 15, EI论文: 20, 核心期刊: 25 },
{ 月份: "5月", SCI论文: 18, EI论文: 23, 核心期刊: 28 },
{ 月份: "6月", SCI论文: 20, EI论文: 25, 核心期刊: 30 },
],
},
lineSettings: {
stack: { 类型: ["SCI论文", "EI论文", "核心期刊"] },
},
projectData: [
{
name: "人工智能基础理论研究",
leader: "张三",
funding: 500,
status: "进行中",
progress: 65,
},
{
name: "新能源材料开发",
leader: "李四",
funding: 300,
status: "已完成",
progress: 100,
},
{
name: "智慧校园建设",
leader: "王五",
funding: 200,
status: "待启动",
progress: 0,
},
{
name: "生物医药研发",
leader: "赵六",
funding: 400,
status: "进行中",
progress: 45,
},
],
};
},
methods: {
goBack() {
this.$router.push("/");
},
getStatusType(status) {
const types = {
进行中: "primary",
已完成: "success",
待启动: "info",
};
return types[status] || "info";
},
},
};
</script>
<style lang="scss" scoped>
.research-detail {
padding: 20px;
background: #f0f2f5;
min-height: 100vh;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.statistics {
margin-bottom: 20px;
.stat-card {
.stat-content {
text-align: center;
.value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.label {
font-size: 14px;
color: #909399;
margin: 8px 0;
}
.trend {
font-size: 12px;
&.up {
color: #67c23a;
}
&.down {
color: #f56c6c;
}
}
}
}
}
.charts {
margin-bottom: 20px;
.chart-card {
height: 400px;
}
}
.project-list {
.el-table {
margin-top: 15px;
}
}
}
</style>

View File

@ -1,274 +0,0 @@
<template>
<div class="staff-detail">
<div class="header">
<el-page-header @back="goBack" content="教职工详情" />
<div class="filters">
<el-select v-model="selectedYear" placeholder="选择年份">
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
</div>
</div>
<el-row :gutter="20" class="overview-cards">
<el-col :span="6" v-for="(item, index) in overviewData" :key="index">
<el-card shadow="hover" class="overview-card">
<div class="card-content">
<div class="value">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
<div class="trend" :class="item.trend">
{{ item.trendValue }}%
<i
:class="item.trend === 'up' ? 'el-icon-top' : 'el-icon-bottom'"
></i>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>职称分布</span>
</div>
<ve-pie :data="titleData" :settings="pieSettings" height="300px" />
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>学历结构</span>
</div>
<ve-ring
:data="educationData"
:settings="ringSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>人员变动趋势</span>
</div>
<ve-line
:data="staffChangeData"
:settings="lineSettings"
height="300px"
/>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>绩效考核分布</span>
</div>
<ve-histogram :data="performanceData" height="300px" />
</el-card>
</el-col>
</el-row>
<el-card class="table-card">
<div slot="header">
<span>招聘进度</span>
</div>
<el-table :data="recruitmentData" style="width: 100%">
<el-table-column prop="position" label="岗位" />
<el-table-column prop="department" label="部门" />
<el-table-column prop="candidates" label="应聘人数" width="100" />
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="progress" label="进度" width="180">
<template slot-scope="scope">
<el-progress :percentage="scope.row.progress" />
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: "StaffDetail",
data() {
return {
selectedYear: "2024",
years: ["2024", "2023", "2022", "2021"],
overviewData: [
{ label: "教职工总数", value: "1,256", trend: "up", trendValue: 5 },
{ label: "新入职人数", value: "86", trend: "up", trendValue: 15 },
{ label: "离职人数", value: "32", trend: "down", trendValue: 8 },
{ label: "在招岗位", value: "25", trend: "up", trendValue: 20 },
],
titleData: {
columns: ["职称", "人数"],
rows: [
{ 职称: "正高级", 人数: 180 },
{ 职称: "副高级", 人数: 320 },
{ 职称: "中级", 人数: 450 },
{ 职称: "初级", 人数: 306 },
],
},
pieSettings: {
radius: "65%",
offsetY: "60%",
},
educationData: {
columns: ["学历", "人数"],
rows: [
{ 学历: "博士", 人数: 420 },
{ 学历: "硕士", 人数: 580 },
{ 学历: "本科", 人数: 236 },
{ 学历: "其他", 人数: 20 },
],
},
ringSettings: {
radius: ["40%", "65%"],
offsetY: "60%",
},
staffChangeData: {
columns: ["月份", "入职人数", "离职人数"],
rows: [
{ 月份: "1月", 入职人数: 15, 离职人数: 5 },
{ 月份: "2月", 入职人数: 12, 离职人数: 4 },
{ 月份: "3月", 入职人数: 18, 离职人数: 6 },
{ 月份: "4月", 入职人数: 20, 离职人数: 8 },
{ 月份: "5月", 入职人数: 16, 离职人数: 5 },
{ 月份: "6月", 入职人数: 14, 离职人数: 4 },
],
},
lineSettings: {
area: true,
},
performanceData: {
columns: ["等级", "人数"],
rows: [
{ 等级: "A", 人数: 320 },
{ 等级: "B", 人数: 520 },
{ 等级: "C", 人数: 280 },
{ 等级: "D", 人数: 120 },
{ 等级: "E", 人数: 16 },
],
},
recruitmentData: [
{
position: "教授",
department: "计算机学院",
candidates: 25,
status: "面试中",
progress: 60,
},
{
position: "副教授",
department: "经管学院",
candidates: 18,
status: "筛选中",
progress: 30,
},
{
position: "讲师",
department: "外语学院",
candidates: 35,
status: "已完成",
progress: 100,
},
{
position: "实验员",
department: "物理学院",
candidates: 12,
status: "待面试",
progress: 20,
},
],
};
},
methods: {
goBack() {
this.$router.push("/");
},
getStatusType(status) {
const types = {
面试中: "primary",
筛选中: "warning",
已完成: "success",
待面试: "info",
};
return types[status] || "info";
},
},
};
</script>
<style lang="scss" scoped>
.staff-detail {
padding: 20px;
background: #f0f2f5;
min-height: 100vh;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.overview-cards {
margin-bottom: 20px;
.overview-card {
.card-content {
text-align: center;
.value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.label {
font-size: 14px;
color: #909399;
margin: 8px 0;
}
.trend {
font-size: 12px;
&.up {
color: #67c23a;
}
&.down {
color: #f56c6c;
}
}
}
}
}
.charts-row {
margin-bottom: 20px;
.chart-card {
height: 400px;
}
}
.table-card {
margin-bottom: 20px;
}
}
</style>

View File

@ -1,262 +0,0 @@
<template>
<div class="student-detail">
<div class="header">
<el-page-header @back="goBack" content="学生详情" />
<div class="filters">
<el-select v-model="selectedYear" placeholder="选择年份">
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
</div>
</div>
<el-row :gutter="20" class="overview-cards">
<el-col :span="8" v-for="(item, index) in overviewData" :key="index">
<el-card shadow="hover" class="overview-card">
<div class="card-content">
<i :class="item.icon"></i>
<div class="info">
<div class="value">{{ item.value }}</div>
<div class="label">{{ item.label }}</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>各年级学生分布</span>
</div>
<ve-pie :data="gradeData" :settings="pieSettings" height="300px" />
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>学生活动参与情况</span>
</div>
<ve-histogram
:data="activityData"
:settings="histogramSettings"
height="300px"
/>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" class="charts-row">
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>心理咨询预约趋势</span>
</div>
<ve-line
:data="counselingData"
:settings="lineSettings"
height="300px"
/>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="chart-card">
<div slot="header">
<span>社团活动分布</span>
</div>
<ve-radar :data="clubData" height="300px" />
</el-card>
</el-col>
</el-row>
<el-card class="table-card">
<div slot="header">
<span>学生活动记录</span>
<el-button style="float: right" type="text">查看全部</el-button>
</div>
<el-table :data="activityRecords" style="width: 100%">
<el-table-column prop="name" label="活动名称" />
<el-table-column prop="type" label="类型" width="120" />
<el-table-column prop="date" label="日期" width="120" />
<el-table-column prop="participants" label="参与人数" width="120" />
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: "StudentDetail",
data() {
return {
selectedYear: "2024",
years: ["2024", "2023", "2022", "2021"],
overviewData: [
{ label: "在校生总数", value: "25,368", icon: "el-icon-user" },
{ label: "参与社团人数", value: "15,623", icon: "el-icon-connection" },
{ label: "志愿服务时长", value: "125,890h", icon: "el-icon-time" },
],
gradeData: {
columns: ["年级", "人数"],
rows: [
{ 年级: "大一", 人数: 6500 },
{ 年级: "大二", 人数: 6200 },
{ 年级: "大三", 人数: 5800 },
{ 年级: "大四", 人数: 5400 },
{ 年级: "研究生", 人数: 1468 },
],
},
pieSettings: {
radius: "65%",
offsetY: "60%",
},
activityData: {
columns: ["月份", "文体活动", "学术活动", "志愿服务"],
rows: [
{ 月份: "1月", 文体活动: 20, 学术活动: 15, 志愿服务: 25 },
{ 月份: "2月", 文体活动: 25, 学术活动: 20, 志愿服务: 30 },
{ 月份: "3月", 文体活动: 35, 学术活动: 25, 志愿服务: 35 },
{ 月份: "4月", 文体活动: 45, 学术活动: 30, 志愿服务: 40 },
{ 月份: "5月", 文体活动: 50, 学术活动: 35, 志愿服务: 45 },
{ 月份: "6月", 文体活动: 40, 学术活动: 30, 志愿服务: 35 },
],
},
histogramSettings: {
stack: { 类型: ["文体活动", "学术活动", "志愿服务"] },
},
counselingData: {
columns: ["月份", "预约人次", "实际咨询"],
rows: [
{ 月份: "1月", 预约人次: 120, 实际咨询: 100 },
{ 月份: "2月", 预约人次: 140, 实际咨询: 115 },
{ 月份: "3月", 预约人次: 160, 实际咨询: 130 },
{ 月份: "4月", 预约人次: 180, 实际咨询: 150 },
{ 月份: "5月", 预约人次: 200, 实际咨询: 170 },
{ 月份: "6月", 预约人次: 220, 实际咨询: 190 },
],
},
lineSettings: {
area: true,
},
clubData: {
columns: ["类型", "人数"],
rows: [
{ 类型: "文学社", 人数: 2500 },
{ 类型: "体育类", 人数: 3500 },
{ 类型: "科技类", 人数: 3000 },
{ 类型: "艺术类", 人数: 2800 },
{ 类型: "公益类", 人数: 2600 },
],
},
activityRecords: [
{
name: "校园文化节",
type: "文化活动",
date: "2023-05-20",
participants: 1200,
status: "已完成",
},
{
name: "科技创新大赛",
type: "学术活动",
date: "2023-05-15",
participants: 500,
status: "进行中",
},
{
name: "志愿者服务日",
type: "志愿活动",
date: "2023-05-10",
participants: 800,
status: "已完成",
},
{
name: "心理健康讲座",
type: "讲座活动",
date: "2023-05-05",
participants: 300,
status: "已完成",
},
],
};
},
methods: {
goBack() {
this.$router.push("/");
},
getStatusType(status) {
return status === "进行中" ? "primary" : "success";
},
},
};
</script>
<style lang="scss" scoped>
.student-detail {
padding: 20px;
background: #f0f2f5;
min-height: 100vh;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.overview-cards {
margin-bottom: 20px;
.overview-card {
.card-content {
display: flex;
align-items: center;
i {
font-size: 48px;
color: #409eff;
margin-right: 20px;
}
.info {
.value {
font-size: 24px;
font-weight: bold;
color: #303133;
}
.label {
font-size: 14px;
color: #909399;
margin-top: 5px;
}
}
}
}
}
.charts-row {
margin-bottom: 20px;
.chart-card {
height: 400px;
}
}
.table-card {
margin-bottom: 20px;
}
}
</style>

View File

@ -3,209 +3,82 @@
<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="decorationColor" />
<div class="title">
<div class="title-part">
<img src="@/assets/logo.png" alt="icon" class="logo" />
<span class="title-text">智慧校园</span>
</div>
<dv-decoration-6
class="dv-dec-6"
:reverse="true"
:color="['#50e3c2', '#67a1e5']"
/>
<span class="title-text">唐山师范学校数据中台</span>
<dv-decoration-6 class="dv-dec-6" :reverse="true" :color="['#50e3c2', '#67a1e5']" />
</div>
<dv-decoration-8
class="dv-dec-8"
:reverse="true"
:color="decorationColor"
/>
<dv-decoration-8 class="dv-dec-8" :reverse="true" :color="decorationColor" />
</div>
<dv-decoration-10 class="dv-dec-10-s" />
</div>
<!-- 学校概况信息卡片 -->
<div class="school-info-cards">
<div class="info-card">
<i class="el-icon-school"></i>
<div class="info-content">
<div class="main-info">
<div class="info-label">在校生总数</div>
<div class="info-value">
{{ formatNumber(schoolData.totalStudents) }}<b></b>
</div>
</div>
<div class="sub-info-container">
<div class="sub-info">
本科生 {{ formatNumber(schoolData.undergrads) }}
</div>
<div class="sub-info">
研究生 {{ formatNumber(schoolData.graduates) }}
</div>
</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-left"></span>
<span class="text">数据分析1</span>
</div>
<div class="react-left ml-3">
<span class="text">数据分析2</span>
</div>
</div>
<div class="info-card">
<i class="el-icon-user"></i>
<div class="info-content">
<div class="main-info">
<div class="info-label">教职工总数</div>
<div class="info-value">
{{ formatNumber(schoolData.totalStaff) }}<b></b>
</div>
</div>
<div class="sub-info-container">
<div class="sub-info">
专任教师 {{ formatNumber(schoolData.teachers) }}
</div>
<div class="sub-info">
博士学位 {{ formatNumber(schoolData.doctors) }}
</div>
</div>
<div class="d-flex aside-width">
<div class="react-right bg-color-blue mr-3">
<span class="text">数据分析1</span>
</div>
</div>
<div class="info-card">
<i class="el-icon-notebook-2"></i>
<div class="info-content">
<div class="main-info">
<div class="info-label">本科专业数</div>
<div class="info-value">{{ schoolData.majors }}<b></b></div>
</div>
<div class="sub-info-container">
<div class="sub-info">
硕士点 {{ schoolData.masterPrograms }}
</div>
<div class="sub-info">
重点学科 {{ schoolData.keyDisciplines }}
</div>
</div>
</div>
</div>
<div class="info-card">
<i class="el-icon-office-building"></i>
<div class="info-content">
<div class="main-info">
<div class="info-label">校园面积</div>
<div class="info-value">
{{ formatNumber(schoolData.campusArea) }}<b></b>
</div>
</div>
<div class="sub-info-container">
<div class="sub-info">
建筑 {{ schoolData.buildingArea }}
</div>
<div class="sub-info">实验室 {{ schoolData.labs }}</div>
</div>
</div>
</div>
<div class="info-card">
<i class="el-icon-reading"></i>
<div class="info-content">
<div class="main-info">
<div class="info-label">图书馆藏</div>
<div class="info-value">{{ schoolData.books }}<b>万册</b></div>
</div>
<div class="sub-info-container">
<div class="sub-info">电子图书 {{ schoolData.ebooks }}万册</div>
<div class="sub-info">期刊 {{ schoolData.journals }}</div>
</div>
</div>
</div>
<div class="info-card">
<i class="el-icon-connection"></i>
<div class="info-content">
<div class="main-info">
<div class="info-label">国际合作</div>
<div class="info-value">
{{ formatNumber(schoolData.partnerships) }}<b></b>
</div>
</div>
<div class="sub-info-container">
<div class="sub-info">
留学生 {{ formatNumber(schoolData.internationalStudents) }}
</div>
<div class="sub-info">
交换生 {{ formatNumber(schoolData.exchangeStudents) }}/
</div>
</div>
<div class="react-right mr-4 react-l-s">
<span class="react-after"></span>
<span class="text">{{ dateYear }} {{ dateWeek }} {{ dateDay }}</span>
</div>
</div>
</div>
<div class="dashboard-container">
<div class="left-panel">
<!-- 科研概况 -->
<common-header
title="科研概况"
@click-more="(title) => getRouterByTitle('科研概况')"
/>
<div class="panel-item">
<research-overview />
<div class="body-box">
<!-- 第三行数据 -->
<div class="content-box">
<div>
<dv-border-box-12>
<centerLeft1 />
</dv-border-box-12>
</div>
<!-- 教职工概况 -->
<common-header
title="教职工概况"
@click-more="(title) => getRouterByTitle('教职工概况')"
/>
<div class="panel-item">
<staff-overview />
<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>
<centerRight2 />
</div>
<div>
<dv-border-box-13>
<centerRight1 />
</dv-border-box-13>
</div>
</div>
<!-- 中间面板 -->
<div class="center-panel">
<div class="center-top">
<img
src="../assets/school.png"
alt="校园图片"
class="school-image"
/>
</div>
<div class="center-bottom">
<!-- 教务概况 -->
<div class="bottom-item">
<common-header
title="教务概况"
@click-more="(title) => getRouterByTitle('教务概况')"
/>
<div class="panel-item">
<education-overview />
</div>
</div>
<!-- 资产概况 -->
<div class="bottom-item">
<common-header
title="资产概况"
@click-more="(title) => getRouterByTitle('资产概况')"
/>
<div class="panel-item">
<asset-overview />
</div>
</div>
</div>
</div>
<div class="right-panel">
<!-- 一卡通概况 -->
<common-header
title="一卡通概况"
@click-more="(title) => getRouterByTitle('一卡通概况')"
/>
<div class="panel-item">
<card-overview />
</div>
<!-- 文献概况 -->
<common-header
title="文献概况"
@click-more="(title) => getRouterByTitle('文献概况')"
/>
<div class="panel-item">
<literature-overview />
</div>
<!-- 第四行数据 -->
<div class="bottom-box">
<dv-border-box-13>
<bottomLeft />
</dv-border-box-13>
<dv-border-box-12>
<bottomRight />
</dv-border-box-12>
</div>
</div>
</div>
@ -214,358 +87,62 @@
</template>
<script>
import { formatNumber } from "@/utils/format";
import drawMixin from "../utils/drawMixin";
import CommonHeader from "@/components/CommonHeader";
import EducationOverview from "@/components/EducationOverview";
import ResearchOverview from "@/components/ResearchOverview";
import StaffOverview from "@/components/StaffOverview";
import AssetOverview from "@/components/AssetOverview";
import LiteratureOverview from "@/components/LiteratureOverview";
import CardOverview from "@/components/CardOverview";
import { formatTime } from "../utils/index.js";
import centerLeft1 from "./centerLeft1";
// import centerLeft2 from "./centerLeft2";
import centerRight1 from "./centerRight1";
import centerRight2 from "./centerRight2";
import center from "./center";
import bottomLeft from "./bottomLeft";
import bottomRight from "./bottomRight";
export default {
mixins: [drawMixin],
data() {
return {
timing: null,
loading: true,
decorationColor: ["#568aea", "#000000"],
schoolData: {
totalStudents: 18000,
undergrads: 16000,
graduates: 500,
internationalStudents: 100,
exchangeStudents: 100,
totalStaff: 1200,
teachers: 900,
doctors: 300,
majors: 60,
masterPrograms: 10,
keyDisciplines: 4,
campusArea: 1000,
buildingArea: 50,
labs: 100,
books: 200,
ebooks: 300,
journals: 2000,
partnerships: 50,
},
routerMap: {
科研概况: "/research-detail",
教务概况: "/education-detail",
教职工概况: "/staff-detail",
资产概况: "/asset-detail",
文献概况: "/literature-detail",
一卡通概况: "/card-detail",
},
dateDay: null,
dateYear: null,
dateWeek: null,
weekday: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
decorationColor: ["#568aea", "#000000"]
};
},
components: {
CommonHeader,
EducationOverview,
ResearchOverview,
StaffOverview,
AssetOverview,
LiteratureOverview,
CardOverview,
centerLeft1,
// centerLeft2,
centerRight1,
centerRight2,
center,
bottomLeft,
bottomRight
},
mounted() {
this.timeFn();
this.cancelLoading();
},
beforeDestroy() {
clearInterval(this.timing);
},
methods: {
timeFn() {
this.timing = setInterval(() => {
this.dateDay = formatTime(new Date(), "HH: mm: ss");
this.dateYear = formatTime(new Date(), "yyyy-MM-dd");
this.dateWeek = this.weekday[new Date().getDay()];
}, 1000);
},
cancelLoading() {
setTimeout(() => {
this.loading = false;
}, 500);
},
getRouterByTitle(title) {
const path = this.routerMap[title];
if (path) {
this.$router.push(path);
}
},
formatNumber,
},
}
}
};
</script>
<style lang="scss" scoped>
@import "../assets/scss/index.scss";
.title {
position: relative;
padding: 0 50px;
margin-bottom: 10px;
.title-text {
font-size: 36px;
font-weight: bold;
background: linear-gradient(to top, #4a90e2, #ffffff);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
// text-shadow: 0 0 10px rgba(74, 144, 226, 0.3);
font-family: "Microsoft YaHei", sans-serif;
}
}
.school-info-cards {
display: flex;
justify-content: space-between;
margin: 10px 20px;
background: rgba(74, 144, 226, 0.05);
border-radius: 15px;
backdrop-filter: blur(5px);
position: relative;
border: 1px solid rgba(74, 144, 226, 0.1);
overflow: hidden;
box-shadow: 0 0 20px rgba(74, 144, 226, 0.05);
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent 0%,
rgba(74, 144, 226, 0.5) 50%,
transparent 100%
);
}
&::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent 0%,
rgba(74, 144, 226, 0.3) 50%,
transparent 100%
);
}
.info-card {
flex: 1;
display: flex;
align-items: flex-start;
gap: 15px;
padding: 20px 10px;
position: relative;
transition: all 0.3s ease;
min-width: 240px;
&:not(:last-child)::after {
content: "";
position: absolute;
right: 0;
top: 15%;
height: 70%;
width: 1px;
background: linear-gradient(
to bottom,
transparent 0%,
rgba(74, 144, 226, 0.15) 50%,
transparent 100%
);
}
&:hover {
transform: translateY(-5px);
background: rgba(74, 144, 226, 0.08);
border-radius: 12px;
box-shadow: 0 5px 15px rgba(74, 144, 226, 0.1);
i {
transform: scale(1.1) translateY(-2px);
background: linear-gradient(135deg, #4a90e2, #36d1dc);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
filter: drop-shadow(0 2px 4px rgba(74, 144, 226, 0.2));
}
.info-content {
.main-info {
.info-value {
transform: scale(1.05);
filter: drop-shadow(0 2px 4px rgba(74, 144, 226, 0.3));
}
}
.sub-info-container {
.sub-info {
color: rgba(74, 144, 226, 0.9);
transform: translateX(-5px);
}
}
}
}
i {
font-size: 40px;
color: #4a90e2;
transition: all 0.3s ease;
margin-top: 20px;
opacity: 0.9;
filter: drop-shadow(0 2px 2px rgba(74, 144, 226, 0.1));
}
.info-content {
flex: 1;
display: flex;
justify-content: space-between;
gap: 10px;
.main-info {
flex: 1;
margin: 0 -5px;
.info-label {
color: rgba(255, 255, 255, 0.9);
font-size: 18px;
margin-bottom: 10px;
font-weight: 500;
}
.info-value {
font-size: 34px;
font-weight: bold;
transition: all 0.3s ease;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
b {
font-size: 16px;
font-weight: normal;
// margin-left: 4px;
}
}
}
.sub-info-container {
display: flex;
flex-direction: column;
justify-content: center;
gap: 8px;
padding-left: 15px;
position: relative;
min-width: 100px;
&::before {
content: "";
position: absolute;
left: 0;
top: 10%;
height: 80%;
width: 1px;
background: linear-gradient(
to bottom,
transparent,
rgba(74, 144, 226, 0.1),
transparent
);
}
.sub-info {
color: rgba(255, 255, 255, 0.7);
font-size: 13px;
transition: all 0.3s ease;
text-align: left;
white-space: nowrap;
&:hover {
color: rgba(74, 144, 226, 0.9);
transform: translateX(5px);
}
}
}
}
}
}
.dashboard-container {
display: flex;
width: 100%;
height: calc(95% - 150px);
padding: 0 20px 20px;
gap: 20px;
overflow-y: auto;
&::-webkit-scrollbar {
width: 0;
background: transparent;
}
.left-panel,
.right-panel {
flex: 1;
display: flex;
flex-direction: column;
gap: 20px;
height: 100%;
.panel-item {
flex: 1;
min-height: 0;
background: rgba(255, 255, 255, 0.05);
padding: 15px;
display: flex;
flex-direction: column;
border-radius: 12px;
}
}
.center-panel {
flex: 2;
display: flex;
flex-direction: column;
gap: 20px;
height: 100%;
.center-top {
flex: 3;
display: flex;
align-items: center;
justify-content: center;
.school-image {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 12px;
}
}
.center-bottom {
flex: 2;
display: flex;
gap: 20px;
.bottom-item {
flex: 1;
display: flex;
flex-direction: column;
gap: 20px;
.panel-item {
flex: 1;
min-height: 0;
background: rgba(255, 255, 255, 0.05);
padding: 0 15px;
display: flex;
flex-direction: column;
border-radius: 12px;
}
}
}
}
}
</style>
</style>

1
src/views/test.vue Normal file
View File

@ -0,0 +1 @@
test

8773
yarn.lock

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.