@ -22,32 +22,17 @@
< div class = "h-70px flex items-center justify-end lt-sm:mt-10px" >
< div class = "px-8px text-right" >
< div class = "mb-16px text-14px text-gray-400" > { { t ( 'workplace.project' ) } } < / div >
< CountTo
class = "text-20px"
: start - val = "0"
: end - val = "totalSate.project"
: duration = "2600"
/ >
< CountTo class = "text-20px" :start-val ="0" :end-val ="totalSate.project" :duration ="2600" / >
< / div >
< el -divider direction = "vertical" / >
< div class = "px-8px text-right" >
< div class = "mb-16px text-14px text-gray-400" > { { t ( 'workplace.toDo' ) } } < / div >
< CountTo
class = "text-20px"
: start - val = "0"
: end - val = "totalSate.todo"
: duration = "2600"
/ >
< CountTo class = "text-20px" :start-val ="0" :end-val ="totalSate.todo" :duration ="2600" / >
< / div >
< el -divider direction = "vertical" border -style = " dashed " / >
< div class = "px-8px text-right" >
< div class = "mb-16px text-14px text-gray-400" > { { t ( 'workplace.access' ) } } < / div >
< CountTo
class = "text-20px"
: start - val = "0"
: end - val = "totalSate.access"
: duration = "2600"
/ >
< CountTo class = "text-20px" :start-val ="0" :end-val ="totalSate.access" :duration ="2600" / >
< / div >
< / div >
< / e l - c o l >
@ -55,9 +40,20 @@
< / e l - s k e l e t o n >
< / e l - c a r d >
< / div >
< div class = "flex flex-wrap gap-4" style = "margin: 2 0px 0;">
< div class = "flex flex-wrap gap-4" style = "margin: 1 0px 0;">
< el -card style = "width: 420px;text-align: center;cursor: pointer;" shadow = "hover" @click ="goToXXLJob" > 任务调度中心 < / el -card >
< / div >
<!-- 新增的静态图片部分 -- >
< div >
< el -card style = "width: 100%; text-align: center;" shadow = "never" >
< div style = "overflow: hidden; height: calc(100% - 2px);" >
< el -image :src ="luduViewImage" fit = "contain" style = "width: 100%; transform: translateY(-2px);" / >
< / div >
< / e l - c a r d >
< / div >
<!-- < el -row class = "mt-8px" :gutter ="8" justify = "space-between" >
< el -col :xl ="16" :lg ="16" :md ="24" :sm ="24" :xs ="24" class = "mb-8px" >
< el -card shadow = "never" >
@ -74,323 +70,328 @@
< / e l - l i n k >
< / div >
< / template >
< el -skeleton :loading ="loading" animated >
< el -row >
< el -col
v - for = "(item, index) in projects"
: key = "`card-${index}`"
: xl = "8"
: lg = "8"
: md = "8"
: sm = "24"
: xs = "24"
>
< el -card shadow = "hover" class = "mr-5px mt-5px" >
< div class = "flex items-center" >
< Icon :icon ="item.icon" :size ="25" class = "mr-8px" / >
< span class = "text-16px" > { { item . name } } < / span >
< / div >
< div class = "mt-12px text-9px text-gray-400" > { { t ( item . message ) } } < / div >
< div class = "mt-12px flex justify-between text-12px text-gray-400" >
< span > { { item . personal } } < / span >
< span > { { formatTime ( item . time , 'yyyy-MM-dd' ) } } < / span >
< / div >
< / e l - c a r d >
< / e l - c o l >
< / e l - r o w >
< / e l - s k e l e t o n >
< / e l - c a r d >
< el -card shadow = "never" class = "mt-8px" >
< el -skeleton :loading ="loading" animated >
< el -row :gutter ="20" justify = "space-between" >
< el -col :xl ="10" :lg ="10" :md ="24" :sm ="24" :xs ="24" >
< el -card shadow = "hover" class = "mb-8px" >
< el -skeleton :loading ="loading" animated >
< Echart :options ="pieOptionsData" :height ="280" / >
< / e l - s k e l e t o n >
< / e l - c a r d >
< / e l - c o l >
< el -col :xl ="14" :lg ="14" :md ="24" :sm ="24" :xs ="24" >
< el -card shadow = "hover" class = "mb-8px" >
< el -skeleton :loading ="loading" animated >
< Echart :options ="barOptionsData" :height ="280" / >
< / e l - s k e l e t o n >
< / e l - c a r d >
< / e l - c o l >
< / e l - r o w >
< / e l - s k e l e t o n >
< el -skeleton :loading ="loading" animated >
< el -row >
< el -col v-for ="(item, index) in projects" :key="`card-${index}`" :xl="8" :lg="8" :md="8" :sm="24" :xs ="24" >
< el -card shadow = "hover" class = "mr-5px mt-5px" >
< div class = "flex items-center" >
< Icon :icon ="item.icon" :size ="25" class = "mr-8px" / >
< span class = "text-16px" > { { item . name } } < / span >
< / div >
< div class = "mt-12px text-9px text-gray-400" > { { t ( item . message ) } } < / div >
< div class = "mt-12px flex justify-between text-12px text-gray-400" >
< span > { { item . personal } } < / span >
< span > { { formatTime ( item . time , 'yyyy-MM-dd' ) } } < / span >
< / div >
< / e l - c a r d >
< / e l - c o l >
< el -col :xl ="8" :lg ="8" :md ="24" :sm ="24" :xs ="24" class = "mb-8px" >
< el -card shadow = "never" >
< template # header >
< / e l - r o w >
< / e l - s k e l e t o n >
< / e l - c a r d >
< el -card shadow = "never" class = "mt-8px" >
< el -skeleton :loading ="loading" animated >
< el -row :gutter ="20" justify = "space-between" >
< el -col :xl ="10" :lg ="10" :md ="24" :sm ="24" :xs ="24" >
< el -card shadow = "hover" class = "mb-8px" >
< el -skeleton :loading ="loading" animated >
< Echart :options ="pieOptionsData" :height ="280" / >
< / e l - s k e l e t o n >
< / e l - c a r d >
< / e l - c o l >
< el -col :xl ="14" :lg ="14" :md ="24" :sm ="24" :xs ="24" >
< el -card shadow = "hover" class = "mb-8px" >
< el -skeleton :loading ="loading" animated >
< Echart :options ="barOptionsData" :height ="280" / >
< / e l - s k e l e t o n >
< / e l - c a r d >
< / e l - c o l >
< / e l - r o w >
< / e l - s k e l e t o n >
< / e l - c a r d >
< / e l - c o l >
< el -col :xl ="8" :lg ="8" :md ="24" :sm ="24" :xs ="24" class = "mb-8px" >
< el -card shadow = "never" >
< template # header >
< div class = "h-3 flex justify-between" >
< span > { { t ( 'workplace.shortcutOperation' ) } } < / span >
< / div >
< / template >
< el -skeleton :loading ="loading" animated >
< el -row >
< el -col v-for ="item in shortcut" :key="`team-${item.name}`" :span="8" class="mb-8px" >
< div class = "flex items-center" >
< Icon :icon ="item.icon" class = "mr-8px" / >
< el -link type = "default" :underline ="false" @click ="setWatermark(item.name)" >
{ { item . name } }
< / e l - l i n k >
< / div >
< / e l - c o l >
< / e l - r o w >
< / e l - s k e l e t o n >
< / e l - c a r d >
< el -card shadow = "never" class = "mt-8px" >
< template # header >
< el -skeleton :loading ="loading" animated >
< el -row >
< el -col v-for ="item in shortcut" :key="`team-${item.name}`" :span="8" class="mb-8px" >
< div class = "flex items-center" >
< Icon :icon ="item.icon" class = "mr-8px" / >
< el -link type = "default" :underline ="false" @click ="setWatermark(item.name)" >
{ { item . name } }
< / e l - l i n k >
< / div >
< / e l - c o l >
< / e l - r o w >
< / e l - s k e l e t o n >
< / e l - c a r d >
< el -card shadow = "never" class = "mt-8px" >
< template # header >
< div class = "h-3 flex justify-between" >
< span > { { t ( 'workplace.notice' ) } } < / span >
< el -link type = "primary" :underline ="false" > { { t ( 'action.more' ) } } < / e l - l i n k >
< / div >
< / template >
< el -skeleton :loading ="loading" animated >
< div v-for ="(item, index) in notice" :key="`dynamics-${index}`" >
< div class = "flex items-center" >
< el -avatar :src ="avatar" :size ="35" class = "mr-16px" >
< img src = "@/assets/imgs/avatar.gif" alt = "" / >
< / e l - a v a t a r >
< div >
< div class = "text-14px" >
< Highlight : keys = "item.keys.map((v) => t(v))" >
{ { item . type } } : { { item . title } }
< / Highlight >
< / div >
< div class = "mt-16px text-12px text-gray-400" >
{ { formatTime ( item . date , 'yyyy-MM-dd' ) } }
< / div >
< / div >
< el -skeleton :loading ="loading" animated >
< div v-for ="(item, index) in notice" :key="`dynamics-${index}`" >
< div class = "flex items-center" >
< el -avatar :src ="avatar" :size ="35" class = "mr-16px" >
< img src = "@/assets/imgs/avatar.gif" alt = "" / >
< / e l - a v a t a r >
< div >
< div class = "text-14px" >
< Highlight : keys = "item.keys.map((v) => t(v))" >
{ { item . type } } : { { item . title } }
< / Highlight >
< / div >
< div class = "mt-16px text-12px text-gray-400" >
{ { formatTime ( item . date , 'yyyy-MM-dd' ) } }
< / div >
< el -divider / >
< / div >
< / e l - s k e l e t o n >
< / e l - c a r d >
< / e l - c o l >
< / e l - r o w > - - >
< / div >
< el -divider / >
< / div >
< / e l - s k e l e t o n >
< / e l - c a r d >
< / e l - c o l >
< / e l - r o w > - - >
< / template >
< script lang = "ts" setup >
import { set } from 'lodash-es'
import { EChartsOption } from 'echarts'
import { formatTime } from '@/utils'
import { set } from 'lodash-es'
import { EChartsOption } from 'echarts'
import { formatTime } from '@/utils'
import luduView from '@/assets/imgs/ludu_view.png'
import { useUserStore } from '@/store/modules/user'
import { useWatermark } from '@/hooks/web/useWatermark'
import type { WorkplaceTotal , Project , Notice , Shortcut } from './types'
import { pieOptions , barOptions } from './echarts-data'
import { useUserStore } from '@/store/modules/user'
import { useWatermark } from '@/hooks/web/useWatermark'
import type { WorkplaceTotal , Project , Notice , Shortcut } from './types'
import { pieOptions , barOptions } from './echarts-data'
defineOptions ( { name : 'Home' } )
defineOptions ( { name : 'Home' } )
const { t } = useI18n ( )
const userStore = useUserStore ( )
const { setWatermark } = useWatermark ( )
const loading = ref ( true )
const avatar = userStore . getUser . avatar
const username = userStore . getUser . nickname
const pieOptionsData = reactive < EChartsOption > ( pieOptions ) as EChartsOption
/ / 获 取 统 计 数
let totalSate = reactive < WorkplaceTotal > ( {
project : 0 ,
access : 0 ,
todo : 0
} )
const getCount = async ( ) => {
const data = {
project : 40 ,
access : 2340 ,
todo : 10
}
totalSate = Object . assign ( totalSate , data )
}
/ / 获 取 项 目 数
let projects = reactive < Project [ ] > ( [ ] )
const getProject = async ( ) => {
const data = [
{
name : 'ruoyi-vue-pro' ,
icon : 'akar-icons:github-fill' ,
message : 'https://github.com/YunaiV/ruoyi-vue-pro' ,
personal : 'Spring Boot 单体架构' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-admin-vue3' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-vue3' ,
personal : 'Vue3 + element-plus' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-admin-vben' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-vben' ,
personal : 'Vue3 + vben(antd)' ,
time : new Date ( )
} ,
{
name : 'yudao-cloud' ,
icon : 'akar-icons:github' ,
message : 'https://github.com/YunaiV/yudao-cloud' ,
personal : 'Spring Cloud 微服务架构' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-mall-uniapp' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-uniapp' ,
personal : 'Vue3 + uniapp' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-admin-vue2' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-vue2' ,
personal : 'Vue2 + element-ui' ,
time : new Date ( )
}
]
projects = Object . assign ( projects , data )
}
/ / 获 取 通 知 公 告
let notice = reactive < Notice [ ] > ( [ ] )
const getNotice = async ( ) => {
const data = [
{
title : '系统支持 JDK 8/17/21, Vue 2/3' ,
type : '通知' ,
keys : [ '通知' , '8' , '17' , '21' , '2' , '3' ] ,
date : new Date ( )
} ,
{
title : '后端提供 Spring Boot 2.7/3.2 + Cloud 双架构' ,
type : '公告' ,
keys : [ '公告' , 'Boot' , 'Cloud' ] ,
date : new Date ( )
} ,
{
title : '全部开源,个人与企业可 100% 直接使用,无需授权' ,
type : '通知' ,
keys : [ '通知' , '无需授权' ] ,
date : new Date ( )
} ,
{
title : '国内使用最广泛的快速开发平台,超 300+ 人贡献' ,
type : '公告' ,
keys : [ '公告' , '最广泛' ] ,
date : new Date ( )
}
]
notice = Object . assign ( notice , data )
}
/ / 获 取 快 捷 入 口
let shortcut = reactive < Shortcut [ ] > ( [ ] )
const getShortcut = async ( ) => {
const data = [
{
name : 'Github' ,
icon : 'akar-icons:github-fill' ,
url : 'github.io'
} ,
{
name : 'Vue' ,
icon : 'logos:vue' ,
url : 'vuejs.org'
} ,
{
name : 'Vite' ,
icon : 'vscode-icons:file-type-vite' ,
url : 'https://vitejs.dev/'
} ,
{
name : 'Angular' ,
icon : 'logos:angular-icon' ,
url : 'github.io'
} ,
{
name : 'React' ,
icon : 'logos:react' ,
url : 'github.io'
} ,
{
name : 'Webpack' ,
icon : 'logos:webpack' ,
url : 'github.io'
}
]
shortcut = Object . assign ( shortcut , data )
}
/ / 用 户 来 源
const getUserAccessSource = async ( ) => {
const data = [
{ value : 335 , name : 'analysis.directAccess' } ,
{ value : 310 , name : 'analysis.mailMarketing' } ,
{ value : 234 , name : 'analysis.allianceAdvertising' } ,
{ value : 135 , name : 'analysis.videoAdvertising' } ,
{ value : 1548 , name : 'analysis.searchEngines' }
]
set (
pieOptionsData ,
'legend.data' ,
data . map ( ( v ) => t ( v . name ) )
)
pieOptionsData ! . series ! [ 0 ] . data = data . map ( ( v ) => {
return {
name : t ( v . name ) ,
value : v . value
}
const luduViewImage = ref ( luduView ) ;
const { t } = useI18n ( )
const userStore = useUserStore ( )
const { setWatermark } = useWatermark ( )
const loading = ref ( true )
const avatar = userStore . getUser . avatar
const username = userStore . getUser . nickname
const pieOptionsData = reactive < EChartsOption > ( pieOptions ) as EChartsOption
/ / 获 取 统 计 数
let totalSate = reactive < WorkplaceTotal > ( {
project : 0 ,
access : 0 ,
todo : 0
} )
}
const barOptionsData = reactive < EChartsOption > ( barOptions ) as EChartsOption
/ / 周 活 跃 量
const getWeeklyUserActivity = async ( ) => {
const data = [
{ value : 13253 , name : 'analysis.monday' } ,
{ value : 34235 , name : 'analysis.tuesday' } ,
{ value : 26321 , name : 'analysis.wednesday' } ,
{ value : 12340 , name : 'analysis.thursday' } ,
{ value : 24643 , name : 'analysis.friday' } ,
{ value : 1322 , name : 'analysis.saturday' } ,
{ value : 1324 , name : 'analysis.sunday' }
]
set (
barOptionsData ,
'xAxis.data' ,
data . map ( ( v ) => t ( v . name ) )
)
set ( barOptionsData , 'series' , [
{
name : t ( 'analysis.activeQuantity' ) ,
data : data . map ( ( v ) => v . value ) ,
type : 'bar'
const getCount = async ( ) => {
const data = {
project : 40 ,
access : 2340 ,
todo : 10
}
] )
}
totalSate = Object . assign ( totalSate , data )
}
const getAllApi = async ( ) => {
await Promise . all ( [
getCount ( ) ,
getProject ( ) ,
getNotice ( ) ,
getShortcut ( ) ,
getUserAccessSource ( ) ,
getWeeklyUserActivity ( )
] )
loading . value = false
}
/ / 获 取 项 目 数
let projects = reactive < Project [ ] > ( [ ] )
const getProject = async ( ) => {
const data = [
{
name : 'ruoyi-vue-pro' ,
icon : 'akar-icons:github-fill' ,
message : 'https://github.com/YunaiV/ruoyi-vue-pro' ,
personal : 'Spring Boot 单体架构' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-admin-vue3' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-vue3' ,
personal : 'Vue3 + element-plus' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-admin-vben' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-vben' ,
personal : 'Vue3 + vben(antd)' ,
time : new Date ( )
} ,
{
name : 'yudao-cloud' ,
icon : 'akar-icons:github' ,
message : 'https://github.com/YunaiV/yudao-cloud' ,
personal : 'Spring Cloud 微服务架构' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-mall-uniapp' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-uniapp' ,
personal : 'Vue3 + uniapp' ,
time : new Date ( )
} ,
{
name : 'yudao-ui-admin-vue2' ,
icon : 'logos:vue' ,
message : 'https://github.com/yudaocode/yudao-ui-admin-vue2' ,
personal : 'Vue2 + element-ui' ,
time : new Date ( )
}
]
projects = Object . assign ( projects , data )
}
const goToXXLJob = async ( ) => {
window . open ( 'http://127.0.0.1:9090/xxl-job-admin/' ) ;
}
getAllApi ( )
/ / 获 取 通 知 公 告
let notice = reactive < Notice [ ] > ( [ ] )
const getNotice = async ( ) => {
const data = [
{
title : '系统支持 JDK 8/17/21, Vue 2/3' ,
type : '通知' ,
keys : [ '通知' , '8' , '17' , '21' , '2' , '3' ] ,
date : new Date ( )
} ,
{
title : '后端提供 Spring Boot 2.7/3.2 + Cloud 双架构' ,
type : '公告' ,
keys : [ '公告' , 'Boot' , 'Cloud' ] ,
date : new Date ( )
} ,
{
title : '全部开源,个人与企业可 100% 直接使用,无需授权' ,
type : '通知' ,
keys : [ '通知' , '无需授权' ] ,
date : new Date ( )
} ,
{
title : '国内使用最广泛的快速开发平台,超 300+ 人贡献' ,
type : '公告' ,
keys : [ '公告' , '最广泛' ] ,
date : new Date ( )
}
]
notice = Object . assign ( notice , data )
}
/ / 获 取 快 捷 入 口
let shortcut = reactive < Shortcut [ ] > ( [ ] )
const getShortcut = async ( ) => {
const data = [
{
name : 'Github' ,
icon : 'akar-icons:github-fill' ,
url : 'github.io'
} ,
{
name : 'Vue' ,
icon : 'logos:vue' ,
url : 'vuejs.org'
} ,
{
name : 'Vite' ,
icon : 'vscode-icons:file-type-vite' ,
url : 'https://vitejs.dev/'
} ,
{
name : 'Angular' ,
icon : 'logos:angular-icon' ,
url : 'github.io'
} ,
{
name : 'React' ,
icon : 'logos:react' ,
url : 'github.io'
} ,
{
name : 'Webpack' ,
icon : 'logos:webpack' ,
url : 'github.io'
}
]
shortcut = Object . assign ( shortcut , data )
}
/ / 用 户 来 源
const getUserAccessSource = async ( ) => {
const data = [
{ value : 335 , name : 'analysis.directAccess' } ,
{ value : 310 , name : 'analysis.mailMarketing' } ,
{ value : 234 , name : 'analysis.allianceAdvertising' } ,
{ value : 135 , name : 'analysis.videoAdvertising' } ,
{ value : 1548 , name : 'analysis.searchEngines' }
]
set (
pieOptionsData ,
'legend.data' ,
data . map ( ( v ) => t ( v . name ) )
)
pieOptionsData ! . series ! [ 0 ] . data = data . map ( ( v ) => {
return {
name : t ( v . name ) ,
value : v . value
}
} )
}
const barOptionsData = reactive < EChartsOption > ( barOptions ) as EChartsOption
/ / 周 活 跃 量
const getWeeklyUserActivity = async ( ) => {
const data = [
{ value : 13253 , name : 'analysis.monday' } ,
{ value : 34235 , name : 'analysis.tuesday' } ,
{ value : 26321 , name : 'analysis.wednesday' } ,
{ value : 12340 , name : 'analysis.thursday' } ,
{ value : 24643 , name : 'analysis.friday' } ,
{ value : 1322 , name : 'analysis.saturday' } ,
{ value : 1324 , name : 'analysis.sunday' }
]
set (
barOptionsData ,
'xAxis.data' ,
data . map ( ( v ) => t ( v . name ) )
)
set ( barOptionsData , 'series' , [
{
name : t ( 'analysis.activeQuantity' ) ,
data : data . map ( ( v ) => v . value ) ,
type : 'bar'
}
] )
}
const getAllApi = async ( ) => {
await Promise . all ( [
getCount ( ) ,
getProject ( ) ,
getNotice ( ) ,
getShortcut ( ) ,
getUserAccessSource ( ) ,
getWeeklyUserActivity ( )
] )
loading . value = false
}
const goToXXLJob = async ( ) => {
window . open ( 'https://mt.ptzykjgs.com/xxl-job-admin/' ) ;
}
getAllApi ( )
< / script >
< style scoped >
. image - container {
width : 100 % ;
display : flex ;
justify - content : center ;
}
. el - image img {
width : 100 % ;
height : auto ;
}
< / style >