refactor: 🎨 优化首页前端页面样式

pull/95/head
李强 2023-04-21 00:28:11 +08:00
parent 08aba985b8
commit 5ff92536e4
24 changed files with 1546 additions and 979 deletions

View File

@ -5,5 +5,5 @@ VUE_APP_TITLE=企业级后台管理系统
# 启用权限管理 # 启用权限管理
VUE_APP_PM_ENABLED = true VUE_APP_PM_ENABLED = true
# 后端接口地址及端口(域名) # 后端接口地址及端口(域名)
VUE_APP_API = "http://192.168.1.22:8001/" VUE_APP_API = "http://127.0.0.1:8000"

View File

@ -1,6 +1,6 @@
{ {
"name": "django-vue-admin", "name": "django-vue-admin",
"version": "2.1.2", "version": "2.1.3",
"scripts": { "scripts": {
"serve": "vue-cli-service serve --open", "serve": "vue-cli-service serve --open",
"start": "npm run serve", "start": "npm run serve",
@ -40,7 +40,9 @@
"screenfull": "^5.0.2", "screenfull": "^5.0.2",
"sortablejs": "^1.10.1", "sortablejs": "^1.10.1",
"ua-parser-js": "^0.7.20", "ua-parser-js": "^0.7.20",
"viser-vue": "^2.4.8",
"vue": "2.7.14", "vue": "2.7.14",
"vue-echarts": "^6.5.4",
"vue-grid-layout": "^2.4.0", "vue-grid-layout": "^2.4.0",
"vue-i18n": "^8.15.1", "vue-i18n": "^8.15.1",
"vue-infinite-scroll": "^2.0.2", "vue-infinite-scroll": "^2.0.2",

View File

@ -36,15 +36,15 @@ import md5 from 'js-md5'
import websocket from '@/api/websocket' import websocket from '@/api/websocket'
import util from '@/libs/util' import util from '@/libs/util'
//引入echarts // 引入echarts
import * as echarts from "echarts" import * as echarts from 'echarts' // 注册echarts组件
// 核心插件 // 核心插件
Vue.use(d2Admin) Vue.use(d2Admin)
Vue.use(VXETable) Vue.use(VXETable)
Vue.prototype.$md5 = md5 Vue.prototype.$md5 = md5
Vue.prototype.$util = util Vue.prototype.$util = util
Vue.prototype.$websocket = websocket Vue.prototype.$websocket = websocket
Vue.prototype.$echarts = echarts //注册echarts组件 Vue.prototype.$echarts = echarts
new Vue({ new Vue({
router, router,
store, store,

View File

@ -1,6 +1,6 @@
<template> <template>
<el-card shadow="hover" header="关于项目" class="card-view" :style="{backgroundColor:randomColor()}"> <el-card shadow="hover" :header="config?.showHeader?.value ? '关于项目' : ''" class="card-view" :style="{backgroundColor:randomColor(),color: config?.fontColor?.value}">
<p>基于RBAC模型的权限控制的一整套基础开发平台前后端分离后端采用 django+django-rest-framework前端采用 <p :style="{color: config?.fontColor?.value}">基于RBAC模型的权限控制的一整套基础开发平台前后端分离后端采用 django+django-rest-framework前端采用
vue+ElementUI+d2-crud-plus如果喜欢就点个星星支持一下 vue+ElementUI+d2-crud-plus如果喜欢就点个星星支持一下
<a href='https://gitee.com/liqianglog/django-vue-admin'> <a href='https://gitee.com/liqianglog/django-vue-admin'>
<img src='https://gitee.com/liqianglog/django-vue-admin/badge/star.svg?theme=dark' alt='star' <img src='https://gitee.com/liqianglog/django-vue-admin/badge/star.svg?theme=dark' alt='star'
@ -12,20 +12,32 @@
<script> <script>
export default { export default {
sort: 9,
title: '关于项目', title: '关于项目',
name: 'about',
icon: 'el-icon-setting', icon: 'el-icon-setting',
description: '点个星星支持一下', description: '点个星星支持一下',
height: 20, height: 20,
width: 8, width: 16,
minH: 10,
minW: 2,
isResizable: true, isResizable: true,
config: { config: {
showHeader: {
label: '显示头部信息',
type: 'boot',
value: true,
placeholder: '颜色为空则随机变换颜色'
},
color: { color: {
label: '背景颜色', label: '背景颜色',
type: 'color', type: 'color',
value: '', value: '',
placeholder: '颜色为空则随机变换颜色' placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
} }
}, },
props: { props: {

View File

@ -1,111 +0,0 @@
<template>
<el-card
class="card-view"
:style="{ backgroundColor: randomColor() }"
shadow="always"
>
<div>
<el-row type="flex" justify="space-around">
<el-col :span="12">
<div class="card-content-label">附件统计</div>
<div class="card-content">
<div class="card-content-value">{{ count}}</div>
<div class="el-icon-document-copy">
附件数量</div>
</div>
</el-col>
<el-col :span="12" :offset="6" style="text-align: right">
<i class="real-time">实时</i>
<div class="card-content-time">
<div class="attachment-value">{{ occupy_space }}MB</div>
<div class="el-icon-s-flag">
附件大小</div>
</div>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
import { request } from "@/api/service";
export default {
title: "附件统计图",
icon: "el-icon-s-order",
description: "总附件数",
name: "attachment",
height: 14,
width: 8,
minH: 14,
minW: 8,
isResizable: true,
data() {
return {
count:"",
occupy_space:"",
};
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res)=>{
this.count=res.data.sum_file.count;
this.occupy_space=res.data.sum_file.occupy_space;
;
})
},
//
randomColor() {
const color = ["#50A8F4FF", "#FD6165FF", "#E679D8FF", "#F9AB5BFF"];
const ran = Math.floor(Math.random() * 4);
return color[ran];
},
},
mounted() {
this.initGet();
},
};
</script>
<style scoped lang="scss">
.card-view {
border-radius: 10px;
color: #ffffff;
.card-content {
.card-content-label {
font-size: 0.8em;
color: #ffffff;
}
.card-content-value {
color: #ffffff;
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
}
}
.attachment-value {
color: #ffffff;
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
margin-right: 180px;
}
.el-icon-document-copy {
font-size: 12px;
}
.el-icon-s-flag {
font-size: 12px;
margin-right: 130px;
}
}
.real-time {
background: rgb(53, 59, 86);
font-size: 14px;
font-style: normal;
padding: 0 7px 0 7px;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<el-card
class="card-view"
:style="{ backgroundColor: randomColor() }"
shadow="always"
>
<div :style="{color: config?.fontColor?.value}">
<div>
<div class="card-content-label">附件统计</div>
<i class="real-time">实时</i>
</div>
<div class="absolute-left">
<div class="card-content">
<div class="card-content-value">{{ count }}</div>
<div class="el-icon-document-copy">
附件数量
</div>
</div>
</div>
<div class="absolute-right">
<div class="card-content-time">
<div class="attachment-value">{{ occupy_space }}MB</div>
<div class="el-icon-s-flag">
附件大小
</div>
</div>
</div>
</div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
export default {
sort: 3,
title: '附件统计',
name: 'attachmentTotal',
icon: 'el-icon-s-order',
description: '总附件数以及附件占用大小',
height: 14,
width: 16,
isResizable: true,
config: {
color: {
label: '背景颜色',
type: 'color',
value: '',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
}
},
props: {
config: {
type: Object,
required: false
}
},
data () {
return {
count: '',
occupy_space: ''
}
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res) => {
this.count = res.data.sum_file.count
this.occupy_space = res.data.sum_file.occupy_space
})
},
//
randomColor () {
if (this.config?.color?.value) {
return this.config.color.value
}
return this.color || this.$util.randomColor()
}
},
mounted () {
this.initGet()
}
}
</script>
<style scoped lang="scss">
.card-view {
//border-radius: 10px;
color: #ffffff;
.card-content {
.card-content-label {
font-size: 0.8em;
}
.card-content-value {
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
}
}
.attachment-value {
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
}
.el-icon-document-copy {
font-size: 12px;
}
.el-icon-s-flag {
font-size: 12px;
}
}
.real-time {
background: rgb(53, 59, 86);
color: #ffffff;
font-size: 14px;
font-style: normal;
padding: 0 7px 0 7px;
border-radius: 4px;
position: absolute;
right: 20px;
top: 20px;
}
.el-card {
height: 100%;
}
.absolute-right {
position: absolute;
right: 30px;
}
.absolute-left {
position: absolute;
}
</style>

View File

@ -6,14 +6,13 @@
<script> <script>
export default { export default {
sort: 8,
title: '宣传图', title: '宣传图',
name: 'dashboardImg',
icon: 'el-icon-medal', icon: 'el-icon-medal',
description: '用于展示各种图片宣传页',
height: 10, height: 10,
width: 8, width: 16,
minH: 10,
minW: 1,
maxW: 24,
maxH: 100,
isResizable: true, isResizable: true,
config: { config: {
src: { src: {
@ -37,7 +36,6 @@ export default {
required: false required: false
} }
}, },
description: '用于展示各种图片宣传页',
data () { data () {
return { return {
} }

View File

@ -1,110 +0,0 @@
<template>
<el-card
class="card-view"
:style="{ backgroundColor: randomColor() }"
shadow="always"
>
<div>
<el-row type="flex" justify="space-around">
<el-col :span="12">
<div class="card-content-label">数据库统计</div>
<div class="card-content">
<div class="card-content-value">{{count }}</div>
<div class="el-icon-coin">
数据库数量</div>
</div>
</el-col>
<el-col :span="12" :offset="6" style="text-align: right">
<i class="real-time">实时</i>
<div class="card-content-time">
<div class="attachment-value">{{ space}}MB</div>
<div class="el-icon-s-flag">
占用空间</div>
</div>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
import { request } from "@/api/service";
export default {
title: "数据库统计图",
icon: "el-icon-coin",
description: "数据库统计",
name: "database",
height: 14,
width: 8,
minH: 14,
minW: 8,
isResizable: true,
data() {
return {
count:"",
space:"",
};
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res)=>{
this.count=res.data.database_info.count;
this.space=res.data.database_info.space;
;
})
},
//
randomColor() {
const color = ["#50A8F4FF", "#FD6165FF", "#E679D8FF", "#F9AB5BFF"];
const ran = Math.floor(Math.random() * 4);
return color[ran];
},
},
mounted() {
this.initGet();
},
};
</script>
<style scoped lang="scss">
.card-view {
border-radius: 10px;
color: #ffffff;
.card-content {
.card-content-label {
font-size: 0.8em;
color: #ffffff;
}
.card-content-value {
color: #ffffff;
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
}
}
.attachment-value {
color: #ffffff;
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
margin-right: 180px;
}
.el-icon-coin{
font-size: 12px;
}
.el-icon-s-flag {
font-size: 12px;
margin-right: 130px;
}
}
.real-time {
background: rgb(53, 59, 86);
font-size: 14px;
font-style: normal;
padding: 0 7px 0 7px;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,146 @@
<template>
<el-card
class="card-view"
:style="{ backgroundColor: randomColor() }"
shadow="always"
>
<div :style="{color: config?.fontColor?.value}">
<div>
<div class="card-content-label">数据库统计</div>
<i class="real-time">实时</i>
</div>
<div class="absolute-left">
<div class="card-content">
<div class="card-content-value">{{ count }}</div>
<div class="el-icon-coin">
数据库数量
</div>
</div>
</div>
<div class="absolute-right">
<div class="card-content-time">
<div class="attachment-value">{{ space }}MB</div>
<div class="el-icon-s-flag">
占用空间
</div>
</div>
</div>
</div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
export default {
sort: 4,
title: '数据库统计',
name: 'databaseTotal',
icon: 'el-icon-coin',
description: '数据库统计',
height: 14,
width: 16,
isResizable: true,
data () {
return {
count: '',
space: ''
}
},
config: {
color: {
label: '背景颜色',
type: 'color',
value: '',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
}
},
props: {
config: {
type: Object,
required: false
}
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res) => {
this.count = res.data.database_info.count
this.space = res.data.database_info.space
})
},
randomColor () {
if (this.config?.color?.value) {
return this.config.color.value
}
return this.color || this.$util.randomColor()
}
},
mounted () {
this.initGet()
}
}
</script>
<style scoped lang="scss">
.card-view {
//border-radius: 10px;
color: #ffffff;
.card-content {
.card-content-label {
font-size: 0.8em;
}
.card-content-value {
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
}
}
.attachment-value {
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
}
.el-icon-coin {
font-size: 12px;
}
.el-icon-s-flag {
font-size: 12px;
}
}
.real-time {
background: rgb(53, 59, 86);
color: #ffffff;
font-size: 14px;
font-style: normal;
padding: 0 7px 0 7px;
border-radius: 4px;
position: absolute;
right: 20px;
top: 20px;
}
.el-card {
height: 100%;
}
.absolute-right{
position: absolute;
right: 30px;
}
.absolute-left{
position: absolute;
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<el-card class="card-view" :style="{backgroundColor:randomColor(),color: config?.fontColor?.value}" shadow="always">
<div>
<el-row type="flex" justify="space-around" style="padding:10px">
<el-col :span="12">
<div class="card-content">
<div class="card-content-label">登录总数</div>
<div class="card-content-value">{{ sum_register }}</div>
</div>
</el-col>
<el-col :span="6" :offset="6" style="text-align: right;">
<i class="el-icon-user-solid" size="48px"></i>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
export default {
sort: 2,
title: '登录总数',
name: 'loginTotal',
icon: 'el-icon-user-solid',
description: '用户登录平台总次数',
height: 14,
width: 16,
isResizable: true,
config: {
color: {
label: '背景颜色',
type: 'color',
value: '',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
}
},
props: {
config: {
type: Object,
required: false
}
},
data () {
return {
sum_register: ''
}
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res) => {
this.sum_register = res.data.sum_register
})
},
//
randomColor () {
if (this.config?.color?.value) {
return this.config.color.value
}
return this.color || this.$util.randomColor()
}
},
mounted () {
this.initGet()
}
}
</script>
<style scoped lang="scss">
.card-view {
//border-radius: 10px;
color: #FFFFFF;
.card-content {
.card-content-label {
font-size: 1em;
}
.card-content-value {
margin-top: 10px;
font-size: 1.5em;
font-weight: bold;
}
}
}
.el-icon-user-solid {
font-size: 30px;
}
.el-card {
height: 100%;
}
</style>

View File

@ -1,84 +0,0 @@
<template>
<el-card class="card-view" :style= "{backgroundColor:randomColor()}" shadow="always">
<div>
<el-row type="flex" justify="space-around" style="padding:10px">
<el-col :span="12">
<div class="card-content">
<div class="card-content-label">用户总数</div>
<div class="card-content-value">{{sum_register}}</div>
</div>
</el-col>
<el-col :span="6" :offset="6" style="text-align: right;">
<i class="el-icon-user-solid" size="48px"></i>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
export default {
title: '用户总数',
icon: 'el-icon-user-solid',
description: '总会员数',
name: 'summarizing',
height: 14,
width: 8,
minH: 14,
minW: 8,
isResizable: true,
data () {
return {
sum_register:"",
}
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res)=>{
this.sum_register=res.data.sum_register
})
},
//
randomColor () {
const color = [
'#50A8F4FF',
'#FD6165FF',
'#E679D8FF',
'#F9AB5BFF'
]
const ran = Math.floor(Math.random() * 4)
return color[ran]
}
},
mounted () {
this.initGet()
}
}
</script>
<style scoped lang="scss">
.card-view{
border-radius: 10px;
color: #FFFFFF;
.card-content{
.card-content-label{
font-size: 1em;
color: #FFFFFF;
}
.card-content-value{
color: #FFFFFF;
margin-top: 10px;
font-size: 1.5em;
font-weight: bold;
}
}
}
.el-icon-user-solid{
font-size: 30px;
}
</style>

View File

@ -1,174 +0,0 @@
<template>
<el-card class="card-view" :style= "{backgroundColor:randomColor()}" shadow="always" >
<div style="display:flex;flex: 1; flex-wrap: wrap;justify-content: space-between; margin-top: 10px;">
<div style="flex: 1; min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-s-promotion"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{ newName }}</h3>
</div>
<div class="enroll-text">今日注册
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-chat-line-square"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{today_login}}</h3>
</div>
<div class="enroll-text">今日登录
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-date"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{Three_days_register}}</h3>
</div>
<div class="enroll-text">三日新增
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px;display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-folder-add"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{Seven_days_register}}</h3>
</div>
<div class="enroll-text">七日新增
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-user-solid"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{Seven_days_login}}</h3>
</div>
<div class="enroll-text">七日活跃
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-user"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{month_login}}</h3>
</div>
<div class="enroll-text">月活跃
</div>
</div>
</el-col>
</div>
</div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
import log from '../init'
export default {
title: '用户新增活跃图',
icon: 'el-icon-user-solid',
description: '用户新增',
height: 28,
minH: 8,
width: 10,
minW: 5,
isResizable: true,
data () {
return {
newName:"",
today_login:"",
Three_days_register:"",
Seven_days_register:"",
Seven_days_login:"",
month_login:"",
}
},
mounted () {
this.initGet()
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res)=>{
this.newName=res.data.today_register;
this. today_login=res.data.today_login;
this. Three_days_register=res.data.Three_days_register;
this. Seven_days_register=res.data.Seven_days_register;
this. Seven_days_login=res.data.Seven_days_login;
this. month_login=res.data.month_login;
;
})
},
//
randomColor () {
const color = [
'#fffff',
]
const ran = Math.floor(Math.random() * 4)
return color[ran]
}
}
}
</script>
<style scoped>
.card-view{
border-radius: 10px;
color: rgb(37,176,138);
}
.lightgreen-box {
border-bottom: 2px solid rgb(37,176,138);
height:60px;
margin-bottom: 10px;
}
.underline i{
font-size: 30px;
}
.orange-box {
height:60px;
color: black;
border-bottom:2px solid rgb(242,242,242);
}
.enroll-time{
margin-left: 10px;
}
.enroll-text{
color: rgb(138,138,138);
}
</style>

