yunzer/runtime/admin/temp/1c825d7302c9198f86d61f24e6c74d99.php
2025-06-09 15:33:30 +08:00

850 lines
26 KiB
PHP

<?php /*a:3:{s:61:"E:\Demos\DemoOwns\PHP\yunzer\app\admin\view\index\welcome.php";i:1749433730;s:61:"E:\Demos\DemoOwns\PHP\yunzer\app\admin\view\public\header.php";i:1746849526;s:59:"E:\Demos\DemoOwns\PHP\yunzer\app\admin\view\public\tail.php";i:1746709977;}*/ ?>
<!DOCTYPE html>
<html>
<head>
<title><?php echo htmlentities((string) $config['admin_name']); ?></title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" type="text/css" href="/static/layui/css/layui.css" media="all"/>
<link rel="stylesheet" type="text/css" href="/static/css/moban.css" media="all"/>
<link rel="stylesheet" type="text/css" href="/static/css/wangeditor.css" media="all"/>
<style type="text/css">
.header span{background:#009688;margin-left:30px;padding:10px;color:#ffffff;}
.header div{border-bottom:solid 2px #009688;margin-top: 8px;}
.header button{float:right;margin-top:-5px;}
.pagination {
display: inline-block;
padding-left: 0;
margin: 20px 0;
border-radius: 4px;
}
.pagination > li {
display: inline;
}
.pagination > li > a,
.pagination > li > span {
position: relative;
float: left;
padding: 6px 12px;
margin-left: -1px;
line-height: 1.42857143;
color: #337ab7;
text-decoration: none;
background-color: #fff;
border: 1px solid #ddd;
}
.pagination > li:first-child > a,
.pagination > li:first-child > span {
margin-left: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.pagination > li:last-child > a,
.pagination > li:last-child > span {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.pagination > li > a:hover,
.pagination > li > span:hover,
.pagination > li > a:focus,
.pagination > li > span:focus {
z-index: 2;
color: #23527c;
background-color: #eee;
border-color: #ddd;
}
.pagination > .active > a,
.pagination > .active > span,
.pagination > .active > a:hover,
.pagination > .active > span:hover,
.pagination > .active > a:focus,
.pagination > .active > span:focus {
z-index: 3;
color: #fff;
cursor: default;
background-color: #337ab7;
border-color: #337ab7;
}
.pagination > .disabled > span,
.pagination > .disabled > span:hover,
.pagination > .disabled > span:focus,
.pagination > .disabled > a,
.pagination > .disabled > a:hover,
.pagination > .disabled > a:focus {
color: #777;
cursor: not-allowed;
background-color: #fff;
border-color: #ddd;
}
.close-img { background: url(/static/images/close_img.png); background-size: 20px 20px; width:20px; height: 20px; position: absolute; right: 5px; top: 5px; z-index: 2;}
</style>
<script type="text/javascript" src="/static/layui/layui.js"></script>
<script type="text/javascript">
layui.use(['layer','form','table','laydate','element','upload'],function(){
layer = layui.layer; // layui 弹框
form = layui.form; // layui form表单
table = layui.table; // layui 表格
laydate = layui.laydate; // layui 时间框
element = layui.element; // layui element
upload = layui.upload; // layui 上传
$ = layui.jquery; // layui jquery
})
</script>
</head>
<body style="padding:10px; box-sizing: border-box;">
<script src="/static/js/jquery.min.js"></script>
<style>
.dashboard-container {
padding: 24px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
/* background-color: #f5f7fa; */
/* min-height: calc(100vh - 60px); */
}
.welcome-header {
background: linear-gradient(135deg, #3881fd 0%, #2c5fd9 100%);
border-radius: 12px;
padding: 30px;
color: white;
margin-bottom: 24px;
box-shadow: 0 4px 20px rgba(56, 129, 253, 0.15);
}
.welcome-header h1 {
font-size: 28px;
font-weight: 600;
margin-bottom: 8px;
}
.welcome-header p {
font-size: 15px;
opacity: 0.9;
margin: 0;
}
.stats-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 24px;
margin-bottom: 24px;
}
.stat-card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.stat-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background: #3881fd;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}
.stat-card .stat-value {
font-size: 32px;
font-weight: 600;
color: #2c3e50;
margin: 12px 0;
display: flex;
align-items: baseline;
}
.stat-card .stat-title {
color: #64748b;
font-size: 14px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.stat-card .stat-icon {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 48px;
opacity: 0.1;
}
.quick-actions {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
}
.quick-actions h2 {
color: #1e293b;
font-size: 18px;
font-weight: 600;
margin-bottom: 20px;
display: flex;
align-items: center;
}
.quick-actions h2::before {
content: '';
display: inline-block;
width: 4px;
height: 18px;
background: #3881fd;
margin-right: 8px;
border-radius: 2px;
}
.action-buttons {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: 16px;
}
.action-button {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 12px 16px;
color: #1e293b;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
}
.action-button:hover {
background: #3881fd;
color: white;
border-color: #3881fd;
transform: translateY(-2px);
}
.action-button i {
margin-right: 8px;
}
.recent-activity {
margin-top: 24px;
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
}
.activity-list {
margin-top: 16px;
}
.activity-item {
display: flex;
align-items: center;
padding: 12px 0;
border-bottom: 1px solid #f1f5f9;
}
.activity-item:last-child {
border-bottom: none;
}
.activity-icon {
width: 36px;
height: 36px;
border-radius: 8px;
background: #f1f5f9;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
}
.activity-content {
flex: 1;
}
.activity-title {
font-weight: 500;
color: #9b9b9b;
}
.activity-time {
font-size: 12px;
color: #64748b;
}
.charts-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 24px;
margin-top: 24px;
}
.chart-card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
}
.chart-card h2 {
color: #1e293b;
font-size: 18px;
font-weight: 600;
margin-bottom: 20px;
display: flex;
align-items: center;
}
.chart-card h2::before {
content: '';
display: inline-block;
width: 4px;
height: 18px;
background: #3881fd;
margin-right: 8px;
border-radius: 2px;
}
.chart-container {
height: 300px;
width: 100%;
}
</style>
<div class="dashboard-container">
<div class="welcome-header">
<h1>欢迎使用<?php echo htmlentities((string) $config['admin_name']); ?></h1>
<p>今天是 <span id="current-time"></span>,祝您工作愉快</p>
</div>
<div class="stats-container">
<div class="stat-card">
<div class="stat-title">用户总数</div>
<div class="stat-value"><?php echo htmlentities((string) number_format($todayStats['total_users'])); ?></div>
<div class="stat-icon">👥</div>
</div>
<div class="stat-card">
<div class="stat-title">今日访问</div>
<div class="stat-value"><?php echo htmlentities((string) number_format($todayStats['daily_visits'])); ?></div>
<div class="stat-icon">📊</div>
</div>
<div class="stat-card">
<div class="stat-title">文章总数</div>
<div class="stat-value"><?php echo htmlentities((string) number_format($todayStats['total_articles'])); ?></div>
<div class="stat-icon">📝</div>
</div>
<div class="stat-card">
<div class="stat-title">资源总数</div>
<div class="stat-value"><?php echo htmlentities((string) number_format($todayStats['total_resources'])); ?></div>
<div class="stat-icon">📦</div>
</div>
</div>
<div class="quick-actions">
<h2>快捷操作</h2>
<div class="action-buttons">
<a href="<?php echo url('user/index'); ?>" class="action-button">
<i class="fas fa-users"></i>用户管理
</a>
<a href="<?php echo url('content/publish'); ?>" class="action-button">
<i class="fas fa-edit"></i>内容发布
</a>
<a href="<?php echo url('statistics/index'); ?>" class="action-button">
<i class="fas fa-chart-bar"></i>数据统计
</a>
<a href="<?php echo url('system/settings'); ?>" class="action-button">
<i class="fas fa-cog"></i>系统设置
</a>
<a href="<?php echo url('system/clear_cache'); ?>" class="action-button">
<i class="fas fa-broom"></i>清除缓存
</a>
</div>
</div>
<div class="recent-activity">
<h2>最近动态</h2>
<div class="activity-list">
<?php if(is_array($recentActivities) || $recentActivities instanceof \think\Collection || $recentActivities instanceof \think\Paginator): $i = 0; $__LIST__ = $recentActivities;if( count($__LIST__)==0 ) : echo "" ;else: foreach($__LIST__ as $key=>$activity): $mod = ($i % 2 );++$i;?>
<div class="activity-item">
<div class="activity-icon"><?php echo htmlentities((string) (isset($activity['icon']) && ($activity['icon'] !== '')?$activity['icon']:'📌')); ?></div>
<div class="activity-content">
<div class="activity-title"><?php echo htmlentities((string) $activity['content']); ?></div>
</div>
</div>
<?php endforeach; endif; else: echo "" ;endif; ?>
</div>
</div>
<div class="charts-container">
<div class="chart-card">
<h2>访问趋势</h2>
<div id="visitTrend" class="chart-container"></div>
</div>
<div class="chart-card">
<h2>用户增长</h2>
<div id="userGrowth" class="chart-container"></div>
</div>
<div class="chart-card">
<h2>资源统计</h2>
<div id="resourceStats" class="chart-container"></div>
</div>
<div class="chart-card">
<h2>文章统计</h2>
<div id="articleStats" class="chart-container"></div>
</div>
</div>
</div>
<script src="/static/js/echarts.min.js"></script>
<script>
function updateTime() {
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth() + 1;
var date = now.getDate();
var hours = now.getHours();
var minutes = now.getMinutes();
var seconds = now.getSeconds();
var padZero = function(num) {
return num < 10 ? '0' + num : num;
};
var timeString = year + '年' +
padZero(month) + '月' +
padZero(date) + '日 ' +
padZero(hours) + ':' +
padZero(minutes) + ':' +
padZero(seconds);
document.getElementById('current-time').innerHTML = timeString;
}
// 获取用户统计数据
function getUserCounts() {
fetch('<?php echo url("users/counts"); ?>')
.then(response => response.json())
.then(res => {
console.log('用户统计接口返回数据:', res);
if (res.code === 0 && res.data) {
// 更新用户总数
document.querySelector('.stat-card:nth-child(1) .stat-value').textContent = res.data.total.toLocaleString();
// 更新用户增长图表
if (window.userChart) {
window.userChart.setOption({
xAxis: {
data: res.data.dates
},
series: [{
name: '新增用户',
data: res.data.counts
}, {
name: '总用户数',
data: res.data.totalCounts
}]
});
}
} else {
console.warn('用户统计接口返回异常:', res);
document.querySelector('.stat-card:nth-child(1) .stat-value').textContent = '0';
}
})
.catch(error => {
console.error('获取用户统计失败:', error);
document.querySelector('.stat-card:nth-child(1) .stat-value').textContent = '0';
});
}
// 获取文章统计数据
function getArticleCounts() {
fetch('<?php echo url("articles/counts"); ?>')
.then(response => response.json())
.then(res => {
console.log('文章统计接口返回数据:', res);
if (res.code === 0 && res.data) {
// 更新文章总数
document.querySelector('.stat-card:nth-child(3) .stat-value').textContent = res.data.total.toLocaleString();
// 更新文章统计图表
if (window.articleChart) {
window.articleChart.setOption({
xAxis: {
data: res.data.dates
},
series: [{
name: '新增文章',
data: res.data.counts
}, {
name: '总文章数',
data: res.data.totalCounts
}]
});
}
} else {
console.warn('文章统计接口返回异常:', res);
document.querySelector('.stat-card:nth-child(3) .stat-value').textContent = '0';
}
})
.catch(error => {
console.error('获取文章统计失败:', error);
document.querySelector('.stat-card:nth-child(3) .stat-value').textContent = '0';
});
}
// 获取资源统计数据
function getResourcesCounts() {
fetch('<?php echo url("resources/counts"); ?>')
.then(response => response.json())
.then(res => {
console.log('资源统计接口返回数据:', res);
if (res.code === 0 && res.data) {
// 更新资源总数
document.querySelector('.stat-card:nth-child(4) .stat-value').textContent = res.data.total.toLocaleString();
// 更新资源统计图表
if (window.resourceChart) {
window.resourceChart.setOption({
xAxis: {
data: res.data.dates
},
series: [{
name: '新增资源',
data: res.data.counts
}, {
name: '总资源数',
data: res.data.totalCounts
}]
});
}
} else {
console.warn('资源统计接口返回异常:', res);
document.querySelector('.stat-card:nth-child(4) .stat-value').textContent = '0';
}
})
.catch(error => {
console.error('获取资源统计失败:', error);
document.querySelector('.stat-card:nth-child(4) .stat-value').textContent = '0';
});
}
updateTime();
setInterval(updateTime, 1000);
// 页面加载完成后获取统计数据
document.addEventListener('DOMContentLoaded', function() {
getUserCounts();
getArticleCounts();
getResourcesCounts();
});
// 访问趋势图表
function initVisitTrend() {
var chart = echarts.init(document.getElementById('visitTrend'));
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['访问量', '独立访客']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: <?php echo json_encode($chartData['visitTrend']['dates']); ?>,
axisLine: {
lineStyle: {
color: '#e2e8f0'
}
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#e2e8f0'
}
},
splitLine: {
lineStyle: {
color: '#f1f5f9'
}
}
},
series: [{
name: '访问量',
data: <?php echo json_encode($chartData['visitTrend']['visits']); ?>,
type: 'line',
smooth: true,
areaStyle: {
opacity: 0.1
},
itemStyle: {
color: '#3881fd'
},
lineStyle: {
width: 3
}
}, {
name: '独立访客',
data: <?php echo json_encode($chartData['visitTrend']['uvs']); ?>,
type: 'line',
smooth: true,
itemStyle: {
color: '#10b981'
},
lineStyle: {
width: 3
}
}]
};
chart.setOption(option);
}
// 用户增长图表
function initUserGrowth() {
var chart = echarts.init(document.getElementById('userGrowth'));
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: ['新增用户', '总用户数']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: <?php echo json_encode($chartData['userGrowth']['dates']); ?>
},
yAxis: {
type: 'value'
},
series: [
{
name: '新增用户',
type: 'bar',
data: <?php echo json_encode($chartData['userGrowth']['newUsers']); ?>,
itemStyle: {
color: '#3881fd'
}
},
{
name: '总用户数',
type: 'line',
smooth: true,
data: <?php echo json_encode($chartData['userGrowth']['totalUsers']); ?>,
itemStyle: {
color: '#10b981'
},
lineStyle: {
width: 3
}
}
]
};
chart.setOption(option);
}
// 资源统计图表
function initResourceStats() {
var chart = echarts.init(document.getElementById('resourceStats'));
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: ['新增资源', '总资源数', '下载量']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: <?php echo json_encode($chartData['resourceStats']['dates']); ?>
},
yAxis: {
type: 'value'
},
series: [
{
name: '新增资源',
type: 'bar',
data: <?php echo json_encode($chartData['resourceStats']['newResources']); ?>,
itemStyle: {
color: '#3881fd'
}
},
{
name: '总资源数',
type: 'line',
smooth: true,
data: <?php echo json_encode($chartData['resourceStats']['totalResources']); ?>,
itemStyle: {
color: '#10b981'
},
lineStyle: {
width: 3
}
},
{
name: '下载量',
type: 'line',
smooth: true,
data: <?php echo json_encode($chartData['resourceStats']['downloads']); ?>,
itemStyle: {
color: '#f59e0b'
},
lineStyle: {
width: 3
}
}
]
};
chart.setOption(option);
}
// 文章统计图表
function initArticleStats() {
var chart = echarts.init(document.getElementById('articleStats'));
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: ['新增文章', '总文章数', '浏览量']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: <?php echo json_encode($chartData['articleStats']['dates']); ?>
},
yAxis: {
type: 'value'
},
series: [
{
name: '新增文章',
type: 'bar',
data: <?php echo json_encode($chartData['articleStats']['newArticles']); ?>,
itemStyle: {
color: '#3881fd'
}
},
{
name: '总文章数',
type: 'line',
smooth: true,
data: <?php echo json_encode($chartData['articleStats']['totalArticles']); ?>,
itemStyle: {
color: '#10b981'
},
lineStyle: {
width: 3
}
},
{
name: '浏览量',
type: 'line',
smooth: true,
data: <?php echo json_encode($chartData['articleStats']['views']); ?>,
itemStyle: {
color: '#f59e0b'
},
lineStyle: {
width: 3
}
}
]
};
chart.setOption(option);
}
// 初始化所有图表
document.addEventListener('DOMContentLoaded', function() {
// 确保ECharts已加载
if (typeof echarts === 'undefined') {
console.error('ECharts未加载');
return;
}
// 初始化图表
try {
initVisitTrend();
initUserGrowth();
initResourceStats();
initArticleStats();
// 监听窗口大小变化,重绘图表
window.addEventListener('resize', function() {
var charts = document.querySelectorAll('.chart-container');
charts.forEach(function(chart) {
var instance = echarts.getInstanceByDom(chart);
if (instance) {
instance.resize();
}
});
});
} catch (error) {
console.error('初始化图表失败:', error);
}
});
</script>
</body>
</html>
<script type="text/javascript">
// 显示图片
function show_img(obj){
var imgurl = $(obj).attr('src');
var res = getMousePos();
var html = '<div style="background:#fff;position:absolute;width:200px;border:solid 1px #cdcdcd;border-radius:6px;padding:2px;left:'+res.x+'px;top:'+res.y+'px;z-index:1000" id="preview">\
<img style="width:100%;border-radius:6px;" src="'+imgurl+'">\
</div>';
$('body').append(html);
}
// 隐藏图片
function hide_img(){
$('#preview').remove();
}
// 图片位置计算
function getMousePos(event) {
var e = event || window.event;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var x = e.pageX || e.clientX + scrollX;
var y = e.pageY || e.clientY + scrollY;
return { 'x': x, 'y': y };
}
// 删除图片
function deleteImage(path,obj){
$(obj).closest('.upload_pic_li').remove();
}
</script>