You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/ui/page/index.html

698 lines
16 KiB
HTML

<!doctype html>
<html>
<head>
<title>项目与用户管理 Dashboard</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f7fa;
color: #333;
}
.dashboard {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
}
.header h1 {
font-size: 28px;
color: #2c3e50;
margin: 0;
}
.header .date {
color: #7f8c8d;
font-size: 14px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
transition: transform 0.3s, box-shadow 0.3s;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.stat-card .icon {
width: 50px;
height: 50px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 15px;
font-size: 20px;
}
.stat-card .value {
font-size: 28px;
font-weight: 700;
margin-bottom: 5px;
}
.stat-card .label {
color: #7f8c8d;
font-size: 14px;
}
.stat-card .trend {
display: flex;
align-items: center;
margin-top: 10px;
font-size: 13px;
}
.trend.up {
color: #2ecc71;
}
.trend.down {
color: #e74c3c;
}
.charts-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 30px;
}
.chart-container {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}
.chart-container h2 {
margin-top: 0;
font-size: 18px;
color: #2c3e50;
}
.chart {
width: 100%;
height: 300px;
}
.recent-activities {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}
.recent-activities h2 {
margin-top: 0;
font-size: 18px;
color: #2c3e50;
}
.activity-item {
display: flex;
padding: 15px 0;
border-bottom: 1px solid #eee;
}
.activity-item:last-child {
border-bottom: none;
}
.activity-icon {
width: 40px;
height: 40px;
border-radius: 50%;
background: #f1f5f9;
display: flex;
align-items: center;
justify-content: center;
margin-right: 15px;
color: #3b82f6;
}
.activity-content {
flex: 1;
}
.activity-title {
font-weight: 600;
margin-bottom: 5px;
}
.activity-time {
color: #7f8c8d;
font-size: 13px;
}
.badge {
display: inline-block;
padding: 3px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
}
.badge-primary {
background: #e3f2fd;
color: #1976d2;
}
.badge-success {
background: #e8f5e9;
color: #388e3c;
}
.badge-warning {
background: #fff8e1;
color: #ffa000;
}
</style>
<body>
<div class="dashboard">
<div class="header">
<h1>项目与用户管理 Dashboard</h1>
<div class="date">{{ currentDate }}</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="icon" style="background: #e3f2fd; color: #1976d2;">
<i class="bi bi-people"></i>
</div>
<div class="value">{{ totalUsers }}</div>
<div class="label">总用户数</div>
<div class="trend up">
<i class="bi bi-arrow-up"></i> {{ userGrowthRate }}% 较上月
</div>
</div>
<div class="stat-card">
<div class="icon" style="background: #e8f5e9; color: #388e3c;">
<i class="bi bi-folder"></i>
</div>
<div class="value">{{ activeProjects }}</div>
<div class="label">活跃项目</div>
<div class="trend up">
<i class="bi bi-arrow-up"></i> {{ projectGrowthRate }}% 较上月
</div>
</div>
<div class="stat-card">
<div class="icon" style="background: #fff8e1; color: #ffa000;">
<i class="bi bi-clock-history"></i>
</div>
<div class="value">{{ pendingTasks }}</div>
<div class="label">待处理任务</div>
<div class="trend down">
<i class="bi bi-arrow-down"></i> {{ taskChangeRate }}% 较上周
</div>
</div>
<div class="stat-card">
<div class="icon" style="background: #f3e5f5; color: #8e24aa;">
<i class="bi bi-graph-up"></i>
</div>
<div class="value">{{ completionRate }}%</div>
<div class="label">项目完成率</div>
<div class="trend up">
<i class="bi bi-arrow-up"></i> {{ completionRateChange }}% 较上月
</div>
</div>
</div>
<div class="charts-grid">
<div class="chart-container">
<h2>用户增长趋势</h2>
<div id="userGrowthChart" class="chart"></div>
</div>
<div class="chart-container">
<h2>项目状态分布</h2>
<div id="projectStatusChart" class="chart"></div>
</div>
</div>
<div class="charts-grid">
<div class="chart-container">
<h2>用户活跃度</h2>
<div id="userActivityChart" class="chart"></div>
</div>
<div class="chart-container">
<h2>任务完成情况</h2>
<div id="taskCompletionChart" class="chart"></div>
</div>
</div>
<div class="recent-activities">
<h2>最近活动</h2>
<div v-for="activity in recentActivities" class="activity-item">
<div class="activity-icon">
<i :class="'bi bi-' + activity.icon"></i>
</div>
<div class="activity-content">
<div class="activity-title">
{{ activity.title }}
<span v-if="activity.type" :class="'badge badge-' + activity.type">{{ activity.typeLabel }}</span>
</div>
<div class="activity-time">{{ activity.time }}</div>
</div>
</div>
</div>
</div>
<script setup>
// 统计数据
totalUsers = 1248;
activeProjects = 86;
pendingTasks = 342;
completionRate = 78;
// 增长率
userGrowthRate = 12.5;
projectGrowthRate = 8.3;
taskChangeRate = 5.2;
completionRateChange = 3.7;
// 当前日期
currentDate = new Date().toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
});
// 最近活动数据
recentActivities = [
{
icon: 'plus-circle',
title: '新用户 "张小明" 注册',
type: 'primary',
typeLabel: '用户',
time: '10分钟前'
},
{
icon: 'folder-plus',
title: '新项目 "电商平台重构" 创建',
type: 'success',
typeLabel: '项目',
time: '35分钟前'
},
{
icon: 'check-circle',
title: '项目 "CRM系统升级" 完成',
type: 'success',
typeLabel: '项目',
time: '2小时前'
},
{
icon: 'exclamation-triangle',
title: '任务 "用户权限模块" 逾期',
type: 'warning',
typeLabel: '任务',
time: '5小时前'
},
{
icon: 'person-plus',
title: '团队成员 "李华" 加入项目',
type: 'primary',
typeLabel: '团队',
time: '昨天'
}
];
// 图表数据
userGrowthData = {
months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月'],
values: [820, 890, 920, 950, 1020, 1120, 1248]
};
projectStatusData = [
{value: 32, name: '进行中'},
{value: 24, name: '已完成'},
{value: 18, name: '规划中'},
{value: 12, name: '已暂停'}
];
userActivityData = {
days: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
activeUsers: [420, 532, 601, 534, 630, 410, 320],
newUsers: [120, 132, 101, 134, 90, 60, 40]
};
taskCompletionData = {
weeks: ['第1周', '第2周', '第3周', '第4周'],
completed: [120, 132, 101, 134],
pending: [80, 60, 90, 70]
};
</script>
<script>
// 初始化图表
function initCharts() {
// 用户增长趋势图
const userGrowthChart = echarts.init(document.getElementById('userGrowthChart'));
userGrowthChart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: {
type: 'category',
data: $data.userGrowthData.months,
axisLine: {
lineStyle: {
color: '#9ca3af'
}
},
axisLabel: {
color: '#6b7280'
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#9ca3af'
}
},
axisLabel: {
color: '#6b7280'
},
splitLine: {
lineStyle: {
color: '#e5e7eb'
}
}
},
series: [{
data: $data.userGrowthData.values,
type: 'line',
smooth: true,
lineStyle: {
width: 4,
color: '#3b82f6'
},
itemStyle: {
color: '#3b82f6',
borderWidth: 2
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(59, 130, 246, 0.5)'
},
{
offset: 1,
color: 'rgba(59, 130, 246, 0.1)'
}
])
}
}]
});
// 项目状态分布图
const projectStatusChart = echarts.init(document.getElementById('projectStatusChart'));
projectStatusChart.setOption({
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
right: 10,
top: 'center',
textStyle: {
color: '#6b7280'
}
},
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: '18',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: $data.projectStatusData.map((item, index) => ({
value: item.value,
name: item.name,
itemStyle: {
color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6'][index]
}
}))
}
]
});
// 用户活跃度图
const userActivityChart = echarts.init(document.getElementById('userActivityChart'));
userActivityChart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: ['活跃用户', '新增用户'],
textStyle: {
color: '#6b7280'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: $data.userActivityData.days,
axisLine: {
lineStyle: {
color: '#9ca3af'
}
},
axisLabel: {
color: '#6b7280'
}
}
],
yAxis: [
{
type: 'value',
axisLine: {
lineStyle: {
color: '#9ca3af'
}
},
axisLabel: {
color: '#6b7280'
},
splitLine: {
lineStyle: {
color: '#e5e7eb'
}
}
}
],
series: [
{
name: '活跃用户',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(59, 130, 246, 0.8)'
},
{
offset: 1,
color: 'rgba(59, 130, 246, 0.1)'
}
])
},
emphasis: {
focus: 'series'
},
data: $data.userActivityData.activeUsers
},
{
name: '新增用户',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(16, 185, 129, 0.8)'
},
{
offset: 1,
color: 'rgba(16, 185, 129, 0.1)'
}
])
},
emphasis: {
focus: 'series'
},
data: $data.userActivityData.newUsers
}
]
});
// 任务完成情况图
const taskCompletionChart = echarts.init(document.getElementById('taskCompletionChart'));
taskCompletionChart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['已完成', '待处理'],
textStyle: {
color: '#6b7280'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: $data.taskCompletionData.weeks,
axisLine: {
lineStyle: {
color: '#9ca3af'
}
},
axisLabel: {
color: '#6b7280'
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#9ca3af'
}
},
axisLabel: {
color: '#6b7280'
},
splitLine: {
lineStyle: {
color: '#e5e7eb'
}
}
},
series: [
{
name: '已完成',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: $data.taskCompletionData.completed,
itemStyle: {
color: '#10b981'
}
},
{
name: '待处理',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: $data.taskCompletionData.pending,
itemStyle: {
color: '#f59e0b'
}
}
]
});
// 窗口大小变化时重新调整图表大小
window.addEventListener('resize', function () {
userGrowthChart.resize();
projectStatusChart.resize();
userActivityChart.resize();
taskCompletionChart.resize();
});
}
// 页面加载完成后初始化图表
initCharts()
</script>