View File

@ -5,95 +5,217 @@
backgroundColor: randomColor(), backgroundColor: randomColor(),
}" }"
> >
<div id="main" style="width: 530px; height: 300px; left: -18px"></div> <div id="main" :style="{width: wpx+'px',height: hpx+'px'}"></div>
</el-card> </el-card>
</template> </template>
<script> <script>
import { request } from "@/api/service"; import { request } from '@/api/service'
export default { export default {
title: "注册用户数折线图", sort: 7,
icon: "el-icon-s-data", title: '注册用户趋势',
description: "用户注册", name: 'registeredUser',
name: "registeredUser", icon: 'el-icon-s-data',
description: '用户注册',
height: 28, height: 28,
width: 10, width: 20,
minH: 10,
minW: 4,
isResizable: true, isResizable: true,
name: "eCharts", props: {
data() { hpx: {
this.myChart = null; type: Number
},
wpx: {
type: Number
}
},
data () {
this.myChart = null
return { return {
time: [], time: []
}; }
}, },
methods: { methods: {
initGet() { initGet () {
request({ request({
url: "/api/system/homepage_statistics/", url: '/api/system/homepage_statistics/'
}).then((res) => { }).then((res) => {
this.time = res.data.sum_days_register_list; this.time = [
this.drawLine(this.time); {
}); time: '2023-04-20',
count: 1
},
{
time: '2023-04-19',
count: 0
},
{
time: '2023-04-18',
count: 0
},
{
time: '2023-04-17',
count: 10
},
{
time: '2023-04-16',
count: 0
},
{
time: '2023-04-15',
count: 2
},
{
time: '2023-04-14',
count: 3
}
]
console.log(this.time)
this.drawLine(this.time)
})
}, },
// //
randomColor() { randomColor () {
const color = ["#fffff"]; const color = ['#fffff']
const ran = Math.floor(Math.random() * 4); const ran = Math.floor(Math.random() * 4)
return color[ran]; return color[ran]
}, },
drawLine() { drawLine () {
// domecharts // domecharts
// //
this.myChart.setOption({ const xAxisData = this.time.map(item => item.time)
title: { text: "" }, const seriesData = this.time.map(item => item.count)
tooltip: {}, const option = {
xAxis: { tooltip: {
data: this.time.map((item) => item.time), trigger: 'axis',
boundaryGap: false, backgroundColor: 'rgba(255, 255, 255, 0.8)',
axisLabel: { textStyle: {
interval: 0, // color: '#666'
rotate: 6,
}, },
axisPointer: {
lineStyle: {
color: '#999',
type: 'dotted',
width: 1
}
},
formatter: params => {
const param = params[0]
return `<div style="padding: 8px;"><div style="color: #333;">${param.name}</div><div style="color: #FFA500;">${param.value} 人</div></div>`
}
}, },
yAxis: {},
legend: { legend: {
data: ["注册用户数"], data: ['用户注册数'],
textStyle: {
color: '#666',
fontSize: 12
}
},
grid: {
top: 40,
left: 40,
right: 65,
bottom: 60
},
xAxis: {
data: xAxisData,
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#aaa',
width: 1
}
},
axisLabel: {
interval: function (index, value) {
// x
return index % 2 === 0
}, //
rotate: 0,
textStyle: {
color: '#333',
fontSize: 12
}
}
},
yAxis: {
axisLine: {
lineStyle: {
color: '#aaa',
width: 1
}
},
axisLabel: {
textStyle: {
color: '#333',
fontSize: 12
}
},
splitLine: {
lineStyle: {
color: '#ddd',
type: 'dotted',
width: 1
}
}
}, },
series: [ series: [
{ {
name: "注册用户数", name: '用户注册数',
type: "line", type: 'line',
data: this.time.map((item) => item.count), data: seriesData,
//线 symbol: 'circle',
areaStyle: { symbolSize: 6,
color: "rgb(98,206,178)", smooth: true,
lineStyle: {
color: 'rgba(38,204,164, 0.8)',
width: 2
}, },
//线
itemStyle: { itemStyle: {
color: "rgb(38,204,164)", // 线 color: 'rgba(98,206,178, 0.8)',
borderColor: 'rgba(38,204,164, 1)',
borderWidth: 1
}, },
}, areaStyle: {
], color: {
}); type: 'linear',
}, x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(140,189,250, 0.8)'
},
{
offset: 1,
color: 'rgba(0, 128, 255, 0)'
}
]
}
}
}
]
}
this.myChart.setOption(option)
}
}, },
mounted() { mounted () {
this.myChart = this.$echarts.init(document.getElementById("main")); this.myChart = this.$echarts.init(document.getElementById('main'))
this.initGet(); this.initGet()
this.drawLine(); this.drawLine()
}, }
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.card-view { .card-view {
border-radius: 10px; //border-radius: 10px;
color: #ffffff; color: #ffffff;
} }
.el-card { .el-card {
height: 100%; height: 100%;
} }
</style> </style>

