375 lines
9.6 KiB
Vue
375 lines
9.6 KiB
Vue
<template>
|
|
<div class="app-container">
|
|
<a-card class="general-card" title="功能使用情况" :bordered="false">
|
|
<a-row :gutter="16">
|
|
<a-col :span="24">
|
|
<a-card title="功能模块使用频率" :bordered="false">
|
|
<div ref="moduleUsageChart" style="height: 400px"></div>
|
|
</a-card>
|
|
</a-col>
|
|
</a-row>
|
|
|
|
<a-divider />
|
|
|
|
<a-row :gutter="16">
|
|
<a-col :span="12">
|
|
<a-card title="各部门功能使用分布" :bordered="false">
|
|
<div ref="departmentUsageChart" style="height: 350px"></div>
|
|
</a-card>
|
|
</a-col>
|
|
<a-col :span="12">
|
|
<a-card title="功能使用时长占比" :bordered="false">
|
|
<div ref="usageTimeChart" style="height: 350px"></div>
|
|
</a-card>
|
|
</a-col>
|
|
</a-row>
|
|
|
|
<a-divider />
|
|
|
|
<a-card title="功能使用详情" :bordered="false">
|
|
<a-table :columns="functionColumns" :data-source="functionData" :pagination="{ pageSize: 10 }">
|
|
<template #bodyCell="{ column, record }">
|
|
<template v-if="column.dataIndex === 'usageRate'">
|
|
<a-progress :percent="record.usageRate" :stroke-color="getUsageRateColor(record.usageRate)" />
|
|
</template>
|
|
<template v-if="column.dataIndex === 'trend'">
|
|
<span :style="{ color: getTrendColor(record.trend) }">
|
|
{{ record.trend >= 0 ? '+' : '' }}{{ record.trend }}%
|
|
<arrow-up-outlined v-if="record.trend > 0" style="color: #52c41a" />
|
|
<arrow-down-outlined v-if="record.trend < 0" style="color: #ff4d4f" />
|
|
<minus-outlined v-if="record.trend === 0" style="color: #1890ff" />
|
|
</span>
|
|
</template>
|
|
</template>
|
|
</a-table>
|
|
</a-card>
|
|
</a-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, onMounted, nextTick } from 'vue'
|
|
import * as echarts from 'echarts'
|
|
// 由于找不到 @ant-design/icons-vue 模块,注释掉相关导入
|
|
// import { ArrowUpOutlined, ArrowDownOutlined, MinusOutlined } from '@ant-design/icons-vue'
|
|
|
|
const moduleUsageChart = ref(null)
|
|
const departmentUsageChart = ref(null)
|
|
const usageTimeChart = ref(null)
|
|
|
|
// 功能使用详情表格数据
|
|
const functionColumns = [
|
|
{
|
|
title: '功能模块',
|
|
dataIndex: 'module',
|
|
key: 'module',
|
|
},
|
|
{
|
|
title: '子功能',
|
|
dataIndex: 'function',
|
|
key: 'function',
|
|
},
|
|
{
|
|
title: '使用次数',
|
|
dataIndex: 'usageCount',
|
|
key: 'usageCount',
|
|
sorter: (a, b) => a.usageCount - b.usageCount,
|
|
},
|
|
{
|
|
title: '使用率',
|
|
dataIndex: 'usageRate',
|
|
key: 'usageRate',
|
|
sorter: (a, b) => a.usageRate - b.usageRate,
|
|
},
|
|
{
|
|
title: '平均使用时长',
|
|
dataIndex: 'averageTime',
|
|
key: 'averageTime',
|
|
sorter: (a, b) => a.averageTime - b.averageTime,
|
|
},
|
|
{
|
|
title: '环比上月',
|
|
dataIndex: 'trend',
|
|
key: 'trend',
|
|
sorter: (a, b) => a.trend - b.trend,
|
|
}
|
|
]
|
|
|
|
const functionData = [
|
|
{
|
|
key: '1',
|
|
module: '组织架构',
|
|
function: '人员管理',
|
|
usageCount: 1245,
|
|
usageRate: 92,
|
|
averageTime: '15分钟',
|
|
trend: 5.2
|
|
},
|
|
{
|
|
key: '2',
|
|
module: '组织架构',
|
|
function: '角色管理',
|
|
usageCount: 865,
|
|
usageRate: 78,
|
|
averageTime: '12分钟',
|
|
trend: 3.8
|
|
},
|
|
{
|
|
key: '3',
|
|
module: '资产管理',
|
|
function: '设备管理',
|
|
usageCount: 1056,
|
|
usageRate: 85,
|
|
averageTime: '18分钟',
|
|
trend: 7.5
|
|
},
|
|
{
|
|
key: '4',
|
|
module: '资产管理',
|
|
function: '库存管理',
|
|
usageCount: 932,
|
|
usageRate: 80,
|
|
averageTime: '14分钟',
|
|
trend: -2.1
|
|
},
|
|
{
|
|
key: '5',
|
|
module: '产品与服务',
|
|
function: '产品管理',
|
|
usageCount: 1120,
|
|
usageRate: 88,
|
|
averageTime: '20分钟',
|
|
trend: 4.3
|
|
},
|
|
{
|
|
key: '6',
|
|
module: '产品与服务',
|
|
function: '服务管理',
|
|
usageCount: 986,
|
|
usageRate: 82,
|
|
averageTime: '16分钟',
|
|
trend: 0
|
|
},
|
|
{
|
|
key: '7',
|
|
module: '项目管理',
|
|
function: '项目模板',
|
|
usageCount: 1320,
|
|
usageRate: 95,
|
|
averageTime: '25分钟',
|
|
trend: 8.7
|
|
},
|
|
{
|
|
key: '8',
|
|
module: '项目管理',
|
|
function: '合同管理',
|
|
usageCount: 1150,
|
|
usageRate: 90,
|
|
averageTime: '22分钟',
|
|
trend: 6.2
|
|
},
|
|
{
|
|
key: '9',
|
|
module: '施工操作台',
|
|
function: '外业施工',
|
|
usageCount: 1280,
|
|
usageRate: 93,
|
|
averageTime: '30分钟',
|
|
trend: 9.5
|
|
},
|
|
{
|
|
key: '10',
|
|
module: '施工操作台',
|
|
function: '数据处理',
|
|
usageCount: 1180,
|
|
usageRate: 91,
|
|
averageTime: '28分钟',
|
|
trend: 5.8
|
|
},
|
|
{
|
|
key: '11',
|
|
module: '聊天平台',
|
|
function: '消息管理',
|
|
usageCount: 1420,
|
|
usageRate: 98,
|
|
averageTime: '35分钟',
|
|
trend: 12.3
|
|
},
|
|
{
|
|
key: '12',
|
|
module: '企业设置',
|
|
function: '企业信息',
|
|
usageCount: 720,
|
|
usageRate: 65,
|
|
averageTime: '10分钟',
|
|
trend: -1.5
|
|
}
|
|
]
|
|
|
|
// 颜色处理函数
|
|
const getUsageRateColor = (rate) => {
|
|
if (rate >= 90) return '#52c41a'
|
|
if (rate >= 70) return '#1890ff'
|
|
return '#faad14'
|
|
}
|
|
|
|
const getTrendColor = (trend) => {
|
|
if (trend > 0) return '#52c41a'
|
|
if (trend < 0) return '#ff4d4f'
|
|
return '#1890ff'
|
|
}
|
|
|
|
onMounted(() => {
|
|
// 使用 nextTick 确保 DOM 已完全渲染
|
|
nextTick(() => {
|
|
// 初始化功能模块使用频率图表
|
|
if (moduleUsageChart.value) {
|
|
const moduleChart = echarts.init(moduleUsageChart.value)
|
|
moduleChart.setOption({
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
axisPointer: {
|
|
type: 'shadow'
|
|
}
|
|
},
|
|
legend: {
|
|
data: ['使用次数', '使用人数']
|
|
},
|
|
grid: {
|
|
left: '3%',
|
|
right: '4%',
|
|
bottom: '3%',
|
|
containLabel: true
|
|
},
|
|
xAxis: {
|
|
type: 'value'
|
|
},
|
|
yAxis: {
|
|
type: 'category',
|
|
data: ['组织架构', '资产管理', '产品与服务', '项目管理', '施工操作台', '聊天平台', '企业设置', '系统资源管理']
|
|
},
|
|
series: [
|
|
{
|
|
name: '使用次数',
|
|
type: 'bar',
|
|
data: [2110, 1988, 2106, 2470, 2460, 1420, 720, 650]
|
|
},
|
|
{
|
|
name: '使用人数',
|
|
type: 'bar',
|
|
data: [320, 302, 315, 335, 340, 356, 120, 85]
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
// 初始化各部门功能使用分布图表
|
|
if (departmentUsageChart.value) {
|
|
const departmentChart = echarts.init(departmentUsageChart.value)
|
|
departmentChart.setOption({
|
|
tooltip: {
|
|
trigger: 'item'
|
|
},
|
|
legend: {
|
|
orient: 'vertical',
|
|
left: 'left'
|
|
},
|
|
series: [
|
|
{
|
|
name: '部门使用分布',
|
|
type: 'pie',
|
|
radius: '70%',
|
|
data: [
|
|
{ value: 35, name: '技术部' },
|
|
{ value: 25, name: '市场部' },
|
|
{ value: 20, name: '销售部' },
|
|
{ value: 10, name: '人事部' },
|
|
{ value: 10, name: '财务部' }
|
|
],
|
|
emphasis: {
|
|
itemStyle: {
|
|
shadowBlur: 10,
|
|
shadowOffsetX: 0,
|
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
}
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
// 初始化功能使用时长占比图表
|
|
if (usageTimeChart.value) {
|
|
const timeChart = echarts.init(usageTimeChart.value)
|
|
timeChart.setOption({
|
|
tooltip: {
|
|
trigger: 'item'
|
|
},
|
|
legend: {
|
|
orient: 'vertical',
|
|
left: 'left'
|
|
},
|
|
series: [
|
|
{
|
|
name: '使用时长占比',
|
|
type: 'pie',
|
|
radius: ['40%', '70%'],
|
|
avoidLabelOverlap: false,
|
|
itemStyle: {
|
|
borderRadius: 10,
|
|
borderColor: '#fff',
|
|
borderWidth: 2
|
|
},
|
|
label: {
|
|
show: false,
|
|
position: 'center'
|
|
},
|
|
emphasis: {
|
|
label: {
|
|
show: true,
|
|
fontSize: '16',
|
|
fontWeight: 'bold'
|
|
}
|
|
},
|
|
labelLine: {
|
|
show: false
|
|
},
|
|
data: [
|
|
{ value: 20, name: '组织架构' },
|
|
{ value: 15, name: '资产管理' },
|
|
{ value: 15, name: '产品与服务' },
|
|
{ value: 20, name: '项目管理' },
|
|
{ value: 20, name: '施工操作台' },
|
|
{ value: 5, name: '聊天平台' },
|
|
{ value: 3, name: '企业设置' },
|
|
{ value: 2, name: '系统资源管理' }
|
|
]
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
// 监听窗口大小变化,调整图表大小
|
|
window.addEventListener('resize', () => {
|
|
if (moduleUsageChart.value) {
|
|
const moduleChart = echarts.getInstanceByDom(moduleUsageChart.value)
|
|
moduleChart?.resize()
|
|
}
|
|
if (departmentUsageChart.value) {
|
|
const departmentChart = echarts.getInstanceByDom(departmentUsageChart.value)
|
|
departmentChart?.resize()
|
|
}
|
|
if (usageTimeChart.value) {
|
|
const timeChart = echarts.getInstanceByDom(usageTimeChart.value)
|
|
timeChart?.resize()
|
|
}
|
|
})
|
|
})
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.general-card {
|
|
margin-bottom: 20px;
|
|
}
|
|
</style> |