View File

@ -1,111 +0,0 @@
<template>
<el-card
class="card-view"
:style="{ backgroundColor: randomColor() }"
shadow="always"
>
<div>
<el-row type="flex" justify="space-around">
<el-col :span="12">
<div class="card-content-label">附件总数</div>
<div class="card-content">
<div class="card-content-value">{{ count }}</div>
<div class="el-icon-document-copy">
附件总数量</div>
</div>
</el-col>
<el-col :span="12" :offset="6" style="text-align: right">
<i class="real-time">实时</i>
<div class="card-content-time">
<div class="attachment-value">{{ occupy_space}}MB</div>
<div class="el-icon-s-flag">
占用空间</div>
</div>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
import { request } from "@/api/service";
export default {
title: "附件总数统计图",
icon: "el-icon-s-order",
description: "附件总数量",
name: "sumTotal",
height: 14,
width: 8,
minH: 14,
minW: 8,
isResizable: true,
data() {
return {
count:"",
occupy_space:"",
};
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res)=>{
this.count=res.data.today_file.count;
this.occupy_space=res.data.today_file.occupy_space;
;
})
},
//
randomColor() {
const color = ["#50A8F4FF", "#FD6165FF", "#E679D8FF", "#F9AB5BFF"];
const ran = Math.floor(Math.random() * 4);
return color[ran];
},
},
mounted() {
this.initGet();
},
};
</script>
<style scoped lang="scss">
.card-view {
border-radius: 10px;
color: #ffffff;
.card-content {
.card-content-label {
font-size: 0.8em;
color: #ffffff;
}
.card-content-value {
color: #ffffff;
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
}
}
.attachment-value {
color: #ffffff;
margin-top: 5px;
font-size: 1.5em;
font-weight: bold;
margin-right: 180px;
}
.el-icon-document-copy {
font-size: 12px;
}
.el-icon-s-flag {
font-size: 12px;
margin-right: 130px;
}
}
.real-time {
background: rgb(53, 59, 86);
font-size: 14px;
font-style: normal;
padding: 0 7px 0 7px;
border-radius: 4px;
}
</style>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-card shadow="hover" header="时钟" class="item-background"> <el-card shadow="hover" class="item-background" :style="{backgroundColor: randomColor(),color: config?.fontColor?.value}">
<div class="time"> <div class="time">
<h2>{{ time }}</h2> <h2>{{ time }}</h2>
<p>{{ day }}</p> <p>{{ day }}</p>
@ -11,14 +11,34 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
export default { export default {
sort: 12,
title: '时钟', title: '时钟',
name: 'myTime',
icon: 'el-icon-alarm-clock', icon: 'el-icon-alarm-clock',
description: '演示部件效果', description: '演示部件效果',
height: 20, height: 14,
minH: 10, width: 16,
width: 8,
minW: 4,
isResizable: true, isResizable: true,
config: {
color: {
label: '背景颜色',
type: 'color',
value: '',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
}
},
props: {
config: {
type: Object,
required: false
}
},
data () { data () {
return { return {
time: '', time: '',
@ -35,16 +55,19 @@ export default {
showTime () { showTime () {
this.time = dayjs().format('HH:mm:ss') this.time = dayjs().format('HH:mm:ss')
this.day = dayjs().format('YYYY年MM月DD日') this.day = dayjs().format('YYYY年MM月DD日')
},
//
randomColor () {
if (this.config?.color?.value) {
return this.config.color.value
}
return 'linear-gradient(to right, #8E54E9, #4776E6)'
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.item-background {
background: linear-gradient(to right, #8E54E9, #4776E6);
color: #fff;
}
.time h2 { .time h2 {
font-size: 24px; font-size: 24px;

View File

@ -1,106 +0,0 @@
<template>
<el-card
class="card-view"
:style="{
backgroundColor: randomColor(),
}"
>
<!-- shadow="always" -->
<div id="myChart" style="width: 530px; height: 300px; left: -15px"></div>
</el-card>
</template>
<script>
import { request } from "@/api/service";
export default {
title: "用户登录折线图",
icon: "el-icon-s-data",
description: "用户登陆",
name: "user",
height: 28,
width: 10,
minH: 10,
minW: 4,
isResizable: true,
name: "eCharts",
data() {
this.myChart=null
return {
time:[]
};
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res)=>{
this.time=res.data.sum_days_login_list
this.drawLine(this.time)
})
},
//
randomColor() {
const color = ["#fffff"];
const ran = Math.floor(Math.random() * 4);
return color[ran];
},
drawLine() {
// domecharts
//
this. myChart.setOption({
title: { text: "" },
tooltip: {},
xAxis: {
data: this.time.map(item=>item.time),
boundaryGap: false,
axisLabel: {
interval: 0, //
rotate: 6,
},
},
yAxis: {},
legend: {
data: ["用户登陆数"],
},
series: [
{
name: "用户登陆数",
type: "line",
data: this.time.map(item=>item.count),
areaStyle: {},
areaStyle: {
//线
color: "rgb(116,135,206)",
},
itemStyle: {
color: "rgb(67,89,185)", // 线
},
},
],
});
},
},
mounted() {
this. myChart =this.$echarts.init(document.getElementById("myChart"));
this.initGet();
this.drawLine();
},
};
</script>
<style scoped lang="scss">
.card-view {
border-radius: 10px;
color: #ffffff;
}
.el-card{
height: 100%;
}
::v-deep .el-card__body {
width: 470px;
height: 300px;
}
</style>

View File

@ -0,0 +1,205 @@
<template>
<el-card
class="card-view"
:style="{
backgroundColor: randomColor(),
}"
>
<!-- shadow="always" -->
<div id="myChart" :style="{width: wpx+'px',height: hpx+'px'}"></div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
export default {
sort: 6,
title: '用户登录趋势',
name: 'userLogin',
icon: 'el-icon-s-data',
description: '用户登陆',
height: 28,
width: 20,
isResizable: true,
props: {
hpx: {
type: Number
},
wpx: {
type: Number
}
},
data () {
this.myChart = null
return {
time: [],
radio: '7'
}
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res) => {
this.time = res.data.sum_days_login_list
console.log(2, this.time)
this.drawLine(this.time)
})
},
//
randomColor () {
const color = ['#fffff']
const ran = Math.floor(Math.random() * 4)
return color[ran]
},
drawLine () {
// domecharts
//
const xAxisData = this.time.map(item => item.time)
const seriesData = this.time.map(item => item.count)
const option = {
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(255, 255, 255, 0.8)',
textStyle: {
color: '#666'
},
axisPointer: {
lineStyle: {
color: '#999',
type: 'dotted',
width: 1
}
},
formatter: params => {
const param = params[0]
return `<div style="padding: 8px;"><div style="color: #333;">${param.name}</div><div style="color: #FFA500;">${param.value} 人</div></div>`
}
},
legend: {
data: ['用户登陆数'],
textStyle: {
color: '#666',
fontSize: 12
}
},
grid: {
top: 40,
left: 40,
right: 65,
bottom: 60
},
xAxis: {
data: xAxisData,
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#aaa',
width: 1
}
},
axisLabel: {
interval: function (index, value) {
// x
return index % 2 === 0
}, //
rotate: 0,
textStyle: {
color: '#333',
fontSize: 12
}
}
},
yAxis: {
axisLine: {
lineStyle: {
color: '#aaa',
width: 1
}
},
axisLabel: {
textStyle: {
color: '#333',
fontSize: 12
}
},
splitLine: {
lineStyle: {
color: '#ddd',
type: 'dotted',
width: 1
}
}
},
series: [
{
name: '用户登陆数',
type: 'line',
data: seriesData,
symbol: 'circle',
smooth: true,
symbolSize: 6,
lineStyle: {
color: 'rgba(0, 128, 255, 0.8)',
width: 2
},
itemStyle: {
color: 'rgba(0, 128, 255, 0.8)',
borderColor: 'rgba(0, 128, 255, 1)',
borderWidth: 1
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(140,189,250, 0.8)'
},
{
offset: 1,
color: 'rgba(0, 128, 255, 0)'
}
]
}
}
}
]
}
this.myChart.setOption(option)
}
},
mounted () {
this.myChart = this.$echarts.init(document.getElementById('myChart'))
this.initGet()
this.drawLine()
console.log(111, this.wpx, this.hpx)
this.myChart.resize({ width: this.wpx, height: this.hpx })
}
}
</script>
<style scoped lang="scss">
.card-view {
//border-radius: 10px;
color: #ffffff;
}
.el-card{
height: 100%;
}
::v-deep .el-card__body {
width: 100%;
height: 100%;
}
.el-radio-button__inner {
border-radius: 20px;
}
</style>

View File

@ -0,0 +1,181 @@
<template>
<el-card class="card-view" :style="{backgroundColor:randomColor()}" shadow="always">
<div style="display:flex;flex: 1; flex-wrap: wrap;justify-content: space-between; margin-top: 10px;">
<div style="flex: 1; min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-s-promotion"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{ newName }}</h3>
</div>
<div class="enroll-text">今日注册
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-chat-line-square"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{ today_login }}</h3>
</div>
<div class="enroll-text">今日登录
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-date"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{ Three_days_register }}</h3>
</div>
<div class="enroll-text">三日新增
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px;display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-folder-add"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{ Seven_days_register }}</h3>
</div>
<div class="enroll-text">七日新增
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-user-solid"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{ Seven_days_login }}</h3>
</div>
<div class="enroll-text">七日活跃
</div>
</div>
</el-col>
</div>
<div style="flex: 1;min-width: 180px;max-width:180px;height: 80px; display: flex;">
<el-col :span="4" class="lightgreen-box">
<div class="underline">
<i class="el-icon-user"></i>
</div>
</el-col>
<el-col :span="20" class="orange-box">
<div class="enroll-time">
<div class="enroll-number"><h3>{{ month_login }}</h3>
</div>
<div class="enroll-text">月活跃
</div>
</div>
</el-col>
</div>
</div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
export default {
sort: 5,
title: '用户新增统计',
name: 'usersActive',
icon: 'el-icon-user-solid',
description: '用户新增以及活跃统计数据',
height: 18,
width: 20,
isResizable: true,
data () {
return {
newName: '',
today_login: '',
Three_days_register: '',
Seven_days_register: '',
Seven_days_login: '',
month_login: ''
}
},
mounted () {
this.initGet()
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res) => {
this.newName = res.data.today_register
this.today_login = res.data.today_login
this.Three_days_register = res.data.Three_days_register
this.Seven_days_register = res.data.Seven_days_register
this.Seven_days_login = res.data.Seven_days_login
this.month_login = res.data.month_login
})
},
//
randomColor () {
const color = [
'#fffff'
]
const ran = Math.floor(Math.random() * 4)
return color[ran]
}
}
}
</script>
<style scoped lang="scss">
.card-view {
// border-radius: 10px;
color: rgb(37, 176, 138);
}
.lightgreen-box {
border-bottom: 2px solid rgb(37, 176, 138);
height: 60px;
margin-bottom: 10px;
}
.underline i {
font-size: 30px;
}
.orange-box {
height: 60px;
color: black;
border-bottom: 2px solid rgb(242, 242, 242);
}
.enroll-time {
margin-left: 10px;
}
.enroll-text {
color: rgb(138, 138, 138);
}
.el-card {
height: 100%;
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<el-card class="card-view" :style="{backgroundColor:randomColor(),color: config?.fontColor?.value}" shadow="always">
<div>
<el-row type="flex" justify="space-around" style="padding:10px">
<el-col :span="12">
<div class="card-content">
<div class="card-content-label">用户总数</div>
<div class="card-content-value">{{ sum_register }}</div>
</div>
</el-col>
<el-col :span="6" :offset="6" style="text-align: right;">
<i class="el-icon-user-solid" size="48px"></i>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
import { request } from '@/api/service'
export default {
sort: 1,
title: '用户总数',
icon: 'el-icon-user-solid',
description: '平台总会员数',
name: 'usersTotal',
height: 14,
width: 16,
isResizable: true,
config: {
color: {
label: '背景颜色',
type: 'color',
value: '',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
}
},
props: {
config: {
type: Object,
required: false
}
},
data () {
return {
sum_register: ''
}
},
methods: {
initGet () {
request({
url: '/api/system/homepage_statistics/'
}).then((res) => {
this.sum_register = res.data.sum_register
})
},
//
randomColor () {
if (this.config?.color?.value) {
return this.config.color.value
}
return this.color || this.$util.randomColor()
}
},
mounted () {
this.initGet()
}
}
</script>
<style scoped lang="scss">
.card-view {
//border-radius: 10px;
color: #FFFFFF;
.card-content {
.card-content-label {
font-size: 1em;
}
.card-content-value {
margin-top: 10px;
font-size: 1.5em;
font-weight: bold;
}
}
}
.el-icon-user-solid {
font-size: 30px;
}
.el-card {
height: 100%;
}
</style>

View File

@ -1,6 +1,6 @@
<template> <template>
<el-card shadow="hover" class="card-view" :style="{backgroundColor:randomColor()}" header="版本信息"> <el-card shadow="hover" class="card-view" :style="{backgroundColor:randomColor(),color: config?.fontColor?.value}">
<div style="text-align: center;color: #FFFFFF"> <div style="text-align: center;">
<h2 style="margin-top: 5px;">{{ title }}</h2> <h2 style="margin-top: 5px;">{{ title }}</h2>
<p style="margin-top: 5px;">最新版本 {{ ver }}</p> <p style="margin-top: 5px;">最新版本 {{ ver }}</p>
</div> </div>
@ -11,14 +11,34 @@
import { mapState } from 'vuex' import { mapState } from 'vuex'
export default { export default {
sort: 10,
title: '版本信息', title: '版本信息',
name: 'ver',
icon: 'el-icon-monitor', icon: 'el-icon-monitor',
description: '当前项目版本信息', description: '当前项目版本信息',
height: 20, height: 14,
minH: 10, width: 16,
width: 8,
minW: 4,
isResizable: true, isResizable: true,
config: {
color: {
label: '背景颜色',
type: 'color',
value: '',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
}
},
props: {
config: {
type: Object,
required: false
}
},
data () { data () {
return { return {
ver: 'loading...', ver: 'loading...',
@ -38,33 +58,32 @@ export default {
this.ver = `v${process.env.VUE_APP_VERSION}` || 'v2.1.1' this.ver = `v${process.env.VUE_APP_VERSION}` || 'v2.1.1'
this.title = this.siteName || process.env.VUE_APP_TITLE this.title = this.siteName || process.env.VUE_APP_TITLE
}, },
golog () {
window.open('https://gitee.com/liqianglog/django-vue-admin/releases')
},
gogit () {
window.open('https://gitee.com/liqianglog/django-vue-admin')
},
// //
randomColor () { randomColor () {
if (this.config?.color?.value) {
return this.config.color.value
}
return this.color || this.$util.randomColor() return this.color || this.$util.randomColor()
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.card-view{ .card-view {
color: #FFFFFF; color: #FFFFFF;
//background: rgb(80,168,244); //background: rgb(80,168,244);
//box-shadow: 1px 6px 8px 2px rgba(80,168,244,0.2); //box-shadow: 1px 6px 8px 2px rgba(80,168,244,0.2);
.card-content{ .card-content {
//text-align: center; //text-align: center;
} }
} }
::v-deep .el-card__body { ::v-deep .el-card__body {
height: 110px; height: 110px;
} }
.el-card{
.el-card {
height: 100%; height: 100%;
} }
</style> </style>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-card shadow="hover" header="欢迎" style="background: linear-gradient(150deg, #3b88ec 0%, #accaff 100%);color: #fff;"> <el-card shadow="hover" :header="config?.showHeader?.value ? '欢迎使用' : ''" :style="{background: randomColor(), color: config?.fontColor?.value}">
<div class="welcome"> <div class="welcome">
<div class="logo"> <div class="logo">
<img src="/image/django-vue-admin.png"> <img src="/image/django-vue-admin.png">
@ -34,14 +34,40 @@
<script> <script>
export default { export default {
title: '欢迎', sort: 11,
title: '欢迎使用',
name: 'welcome',
icon: 'el-icon-present', icon: 'el-icon-present',
description: '项目特色以及文档链接', description: '项目特色以及文档链接',
width: 8, width: 16,
height: 45, height: 45,
minH: 45,
minW: 1,
isResizable: true, isResizable: true,
config: {
showHeader: {
label: '显示头部信息',
type: 'boot',
value: true,
placeholder: '颜色为空则随机变换颜色'
},
color: {
label: '背景颜色',
type: 'color',
value: '',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: '#ffffff',
placeholder: '请选择字体颜色'
}
},
props: {
config: {
type: Object,
required: false
}
},
data () { data () {
return {} return {}
}, },
@ -54,7 +80,7 @@ export default {
if (this.config?.color?.value) { if (this.config?.color?.value) {
return this.config.color.value return this.config.color.value
} }
return this.color || this.$util.randomColor() return 'linear-gradient(150deg, #3b88ec 0%, #accaff 100%)'
} }
} }
} }

View File

@ -15,10 +15,11 @@
:key="index" :key="index"
:rules="item.rules"> :rules="item.rules">
<el-input v-if="item.type==='input'" v-model="item.value" :placeholder="item.placeholder || '请输入'"></el-input> <el-input v-if="item.type==='input'" v-model="item.value" :placeholder="item.placeholder || '请输入'"></el-input>
<el-switch v-if="item.type==='boot'" v-model="item.value" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
<el-color-picker v-if="item.type==='color'" v-model="item.value" show-alpha :predefine="predefineColors"></el-color-picker> <el-color-picker v-if="item.type==='color'" v-model="item.value" show-alpha :predefine="predefineColors"></el-color-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="deviceUpgradeDrawer = false">保存</el-button> <el-button type="primary" @click="saveConfig"></el-button>
<el-button @click="deviceUpgradeDrawer = false">关闭</el-button> <el-button @click="deviceUpgradeDrawer = false">关闭</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -59,6 +60,10 @@ export default {
this.myComp = myComp this.myComp = myComp
this.items = items this.items = items
console.log(1112, this.myComp, this.items) console.log(1112, this.myComp, this.items)
},
saveConfig () {
this.deviceUpgradeDrawer = false
this.$emit('saveConfig', this.myComp, this.items)
} }
} }

View File

@ -9,6 +9,10 @@
</el-button> </el-button>
</div> </div>
<div slot="operateButton"> <div slot="operateButton">
<el-tooltip class="item" effect="dark" content="清空画布" placement="top">
<el-button v-if="customizing" type="danger" icon="el-icon-delete" circle size="mini"
@click="clickEmpty"></el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="最小化" placement="top"> <el-tooltip class="item" effect="dark" content="最小化" placement="top">
<el-button v-if="customizing" type="success" icon="el-icon-minus" circle size="mini" <el-button v-if="customizing" type="success" icon="el-icon-minus" circle size="mini"
@click="clickMinimize"></el-button> @click="clickMinimize"></el-button>
@ -30,7 +34,8 @@
<span v-for="item in myCompsList" :key="item.title"> <span v-for="item in myCompsList" :key="item.title">
<el-tooltip class="item" effect="dark" :content="item.description" placement="top"> <el-tooltip class="item" effect="dark" :content="item.description" placement="top">
<div class="widgetsListItem" :style="{background: $util.randomBackground()}"> <div class="widgetsListItem" :style="{background: $util.randomBackground()}">
<span style="position: relative;right: 8px;float: right;top: -22px;cursor: pointer;" @click="push(item)"> <span style="position: relative;right: 8px;float: right;top: -22px;cursor: pointer;"
@click="push(item)">
<i class="el-icon-plus"></i> <i class="el-icon-plus"></i>
</span> </span>
<i :class="item.icon"></i> &nbsp;{{ item.title }} <i :class="item.icon"></i> &nbsp;{{ item.title }}
@ -55,20 +60,17 @@
:use-css-transforms="true" :use-css-transforms="true"
:autoSize="true" :autoSize="true"
> >
<grid-item v-for="(item, index) in layout" <grid-item
:static="item.static" v-for="(item, index) in layout"
:x="item.x" :static="item.static"
:y="item.y" :x="item.x"
:w="item.w" :y="item.y"
:h="item.h" :w="item.w"
:i="item.i" :h="item.h"
:minW="item.minW" :i="item.i"
:minH="item.minH" :key="index"
:maxW="item.maxW" :isResizable="customizing"
:maxH="item.maxH" @container-resized="containerResizedEvent"
:key="index"
:isResizable="customizing"
> >
<div v-if="customizing" class="customize-overlay"> <div v-if="customizing" class="customize-overlay">
<el-button v-if="item.config && Object.keys(item.config).length!==0" class="close" style="right: 60px;" <el-button v-if="item.config && Object.keys(item.config).length!==0" class="close" style="right: 60px;"
@ -79,14 +81,16 @@
<label> <label>
<i :class="allComps[item.element].icon"></i> <i :class="allComps[item.element].icon"></i>
{{ allComps[item.element].title }}</label> {{ allComps[item.element].title }}</label>
<div style="color:#000;">{{ item.w }} x {{ item.h }}</div>
</div> </div>
<component :class="customizing?'set-component-bg':''" :is="allComps[item.element]" <component :class="customizing?'set-component-bg':''" :is="allComps[item.element]"
:config="item.config || {}"></component> :config="item.config || {}" :width="item.w" :height="item.h" :wpx="item.wpx"
:hpx="item.hpx"></component>
</grid-item> </grid-item>
</grid-layout> </grid-layout>
</div> </div>
</div> </div>
<dashboard-config ref="dashboardConfig"></dashboard-config> <dashboard-config ref="dashboardConfig" @saveConfig="saveConfig"></dashboard-config>
</d2-container> </d2-container>
</template> </template>
@ -114,12 +118,18 @@ export default {
selectLayout: [], selectLayout: [],
defaultLayout: initData, defaultLayout: initData,
layout: [], layout: [],
colNum: 24, colNum: 48,
minimize: false minimize: false
} }
}, },
created () { async created () {
this.layout = JSON.parse(util.cookies.get('grid-layout') || JSON.stringify(this.defaultLayout)) this.layout = await this.$store.dispatch('d2admin/db/get', {
dbName: 'sys',
path: 'grid-layout',
defaultValue: JSON.parse(JSON.stringify(this.defaultLayout)),
user: true
}, { root: true })
console.log(this.layout)
}, },
mounted () { mounted () {
this.$emit('on-mounted') this.$emit('on-mounted')
@ -130,19 +140,19 @@ export default {
for (var key in this.allComps) { for (var key in this.allComps) {
allCompsList.push({ allCompsList.push({
key: key, key: key,
sort: allComps[key].sort,
title: allComps[key].title, title: allComps[key].title,
icon: allComps[key].icon, icon: allComps[key].icon,
height: allComps[key].height, height: allComps[key].height,
width: allComps[key].width, width: allComps[key].width,
minH: allComps[key].minH || 1,
minW: allComps[key].minW || 1,
maxH: allComps[key].maxH || 100,
maxW: (allComps[key].maxW > this.colNum ? this.colNum : allComps[key].maxW) || Infinity,
config: allComps[key].config || {}, config: allComps[key].config || {},
isResizable: allComps[key].isResizable || null, isResizable: allComps[key].isResizable || null,
description: allComps[key].description description: allComps[key].description
}) })
} }
allCompsList.sort(function (a, b) {
return (a.sort || 0) - (b.sort || 0)
})
return allCompsList return allCompsList
}, },
myCompsList () { myCompsList () {
@ -168,17 +178,12 @@ export default {
}, },
// //
push (item) { push (item) {
console.log(1, item)
this.layout.push({ this.layout.push({
i: this.getLayoutElementNumber(item.key), i: this.getLayoutElementNumber(item.key),
x: (this.layout.length * 2) % (this.colNum || 12), x: (this.layout.length * 2) % (this.colNum || 24),
y: this.layout.length + (this.colNum || 12), y: this.layout.length + (this.colNum || 24),
w: item.width, w: item.width,
h: item.height, h: item.height,
minW: item.minW,
minH: item.minH,
maxW: item.maxW,
maxH: item.maxH,
config: item.config || {}, config: item.config || {},
isResizable: item.isResizable || null, isResizable: item.isResizable || null,
element: item.key element: item.key
@ -189,13 +194,18 @@ export default {
this.layout.splice(index, 1) this.layout.splice(index, 1)
}, },
// //
save () { async save () {
console.log(this.layout) console.log(this.layout)
this.customizing = false this.customizing = false
this.minimize = false this.minimize = false
this.$refs.suspendedLibrary.menu = false this.$refs.suspendedLibrary.menu = false
this.$refs.widgets.style.removeProperty('transform') this.$refs.widgets.style.removeProperty('transform')
util.cookies.set('grid-layout', this.layout) await this.$store.dispatch('d2admin/db/set', {
dbName: 'sys',
path: 'grid-layout',
value: this.layout,
user: true
}, { root: true })
}, },
// //
backDefault () { backDefault () {
@ -204,33 +214,68 @@ export default {
this.$refs.suspendedLibrary.menu = false this.$refs.suspendedLibrary.menu = false
this.$refs.widgets.style.removeProperty('transform') this.$refs.widgets.style.removeProperty('transform')
this.layout = JSON.parse(JSON.stringify(this.defaultLayout)) this.layout = JSON.parse(JSON.stringify(this.defaultLayout))
util.cookies.remove('grid-layout') //
this.$store.dispatch('d2admin/db/set', {
dbName: 'sys',
path: 'grid-layout',
value: this.layout,
user: true
}, { root: true })
}, },
// //
close () { async close () {
this.customizing = false this.customizing = false
this.minimize = false this.minimize = false
this.$refs.suspendedLibrary.menu = false this.$refs.suspendedLibrary.menu = false
this.$refs.widgets.style.removeProperty('transform') this.$refs.widgets.style.removeProperty('transform')
this.layout = await this.$store.dispatch('d2admin/db/get', {
dbName: 'sys',
path: 'grid-layout',
defaultValue: JSON.stringify(this.defaultLayout),
user: true
}, { root: true })
},
//
clickEmpty () {
this.layout = []
},
//
saveConfig (myComp, items) {
this.layout.map(val => {
if (val.i === items.i) {
val.config = JSON.parse(JSON.stringify(items.config))
}
})
}, },
// //
clickMinimize () { clickMinimize () {
this.minimize = !this.minimize this.minimize = !this.minimize
this.$refs.suspendedLibrary.menu = !this.$refs.suspendedLibrary.menu this.$refs.suspendedLibrary.menu = !this.$refs.suspendedLibrary.menu
}, },
// //
clickConfig (itme) { clickConfig (itme) {
this.$refs.dashboardConfig.deviceUpgradeDrawer = true this.$refs.dashboardConfig.deviceUpgradeDrawer = true
this.$refs.dashboardConfig.initData(this.allComps[itme.element], itme) this.$refs.dashboardConfig.initData(this.allComps[itme.element], JSON.parse(JSON.stringify(itme)))
this.minimize = false this.minimize = false
},
//
containerResizedEvent: function (i, newH, newW, newHPx, newWPx) {
console.log('CONTAINER RESIZED i=' + i + ', H=' + newH + ', W=' + newW + ', H(px)=' + newHPx + ', W(px)=' + newWPx)
this.layout.map(val => {
if (val.i === i) {
val.hpx = Number(newHPx)
val.wpx = Number(newWPx)
}
})
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep .d2-container-full__body{ ::v-deep .d2-container-full__body {
padding: 0!important; padding: 0!important;
} }
.widgetsListItem { .widgetsListItem {
width: 168px; width: 168px;
height: 75px; height: 75px;
@ -294,7 +339,7 @@ export default {
} }
.set-component-bg { .set-component-bg {
background: rgba(255, 255, 255, 0.5); //background: rgba(255, 255, 255, 0.5);
border: 1px solid rgba(0, 0, 0, .5); border: 1px solid rgba(0, 0, 0, .5);
} }

View File

@ -1,159 +1,153 @@
const log = [ const log = [
{ {
i: 'dashboardImg1', i: 'usersTotal0',
x: 9,
y: 21,
w: 8,
h: 24,
minW: 1,
minH: 10,
maxW: 24,
maxH: 100,
config: {
src: {
label: '图片地址',
type: 'input',
value: '/image/card/tencent.jpg',
rules: [
{
required: true,
message: '不能为空'
}
]
},
url: {
label: '跳转地址',
type: 'input',
value: 'https://cloud.tencent.com/act/cps/redirect?redirect=1060&cps_key=b302a514a6688aa30823fac954464e5d&from=console',
rules: [
{
required: true,
message: '不能为空'
}
]
}
},
isResizable: true,
element: 'dashboardImg',
moved: false
},
{
i: 'dashboardImg2',
x: 9,
y: 0,
w: 15,
h: 21,
minW: 1,
minH: 10,
maxW: 24,
maxH: 100,
config: {
src: {
label: '图片地址',
type: 'input',
value: 'https://kfm-waiter.oss-cn-zhangjiakou.aliyuncs.com/dvadmin/img/aliyun-02.png',
placeholder: '请输入图片地址',
rules: [
{
required: true,
message: '不能为空'
}
]
},
url: {
label: '跳转地址',
type: 'input',
placeholder: '请输入跳转地址',
value: 'https://www.aliyun.com/minisite/goods?userCode=jpef8a71&share_source=copy_link',
rules: [
{
required: true,
message: '不能为空'
}
]
}
},
isResizable: true,
element: 'dashboardImg',
moved: false
},
{
i: 'time3',
x: 9,
y: 45,
w: 8,
h: 19,
minW: 4,
minH: 10,
maxW: null,
maxH: 100,
config: {},
isResizable: true,
element: 'time',
moved: false
},
{
i: 'ver4',
x: 17,
y: 45,
w: 7,
h: 19,
minW: 4,
minH: 10,
maxW: null,
maxH: 100,
config: {},
isResizable: true,
element: 'ver',
moved: false
},
{
i: 'about5',
x: 0, x: 0,
y: 45, y: 0,
w: 9, w: 12,
h: 19, h: 12,
minW: 2,
minH: 10,
maxW: null,
maxH: 100,
config: { config: {
color: { color: {
label: '背景颜色', label: '背景颜色',
type: 'color', type: 'color',
value: null, value: 'rgba(255, 255, 255, 1)',
placeholder: '颜色为空则随机变换颜色' placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: 'rgba(70, 183, 146, 1)',
placeholder: '请选择字体颜色'
} }
}, },
isResizable: true, isResizable: true,
element: 'about', element: 'usersTotal',
moved: false moved: false,
hpx: 122,
wpx: 397
}, },
{ {
i: 'welcome5', i: 'loginTotal1',
x: 0, x: 12,
y: 0, y: 0,
w: 9, w: 12,
h: 45, h: 12,
minW: 1, config: {
minH: 45, color: {
maxW: null, label: '背景颜色',
maxH: 100, type: 'color',
value: 'rgba(255, 255, 255, 1)',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: 'rgba(30, 144, 255, 1)',
placeholder: '请选择字体颜色'
}
},
isResizable: true,
element: 'loginTotal',
moved: false,
hpx: 122,
wpx: 397
},
{
i: 'attachmentTotal2',
x: 24,
y: 0,
w: 12,
h: 12,
config: {
color: {
label: '背景颜色',
type: 'color',
value: 'rgba(255, 255, 255, 1)',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: 'rgba(255, 140, 0, 1)',
placeholder: '请选择字体颜色'
}
},
isResizable: true,
element: 'attachmentTotal',
moved: false,
hpx: 122,
wpx: 397
},
{
i: 'databaseTotal3',
x: 36,
y: 0,
w: 12,
h: 12,
config: {
color: {
label: '背景颜色',
type: 'color',
value: 'rgba(255, 255, 255, 1)',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: 'rgba(0, 186, 189, 1)',
placeholder: '请选择字体颜色'
}
},
isResizable: true,
element: 'databaseTotal',
moved: false,
hpx: 122,
wpx: 397
},
{
i: 'usersActive5',
x: 33,
y: 12,
w: 15,
h: 24,
config: {}, config: {},
isResizable: true, isResizable: true,
element: 'welcome', element: 'usersActive',
moved: false moved: false,
hpx: 254,
wpx: 498
}, },
{ {
i: 'dashboardImg6', i: 'userLogin6',
x: 17, x: 0,
y: 21, y: 12,
w: 7, w: 16,
h: 24,
config: {},
isResizable: true,
element: 'userLogin',
moved: false,
hpx: 254,
wpx: 532
},
{
i: 'registeredUser7',
x: 16,
y: 12,
w: 17,
h: 24,
config: {},
isResizable: true,
element: 'registeredUser',
moved: false,
hpx: 254,
wpx: 566
},
{
i: 'dashboardImg8',
x: 32,
y: 36,
w: 16,
h: 24, h: 24,
minW: 1,
minH: 10,
maxW: 24,
maxH: 100,
config: { config: {
src: { src: {
label: '图片地址', label: '图片地址',
@ -182,7 +176,137 @@ const log = [
}, },
isResizable: true, isResizable: true,
element: 'dashboardImg', element: 'dashboardImg',
moved: false moved: false,
hpx: 254,
wpx: 532
},
{
i: 'dashboardImg9',
x: 16,
y: 36,
w: 16,
h: 24,
config: {
src: {
label: '图片地址',
type: 'input',
value: '/image/card/tencent.jpg',
placeholder: '请输入图片地址',
rules: [
{
required: true,
message: '不能为空'
}
]
},
url: {
label: '跳转地址',
type: 'input',
placeholder: '请输入跳转地址',
value: 'https://cloud.tencent.com/act/cps/redirect?redirect=1060&cps_key=b302a514a6688aa30823fac954464e5d&from=console',
rules: [
{
required: true,
message: '不能为空'
}
]
}
},
isResizable: true,
element: 'dashboardImg',
moved: false,
hpx: 254,
wpx: 532
},
{
i: 'dashboardImg10',
x: 16,
y: 60,
w: 22,
h: 15,
config: {
src: {
label: '图片地址',
type: 'input',
value: 'https://kfm-waiter.oss-cn-zhangjiakou.aliyuncs.com/dvadmin/img/aliyun-02.png',
placeholder: '请输入图片地址',
rules: [
{
required: true,
message: '不能为空'
}
]
},
url: {
label: '跳转地址',
type: 'input',
placeholder: '请输入跳转地址',
value: 'https://www.aliyun.com/minisite/goods?userCode=jpef8a71&share_source=copy_link',
rules: [
{
required: true,
message: '不能为空'
}
]
}
},
isResizable: true,
element: 'dashboardImg',
moved: false,
hpx: 155,
wpx: 736
},
{
i: 'welcome10',
x: 0,
y: 36,
w: 16,
h: 39,
config: {
color: {
label: '背景颜色',
type: 'color',
value: 'rgba(255, 255, 255, 1)',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: 'rgba(0, 0, 0, 1)',
placeholder: '请选择字体颜色'
}
},
isResizable: true,
element: 'welcome',
moved: false,
hpx: 419,
wpx: 532
},
{
i: 'ver11',
x: 38,
y: 60,
w: 10,
h: 15,
config: {
color: {
label: '背景颜色',
type: 'color',
value: 'rgba(255, 255, 255, 1)',
placeholder: '颜色为空则随机变换颜色'
},
fontColor: {
label: '字体颜色',
type: 'color',
value: 'rgba(30, 144, 255, 1)',
placeholder: '请选择字体颜色'
}
},
isResizable: true,
element: 'ver',
moved: false,
hpx: 155,
wpx: 329
} }
] ]
export default log export default log