更新后端
This commit is contained in:
1 parent
4c6f7277b0
commit
11fe0b4357
28 files changed
+4644
-134
No files matched your search
@@ -7,6 +7,7 @@ use app\admin\controller\Base;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use app\common\service\LogService;
|
||||
|
||||
class Article extends Base
|
||||
{
|
||||
@@ -411,4 +412,20 @@ class Article extends Base
|
||||
}
|
||||
return json(['code' => 0, 'msg' => '删除成功', 'data' => []]);
|
||||
}
|
||||
|
||||
//统计文章数量
|
||||
public function counts() {
|
||||
$total = Db::table('yz_article')
|
||||
->where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->count();
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'total' => $total
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -61,10 +61,206 @@ class Index extends Base{
|
||||
}
|
||||
# 欢迎页面
|
||||
public function welcome(){
|
||||
View::assign([
|
||||
'time' => date('Y-m-d',$_SERVER['REQUEST_TIME']),
|
||||
// 获取今日统计数据
|
||||
$today = date('Y-m-d');
|
||||
$todayStats = Db::name('yz_daily_stats')
|
||||
->where('date', $today)
|
||||
->find();
|
||||
|
||||
// 获取最近7天的访问趋势
|
||||
$last7Days = Db::name('yz_daily_stats')
|
||||
->where('date', '>=', date('Y-m-d', strtotime('-7 days')))
|
||||
->where('date', '<=', $today)
|
||||
->order('date', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 获取用户增长趋势
|
||||
$userGrowth = Db::name('yz_daily_stats')
|
||||
->where('date', '>=', date('Y-m-d', strtotime('-30 days')))
|
||||
->where('date', '<=', $today)
|
||||
->field('date, new_users, total_users')
|
||||
->order('date', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 获取资源下载统计
|
||||
$resourceStats = Db::name('yz_daily_stats')
|
||||
->where('date', '>=', date('Y-m-d', strtotime('-7 days')))
|
||||
->where('date', '<=', $today)
|
||||
->field('date, daily_resources, resource_downloads')
|
||||
->order('date', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 获取文章访问统计
|
||||
$articleStats = Db::name('yz_daily_stats')
|
||||
->where('date', '>=', date('Y-m-d', strtotime('-7 days')))
|
||||
->where('date', '<=', $today)
|
||||
->field('date, daily_articles, article_views')
|
||||
->order('date', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 获取最近的活动记录
|
||||
$recentActivities = $this->getRecentActivities();
|
||||
|
||||
// 准备图表数据
|
||||
$chartData = [
|
||||
'visitTrend' => $this->formatVisitTrendData($last7Days),
|
||||
'userGrowth' => $this->formatUserGrowthData($userGrowth),
|
||||
'resourceStats' => $this->formatResourceStatsData($resourceStats),
|
||||
'articleStats' => $this->formatArticleStatsData($articleStats)
|
||||
];
|
||||
|
||||
// 准备统计数据
|
||||
$stats = [
|
||||
'total_users' => $todayStats['total_users'] ?? 0,
|
||||
'daily_visits' => $todayStats['daily_visits'] ?? 0,
|
||||
'total_articles' => $todayStats['total_articles'] ?? 0,
|
||||
'total_resources' => $todayStats['total_resources'] ?? 0,
|
||||
];
|
||||
|
||||
return View::fetch('', [
|
||||
'stats' => $stats,
|
||||
'chartData' => $chartData,
|
||||
'recentActivities' => $recentActivities
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最近的活动记录
|
||||
*/
|
||||
private function getRecentActivities()
|
||||
{
|
||||
$today = date('Y-m-d');
|
||||
$activities = [];
|
||||
|
||||
// 获取今日新用户
|
||||
$newUsers = Db::name('yz_daily_stats')
|
||||
->where('date', $today)
|
||||
->value('new_users');
|
||||
if ($newUsers > 0) {
|
||||
$activities[] = [
|
||||
'icon' => '👥',
|
||||
'title' => '新增用户 ' . $newUsers . ' 人',
|
||||
'time' => '今日'
|
||||
];
|
||||
}
|
||||
|
||||
// 获取今日文章
|
||||
$newArticles = Db::name('yz_daily_stats')
|
||||
->where('date', $today)
|
||||
->value('daily_articles');
|
||||
if ($newArticles > 0) {
|
||||
$activities[] = [
|
||||
'icon' => '📝',
|
||||
'title' => '发布文章 ' . $newArticles . ' 篇',
|
||||
'time' => '今日'
|
||||
];
|
||||
}
|
||||
|
||||
// 获取今日资源
|
||||
$newResources = Db::name('yz_daily_stats')
|
||||
->where('date', $today)
|
||||
->value('daily_resources');
|
||||
if ($newResources > 0) {
|
||||
$activities[] = [
|
||||
'icon' => '📦',
|
||||
'title' => '上传资源 ' . $newResources . ' 个',
|
||||
'time' => '今日'
|
||||
];
|
||||
}
|
||||
|
||||
return $activities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化访问趋势数据
|
||||
*/
|
||||
private function formatVisitTrendData($data)
|
||||
{
|
||||
$dates = [];
|
||||
$visits = [];
|
||||
$uvs = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$dates[] = date('m-d', strtotime($item['date']));
|
||||
$visits[] = $item['daily_visits'];
|
||||
$uvs[] = $item['unique_visitors'];
|
||||
}
|
||||
|
||||
return [
|
||||
'dates' => $dates,
|
||||
'visits' => $visits,
|
||||
'uvs' => $uvs
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化用户增长数据
|
||||
*/
|
||||
private function formatUserGrowthData($data)
|
||||
{
|
||||
$dates = [];
|
||||
$newUsers = [];
|
||||
$totalUsers = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$dates[] = date('m-d', strtotime($item['date']));
|
||||
$newUsers[] = $item['new_users'];
|
||||
$totalUsers[] = $item['total_users'];
|
||||
}
|
||||
|
||||
return [
|
||||
'dates' => $dates,
|
||||
'newUsers' => $newUsers,
|
||||
'totalUsers' => $totalUsers
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化资源统计数据
|
||||
*/
|
||||
private function formatResourceStatsData($data)
|
||||
{
|
||||
$dates = [];
|
||||
$resources = [];
|
||||
$downloads = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$dates[] = date('m-d', strtotime($item['date']));
|
||||
$resources[] = $item['daily_resources'];
|
||||
$downloads[] = $item['resource_downloads'];
|
||||
}
|
||||
|
||||
return [
|
||||
'dates' => $dates,
|
||||
'resources' => $resources,
|
||||
'downloads' => $downloads
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文章统计数据
|
||||
*/
|
||||
private function formatArticleStatsData($data)
|
||||
{
|
||||
$dates = [];
|
||||
$articles = [];
|
||||
$views = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$dates[] = date('m-d', strtotime($item['date']));
|
||||
$articles[] = $item['daily_articles'];
|
||||
$views[] = $item['article_views'];
|
||||
}
|
||||
|
||||
return [
|
||||
'dates' => $dates,
|
||||
'articles' => $articles,
|
||||
'views' => $views
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,4 +439,5 @@ class Index extends Base{
|
||||
return json(['code'=>1, 'msg'=>$e->getMessage()])->send();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\controller\Base;
|
||||
use think\facade\Db;
|
||||
use think\facade\Request;
|
||||
use think\facade\View;
|
||||
|
||||
class Log extends Base
|
||||
{
|
||||
/**
|
||||
* 登录日志列表
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$page = input('post.page', 1);
|
||||
$limit = input('post.limit', 10);
|
||||
$username = input('post.username');
|
||||
$ip = input('post.ip');
|
||||
$status = input('post.status');
|
||||
$startTime = input('post.start_time');
|
||||
$endTime = input('post.end_time');
|
||||
|
||||
$query = Db::name('yz_logs_login');
|
||||
|
||||
// 搜索条件
|
||||
if ($username) {
|
||||
$query = $query->where('username', 'like', "%{$username}%");
|
||||
}
|
||||
if ($ip) {
|
||||
$query = $query->where('ip_address', 'like', "%{$ip}%");
|
||||
}
|
||||
if ($status !== '') {
|
||||
$query = $query->where('login_status', $status);
|
||||
}
|
||||
if ($startTime) {
|
||||
$query = $query->where('login_time', '>=', $startTime);
|
||||
}
|
||||
if ($endTime) {
|
||||
$query = $query->where('login_time', '<=', $endTime);
|
||||
}
|
||||
|
||||
$count = $query->count();
|
||||
$list = $query->order('id desc')
|
||||
->page($page, $limit)
|
||||
->select();
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'count' => $count,
|
||||
'data' => $list
|
||||
]);
|
||||
}
|
||||
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作日志列表
|
||||
*/
|
||||
public function operation()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$page = input('post.page', 1);
|
||||
$limit = input('post.limit', 10);
|
||||
$username = input('post.username');
|
||||
$module = input('post.module');
|
||||
$operation = input('post.operation');
|
||||
$status = input('post.status');
|
||||
$startTime = input('post.start_time');
|
||||
$endTime = input('post.end_time');
|
||||
|
||||
$query = Db::name('yz_logs_operation');
|
||||
|
||||
// 搜索条件
|
||||
if ($username) {
|
||||
$query = $query->where('username', 'like', "%{$username}%");
|
||||
}
|
||||
if ($module) {
|
||||
$query = $query->where('module', 'like', "%{$module}%");
|
||||
}
|
||||
if ($operation) {
|
||||
$query = $query->where('operation', 'like', "%{$operation}%");
|
||||
}
|
||||
if ($status !== '') {
|
||||
$query = $query->where('status', $status);
|
||||
}
|
||||
if ($startTime) {
|
||||
$query = $query->where('operation_time', '>=', $startTime);
|
||||
}
|
||||
if ($endTime) {
|
||||
$query = $query->where('operation_time', '<=', $endTime);
|
||||
}
|
||||
|
||||
$count = $query->count();
|
||||
$list = $query->order('id desc')
|
||||
->page($page, $limit)
|
||||
->select();
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'count' => $count,
|
||||
'data' => $list
|
||||
]);
|
||||
}
|
||||
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录操作日志
|
||||
*/
|
||||
protected function recordOperation($operation, $status = 1, $error_message = '')
|
||||
{
|
||||
$data = [
|
||||
'username' => session('admin_username'),
|
||||
'module' => '日志管理',
|
||||
'operation' => $operation,
|
||||
'request_method' => Request::method(),
|
||||
'request_url' => Request::url(true),
|
||||
'request_params' => json_encode(Request::param(), JSON_UNESCAPED_UNICODE),
|
||||
'ip_address' => Request::ip(),
|
||||
'status' => $status,
|
||||
'error_message' => $error_message,
|
||||
'operation_time' => date('Y-m-d H:i:s'),
|
||||
'execution_time' => 0
|
||||
];
|
||||
|
||||
Db::name('yz_logs_operation')->insert($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除登录日志
|
||||
*/
|
||||
public function deleteLogin()
|
||||
{
|
||||
$id = input('post.id');
|
||||
try {
|
||||
if (Db::name('yz_logs_login')->delete($id)) {
|
||||
$this->recordOperation('删除登录日志');
|
||||
return json(['code' => 0, 'msg' => '删除成功']);
|
||||
}
|
||||
$this->recordOperation('删除登录日志', 0, '删除失败');
|
||||
return json(['code' => 1, 'msg' => '删除失败']);
|
||||
} catch (\Exception $e) {
|
||||
$this->recordOperation('删除登录日志', 0, $e->getMessage());
|
||||
return json(['code' => 1, 'msg' => '删除失败:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除操作日志
|
||||
*/
|
||||
public function deleteOperation()
|
||||
{
|
||||
$id = input('post.id');
|
||||
try {
|
||||
if (Db::name('yz_logs_operation')->delete($id)) {
|
||||
$this->recordOperation('删除操作日志');
|
||||
return json(['code' => 0, 'msg' => '删除成功']);
|
||||
}
|
||||
$this->recordOperation('删除操作日志', 0, '删除失败');
|
||||
return json(['code' => 1, 'msg' => '删除失败']);
|
||||
} catch (\Exception $e) {
|
||||
$this->recordOperation('删除操作日志', 0, $e->getMessage());
|
||||
return json(['code' => 1, 'msg' => '删除失败:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空登录日志
|
||||
*/
|
||||
public function clearLogin()
|
||||
{
|
||||
try {
|
||||
if (Db::name('yz_logs_login')->where('1=1')->delete()) {
|
||||
$this->recordOperation('清空登录日志');
|
||||
return json(['code' => 0, 'msg' => '清空成功']);
|
||||
}
|
||||
$this->recordOperation('清空登录日志', 0, '清空失败');
|
||||
return json(['code' => 1, 'msg' => '清空失败']);
|
||||
} catch (\Exception $e) {
|
||||
$this->recordOperation('清空登录日志', 0, $e->getMessage());
|
||||
return json(['code' => 1, 'msg' => '清空失败:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空操作日志
|
||||
*/
|
||||
public function clearOperation()
|
||||
{
|
||||
try {
|
||||
if (Db::name('yz_logs_operation')->where('1=1')->delete()) {
|
||||
$this->recordOperation('清空操作日志');
|
||||
return json(['code' => 0, 'msg' => '清空成功']);
|
||||
}
|
||||
$this->recordOperation('清空操作日志', 0, '清空失败');
|
||||
return json(['code' => 1, 'msg' => '清空失败']);
|
||||
} catch (\Exception $e) {
|
||||
$this->recordOperation('清空操作日志', 0, $e->getMessage());
|
||||
return json(['code' => 1, 'msg' => '清空失败:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -445,4 +445,20 @@ class Resources extends Base
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
//统计资源数量
|
||||
public function counts() {
|
||||
$total = Db::table('yz_resources')
|
||||
->where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->count();
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'total' => $total
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -109,7 +109,7 @@
|
||||
<li class="layui-nav-item" data-name="index/welcome">
|
||||
<a href="javascript:;" lay-tips="工作台" lay-direction="2"
|
||||
onclick="menuFire('index/welcome',1)">
|
||||
<i class="layui-icon layui-icon-home" style="margin-top: -30px;"></i>
|
||||
<i class="layui-icon layui-icon-home" style="margin-top: -20px;"></i>
|
||||
<cite>工作台</cite>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,78 +1,205 @@
|
||||
{include file="public/header" /}
|
||||
<script src="__STATIC__/js/jquery.min.js"></script>
|
||||
<style>
|
||||
.dashboard-container {
|
||||
padding: 20px;
|
||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||
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 {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
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 {
|
||||
color: #3881fd;
|
||||
font-weight: 300;
|
||||
font-size: 28px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.welcome-header p {
|
||||
font-size: 15px;
|
||||
opacity: 0.9;
|
||||
margin: 0;
|
||||
}
|
||||
.stats-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
margin-bottom: 30px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.stat-card {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
|
||||
padding: 20px;
|
||||
min-width: 200px;
|
||||
flex: 1;
|
||||
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 5px 15px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.stat-card .stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #3881fd;
|
||||
margin: 10px 0;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
margin: 12px 0;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
.stat-card .stat-title {
|
||||
color: #7f8c8d;
|
||||
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-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.quick-actions h2 {
|
||||
color: #2c3e50;
|
||||
color: #1e293b;
|
||||
font-size: 18px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 500;
|
||||
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: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.action-button {
|
||||
background-color: #f8f9fa;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 10px 15px;
|
||||
color: #3881fd;
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 12px 16px;
|
||||
color: #1e293b;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
.action-button:hover {
|
||||
background-color: #e9ecef;
|
||||
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: #1e293b;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.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>
|
||||
|
||||
@@ -85,34 +212,84 @@
|
||||
<div class="stats-container">
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">用户总数</div>
|
||||
<div class="stat-value">1,234</div>
|
||||
<div class="stat-value">{$stats.total_users|number_format}</div>
|
||||
<div class="stat-icon">👥</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">今日访问</div>
|
||||
<div class="stat-value">256</div>
|
||||
<div class="stat-value">{$stats.daily_visits|number_format}</div>
|
||||
<div class="stat-icon">📊</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">数据总量</div>
|
||||
<div class="stat-value">8,642</div>
|
||||
<div class="stat-title">文章总数</div>
|
||||
<div class="stat-value">{$stats.total_articles|number_format}</div>
|
||||
<div class="stat-icon">📝</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">系统消息</div>
|
||||
<div class="stat-value">12</div>
|
||||
<div class="stat-title">资源总数</div>
|
||||
<div class="stat-value">{$stats.total_resources|number_format}</div>
|
||||
<div class="stat-icon">📦</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="quick-actions">
|
||||
<h2>快捷操作</h2>
|
||||
<div class="action-buttons">
|
||||
<button class="action-button">用户管理</button>
|
||||
<button class="action-button">内容发布</button>
|
||||
<button class="action-button">数据统计</button>
|
||||
<button class="action-button">系统设置</button>
|
||||
<button class="action-button">清除缓存</button>
|
||||
<a href="{:url('user/index')}" class="action-button">
|
||||
<i class="fas fa-users"></i>用户管理
|
||||
</a>
|
||||
<a href="{:url('content/publish')}" class="action-button">
|
||||
<i class="fas fa-edit"></i>内容发布
|
||||
</a>
|
||||
<a href="{:url('statistics/index')}" class="action-button">
|
||||
<i class="fas fa-chart-bar"></i>数据统计
|
||||
</a>
|
||||
<a href="{:url('system/settings')}" class="action-button">
|
||||
<i class="fas fa-cog"></i>系统设置
|
||||
</a>
|
||||
<a href="{: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">
|
||||
{volist name="recentActivities" id="activity"}
|
||||
<div class="activity-item">
|
||||
<div class="activity-icon">{$activity.icon}</div>
|
||||
<div class="activity-content">
|
||||
<div class="activity-title">{$activity.title}</div>
|
||||
<div class="activity-time">{$activity.time}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/volist}
|
||||
</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="__JS__/echarts.min.js"></script>
|
||||
<script>
|
||||
function updateTime() {
|
||||
var now = new Date();
|
||||
@@ -123,12 +300,10 @@ function updateTime() {
|
||||
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) + '日 ' +
|
||||
@@ -139,11 +314,296 @@ function updateTime() {
|
||||
document.getElementById('current-time').innerHTML = timeString;
|
||||
}
|
||||
|
||||
// 页面加载完立即执行一次
|
||||
updateTime();
|
||||
// 获取文章统计数据
|
||||
function getArticleCounts() {
|
||||
fetch('{:url("article/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();
|
||||
} else {
|
||||
console.warn('文章统计接口返回异常:', res);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('获取文章统计失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// 每秒更新一次时间
|
||||
// 获取资源统计数据
|
||||
function getResourcesCounts() {
|
||||
fetch('{: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();
|
||||
} else {
|
||||
console.warn('资源统计接口返回异常:', res);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('获取资源统计失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
updateTime();
|
||||
setInterval(updateTime, 1000);
|
||||
|
||||
// 页面加载完成后获取统计数据
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
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: {$chartData.visitTrend.dates|json_encode},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#e2e8f0'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#e2e8f0'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#f1f5f9'
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: '访问量',
|
||||
data: {$chartData.visitTrend.visits|json_encode},
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
opacity: 0.1
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
},
|
||||
lineStyle: {
|
||||
width: 3
|
||||
}
|
||||
}, {
|
||||
name: '独立访客',
|
||||
data: {$chartData.visitTrend.uvs|json_encode},
|
||||
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: {$chartData.userGrowth.dates|json_encode}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '新增用户',
|
||||
type: 'bar',
|
||||
data: {$chartData.userGrowth.newUsers|json_encode},
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '总用户数',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: {$chartData.userGrowth.totalUsers|json_encode},
|
||||
itemStyle: {
|
||||
color: '#10b981'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
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: {$chartData.resourceStats.dates|json_encode}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '新增资源',
|
||||
type: 'bar',
|
||||
data: {$chartData.resourceStats.resources|json_encode},
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '下载量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: {$chartData.resourceStats.downloads|json_encode},
|
||||
itemStyle: {
|
||||
color: '#10b981'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
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: {$chartData.articleStats.dates|json_encode}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '新增文章',
|
||||
type: 'bar',
|
||||
data: {$chartData.articleStats.articles|json_encode},
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '访问量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: {$chartData.articleStats.views|json_encode},
|
||||
itemStyle: {
|
||||
color: '#10b981'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
chart.setOption(option);
|
||||
}
|
||||
|
||||
// 初始化所有图表
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initVisitTrend();
|
||||
initUserGrowth();
|
||||
initResourceStats();
|
||||
initArticleStats();
|
||||
|
||||
// 监听窗口大小变化,重绘图表
|
||||
window.addEventListener('resize', function() {
|
||||
var charts = document.querySelectorAll('.chart-container');
|
||||
charts.forEach(function(chart) {
|
||||
echarts.getInstanceByDom(chart)?.resize();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{include file="public/tail" /}
|
||||
@@ -0,0 +1,166 @@
|
||||
{include file="public/header" /}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
<span class="layui-badge layui-bg-blue">登录日志</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<form class="layui-form layui-form-pane" action="">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="username" placeholder="请输入用户名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">IP地址</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="ip" placeholder="请输入IP地址" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="status">
|
||||
<option value="">全部</option>
|
||||
<option value="1">成功</option>
|
||||
<option value="0">失败</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">时间范围</label>
|
||||
<div class="layui-input-inline" style="width: 300px;">
|
||||
<input type="text" name="time_range" class="layui-input" id="timeRange" placeholder="请选择时间范围">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button class="layui-btn" lay-submit lay-filter="searchForm">
|
||||
<i class="layui-icon layui-icon-search"></i> 搜索
|
||||
</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table id="loginLogTable" lay-filter="loginLogTable"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="tableToolbar">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="clearAll">
|
||||
<i class="layui-icon layui-icon-delete"></i> 清空日志
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tableBar">
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
<script src="/static/layui/layui.js"></script>
|
||||
<script>
|
||||
layui.use(['table', 'form', 'laydate'], function(){
|
||||
var table = layui.table;
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
|
||||
// 初始化时间范围选择器
|
||||
laydate.render({
|
||||
elem: '#timeRange',
|
||||
type: 'datetime',
|
||||
range: true
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.render({
|
||||
elem: '#loginLogTable',
|
||||
url: '{:url("log/login")}',
|
||||
method: 'post',
|
||||
toolbar: '#tableToolbar',
|
||||
defaultToolbar: ['filter', 'exports', 'print'],
|
||||
parseData: function(res) {
|
||||
return {
|
||||
"code": res.code === 0 ? 0 : 1,
|
||||
"msg": res.msg,
|
||||
"count": res.count,
|
||||
"data": res.data
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{field: 'id', title: 'ID', width: 80, sort: true},
|
||||
{field: 'username', title: '用户名', width: 120},
|
||||
{field: 'ip_address', title: 'IP地址', width: 130},
|
||||
{field: 'location', title: '登录地点', width: 120},
|
||||
{field: 'device_type', title: '设备类型', width: 100},
|
||||
{field: 'user_agent', title: '浏览器', width: 200},
|
||||
{field: 'login_status', title: '状态', width: 100, templet: function(d){
|
||||
return d.login_status == 1 ?
|
||||
'<span class="layui-badge layui-bg-green">成功</span>' :
|
||||
'<span class="layui-badge layui-bg-red">失败</span>';
|
||||
}},
|
||||
{field: 'failure_reason', title: '失败原因', width: 150},
|
||||
{field: 'login_time', title: '登录时间', width: 180, sort: true},
|
||||
{title: '操作', toolbar: '#tableBar', width: 80, fixed: 'right'}
|
||||
]],
|
||||
page: true,
|
||||
limit: 10,
|
||||
limits: [10, 20, 50, 100]
|
||||
});
|
||||
|
||||
// 监听搜索表单提交
|
||||
form.on('submit(searchForm)', function(data){
|
||||
var timeRange = data.field.time_range;
|
||||
if(timeRange){
|
||||
var times = timeRange.split(' - ');
|
||||
data.field.start_time = times[0];
|
||||
data.field.end_time = times[1];
|
||||
}
|
||||
delete data.field.time_range;
|
||||
|
||||
table.reload('loginLogTable', {
|
||||
where: data.field,
|
||||
page: {curr: 1}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// 监听工具条
|
||||
table.on('tool(loginLogTable)', function(obj){
|
||||
var data = obj.data;
|
||||
if(obj.event === 'del'){
|
||||
layer.confirm('确定删除这条日志吗?', function(index){
|
||||
$.post('{:url("log/deleteLogin")}', {id: data.id}, function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
obj.del();
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听头工具栏事件
|
||||
table.on('toolbar(loginLogTable)', function(obj){
|
||||
if(obj.event === 'clearAll'){
|
||||
layer.confirm('确定要清空所有登录日志吗?', function(index){
|
||||
$.post('{:url("log/clearLogin")}', function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
table.reload('loginLogTable');
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,175 @@
|
||||
{include file="public/header" /}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
<span class="layui-badge layui-bg-blue">操作日志</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<form class="layui-form layui-form-pane" action="">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="username" placeholder="请输入用户名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">模块</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="module" placeholder="请输入模块" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">操作</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="operation" placeholder="请输入操作" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="status">
|
||||
<option value="">全部</option>
|
||||
<option value="1">成功</option>
|
||||
<option value="0">失败</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">时间范围</label>
|
||||
<div class="layui-input-inline" style="width: 300px;">
|
||||
<input type="text" name="time_range" class="layui-input" id="timeRange" placeholder="请选择时间范围">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button class="layui-btn" lay-submit lay-filter="searchForm">
|
||||
<i class="layui-icon layui-icon-search"></i> 搜索
|
||||
</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table id="operationLogTable" lay-filter="operationLogTable"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="tableToolbar">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="clearAll">
|
||||
<i class="layui-icon layui-icon-delete"></i> 清空日志
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tableBar">
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
<script src="/static/layui/layui.js"></script>
|
||||
<script>
|
||||
layui.use(['table', 'form', 'laydate'], function(){
|
||||
var table = layui.table;
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
|
||||
// 初始化时间范围选择器
|
||||
laydate.render({
|
||||
elem: '#timeRange',
|
||||
type: 'datetime',
|
||||
range: true
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.render({
|
||||
elem: '#operationLogTable',
|
||||
url: '{:url("log/operation")}',
|
||||
method: 'post',
|
||||
toolbar: '#tableToolbar',
|
||||
defaultToolbar: ['filter', 'exports', 'print'],
|
||||
parseData: function(res) {
|
||||
return {
|
||||
"code": res.code === 0 ? 0 : 1,
|
||||
"msg": res.msg,
|
||||
"count": res.count,
|
||||
"data": res.data
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{field: 'id', title: 'ID', width: 80, sort: true},
|
||||
{field: 'username', title: '用户名', width: 120},
|
||||
{field: 'module', title: '模块', width: 120},
|
||||
{field: 'operation', title: '操作', width: 120},
|
||||
{field: 'request_method', title: '请求方法', width: 100},
|
||||
{field: 'request_url', title: '请求URL', width: 200},
|
||||
{field: 'request_params', title: '请求参数', width: 200},
|
||||
{field: 'ip_address', title: 'IP地址', width: 130},
|
||||
{field: 'status', title: '状态', width: 100, templet: function(d){
|
||||
return d.status == 1 ?
|
||||
'<span class="layui-badge layui-bg-green">成功</span>' :
|
||||
'<span class="layui-badge layui-bg-red">失败</span>';
|
||||
}},
|
||||
{field: 'error_message', title: '错误信息', width: 150},
|
||||
{field: 'operation_time', title: '操作时间', width: 180, sort: true},
|
||||
{field: 'execution_time', title: '执行时间(ms)', width: 120, sort: true},
|
||||
{title: '操作', toolbar: '#tableBar', width: 80, fixed: 'right'}
|
||||
]],
|
||||
page: true,
|
||||
limit: 10,
|
||||
limits: [10, 20, 50, 100]
|
||||
});
|
||||
|
||||
// 监听搜索表单提交
|
||||
form.on('submit(searchForm)', function(data){
|
||||
var timeRange = data.field.time_range;
|
||||
if(timeRange){
|
||||
var times = timeRange.split(' - ');
|
||||
data.field.start_time = times[0];
|
||||
data.field.end_time = times[1];
|
||||
}
|
||||
delete data.field.time_range;
|
||||
|
||||
table.reload('operationLogTable', {
|
||||
where: data.field,
|
||||
page: {curr: 1}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// 监听工具条
|
||||
table.on('tool(operationLogTable)', function(obj){
|
||||
var data = obj.data;
|
||||
if(obj.event === 'del'){
|
||||
layer.confirm('确定删除这条日志吗?', function(index){
|
||||
$.post('{:url("log/deleteOperation")}', {id: data.id}, function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
obj.del();
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听头工具栏事件
|
||||
table.on('toolbar(operationLogTable)', function(obj){
|
||||
if(obj.event === 'clearAll'){
|
||||
layer.confirm('确定要清空所有操作日志吗?', function(index){
|
||||
$.post('{:url("log/clearOperation")}', function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
table.reload('operationLogTable');
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -40,7 +40,7 @@
|
||||
</div>
|
||||
<div class="layui-col-xs5">
|
||||
<div style="margin-left:10px;">
|
||||
<img src="{:captcha_src()}" class="layadmin-user-login-codeimg" id="img"
|
||||
<img src="{:captcha_src()}?t={:time()}" class="layadmin-user-login-codeimg" id="img"
|
||||
onclick="reloadImg()">
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,7 +75,8 @@
|
||||
});
|
||||
// 重新生成验证码
|
||||
function reloadImg() {
|
||||
$('#img').attr('src', '{:captcha_src()}?rand=' + Math.random());
|
||||
var timestamp = new Date().getTime();
|
||||
$('#img').attr('src', '{:captcha_src()}?t=' + timestamp);
|
||||
}
|
||||
|
||||
// 登录处理函数
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
<?php
|
||||
// 中间件配置
|
||||
return [
|
||||
// 别名或分组
|
||||
'alias' => [],
|
||||
'alias' => [
|
||||
'auth' => \app\middleware\Auth::class,
|
||||
],
|
||||
// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
|
||||
'priority' => [],
|
||||
// 全局中间件
|
||||
'global' => [
|
||||
\app\middleware\Auth::class,
|
||||
],
|
||||
];
|
||||
@@ -86,12 +86,12 @@ html{
|
||||
/* 侧边菜单 */
|
||||
.layui-side-menu .layui-side-scroll{width: 240px;}
|
||||
.layui-side-menu .layui-nav{width: 220px; margin-top: 70px; background: none;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item a{height: 60px; line-height: 60px; padding-left: 45px; padding-right: 30px;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item a{height: 40px; line-height: 40px; padding-left: 45px; padding-right: 30px;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item > a{padding-top: 8px; padding-bottom: 8px;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item a:hover{background: none;}
|
||||
.layui-side-menu .layui-nav .layui-nav-itemed > .layui-nav-child{padding: 5px 0;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item .layui-icon{position: absolute; top: 50%; left: 20px; margin-top: -35px;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item .layui-icons{margin-top: -29px;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item .layui-icon{position: absolute; top: 50%; left: 20px; margin-top: -25px;}
|
||||
.layui-side-menu .layui-nav .layui-nav-item .layui-icons{margin-top: -20px;}
|
||||
.layui-side-menu .layui-nav .layui-nav-child .layui-nav-child{background: none!important;}
|
||||
.layui-side-menu .layui-nav .layui-nav-child .layui-nav-child a{padding-left: 60px}
|
||||
.layui-side-menu .layui-nav .layui-nav-more{right: 15px;}
|
||||
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).echarts={})}(this,(function(t){"use strict";
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},e(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var i=function(){this.firefox=!1,this.ie=!1,this.edge=!1,this.newEdge=!1,this.weChat=!1},r=new function(){this.browser=new i,this.node=!1,this.wxa=!1,this.worker=!1,this.svgSupported=!1,this.touchEventsSupported=!1,this.pointerEventsSupported=!1,this.domSupported=!1,this.transformSupported=!1,this.transform3dSupported=!1,this.hasGlobalWindow="undefined"!=typeof window};"object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?(r.wxa=!0,r.touchEventsSupported=!0):"undefined"==typeof document&&"undefined"!=typeof self?r.worker=!0:"undefined"==typeof navigator?(r.node=!0,r.svgSupported=!0):function(t,e){var n=e.browser,i=t.match(/Firefox\/([\d.]+)/),r=t.match(/MSIE\s([\d.]+)/)||t.match(/Trident\/.+?rv:(([\d.]+))/),o=t.match(/Edge?\/([\d.]+)/),a=/micromessenger/i.test(t);i&&(n.firefox=!0,n.version=i[1]);r&&(n.ie=!0,n.version=r[1]);o&&(n.edge=!0,n.version=o[1],n.newEdge=+o[1].split(".")[0]>18);a&&(n.weChat=!0);e.svgSupported="undefined"!=typeof SVGRect,e.touchEventsSupported="ontouchstart"in window&&!n.ie&&!n.edge,e.pointerEventsSupported="onpointerdown"in window&&(n.edge||n.ie&&+n.version>=11),e.domSupported="undefined"!=typeof document;var s=document.documentElement.style;e.transform3dSupported=(n.ie&&"transition"in s||n.edge||"WebKitCSSMatrix"in window&&"m11"in new WebKitCSSMatrix||"MozPerspective"in s)&&!("OTransition"in s),e.transformSupported=e.transform3dSupported||n.ie&&+n.version>=9}(navigator.userAgent,r);var o="sans-serif",a="12px "+o;var s,l,u=function(t){var e={};if("undefined"==typeof JSON)return e;for(var n=0;n<t.length;n++){var i=String.fromCharCode(n+32),r=(t.charCodeAt(n)-20)/100;e[i]=r}return e}("007LLmW'55;N0500LLLLLLLLLL00NNNLzWW\\\\WQb\\0FWLg\\bWb\\WQ\\WrWWQ000CL5LLFLL0LL**F*gLLLL5F0LF\\FFF5.5N"),h={createCanvas:function(){return"undefined"!=typeof document&&document.createElement("canvas")},measureText:function(t,e){if(!s){var n=h.createCanvas();s=n&&n.getContext("2d")}if(s)return l!==e&&(l=s.font=e||a),s.measureText(t);t=t||"";var i=/(\d+)px/.exec(e=e||a),r=i&&+i[1]||12,o=0;if(e.indexOf("mono")>=0)o=r*t.length;else for(var c=0;c<t.length;c++){var p=u[t[c]];o+=null==p?r:p*r}return{width:o}},loadImage:function(t,e,n){var i=new Image;return i.onload=e,i.onerror=n,i.src=t,i}};function c(t){for(var e in h)t[e]&&(h[e]=t[e])}var p=V(["Function","RegExp","Date","Error","CanvasGradient","CanvasPattern","Image","Canvas"],(function(t,e){return t["[object "+e+"]"]=!0,t}),{}),d=V(["Int8","Uint8","Uint8Clamped","Int16","Uint16","Int32","Uint32","Float32","Float64"],(function(t,e){return t["[object "+e+"Array]"]=!0,t}),{}),f=Object.prototype.toString,g=Array.prototype,y=g.forEach,v=g.filter,m=g.slice,x=g.map,_=function(){}.constructor,b=_?_.prototype:null,w="__proto__",S=2311;function M(){return S++}function I(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];"undefined"!=typeof console&&console.error.apply(console,t)}function T(t){if(null==t||"object"!=typeof t)return t;var e=t,n=f.call(t);if("[object Array]"===n){if(!pt(t)){e=[];for(var i=0,r=t.length;i<r;i++)e[i]=T(t[i])}}else if(d[n]){if(!pt(t)){var o=t.constructor;if(o.from)e=o.from(t);else{e=new o(t.length);for(i=0,r=t.length;i<r;i++)e[i]=t[i]}}}else if(!p[n]&&!pt(t)&&!J(t))for(var a in e={},t)t.hasOwnProperty(a)&&a!==w&&(e[a]=T(t[a]));return e}function C(t,e,n){if(!q(e)||!q(t))return n?T(e):t;for(var i in e)if(e.hasOwnProperty(i)&&i!==w){var r=t[i],o=e[i];!q(o)||!q(r)||Y(o)||Y(r)||J(o)||J(r)||K(o)||K(r)||pt(o)||pt(r)?!n&&i in t||(t[i]=T(e[i])):C(r,o,n)}return t}function D(t,e){for(var n=t[0],i=1,r=t.length;i<r;i++)n=C(n,t[i],e);return n}function A(t,e){if(Object.assign)Object.assign(t,e);else for(var n in e)e.hasOwnProperty(n)&&n!==w&&(t[n]=e[n]);return t}function k(t,e,n){for(var i=G(e),r=0;r<i.length;r++){var o=i[r];(n?null!=e[o]:null==t[o])&&(t[o]=e[o])}return t}var L=h.createCanvas;function P(t,e){if(t){if(t.indexOf)return t.indexOf(e);for(var n=0,i=t.length;n<i;n++)if(t[n]===e)return n}return-1}function O(t,e){var n=t.prototype;function i(){}for(var r in i.prototype=e.prototype,t.prototype=new i,n)n.hasOwnProperty(r)&&(t.prototype[r]=n[r]);t.prototype.constructor=t,t.superClass=e}function R(t,e,n){if(t="prototype"in t?t.prototype:t,e="prototype"in e?e.prototype:e,Object.getOwnPropertyNames)for(var i=Object.getOwnPropertyNames(e),r=0;r<i.length;r++){var o=i[r];"constructor"!==o&&(n?null!=e[o]:null==t[o])&&(t[o]=e[o])}else k(t,e,n)}function N(t){return!!t&&("string"!=typeof t&&"number"==typeof t.lengLine truncated
|
||||
/*!
|
||||
* ZRender, a high performance 2d drawing library.
|
||||
*
|
||||
* Copyright (c) 2013, Baidu Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* LICENSE
|
||||
* https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
|
||||
*/
|
||||
var Vr={},Br={};var Fr=function(){function t(t,e,n){var i=this;this._sleepAfterStill=10,this._stillFrameAccum=0,this._needsRefresh=!0,this._needsRefreshHover=!0,this._darkMode=!1,n=n||{},this.dom=e,this.id=t;var o=new rn,a=n.renderer||"canvas";Vr[a]||(a=G(Vr)[0]),n.useDirtyRect=null!=n.useDirtyRect&&n.useDirtyRect;var s=new Vr[a](e,o,n,t),l=n.ssr||s.ssrOnly;this.storage=o,this.painter=s;var u,h=r.node||r.worker||l?null:new ir(s.getViewportRoot(),s.root),c=n.useCoarsePointer;(null==c||"auto"===c?r.touchEventsSupported:!!c)&&(u=rt(n.pointerSize,44)),this.handler=new Ye(o,s,h,s.root,u),this.animation=new Fi({stage:{update:l?null:function(){return i._flush(!0)}}}),l||this.animation.start()}return t.prototype.add=function(t){t&&(this.storage.addRoot(t),t.addSelfToZr(this),this.refresh())},t.prototype.remove=function(t){t&&(this.storage.delRoot(t),t.removeSelfFromZr(this),this.refresh())},t.prototype.configLayer=function(t,e){this.painter.configLayer&&this.painter.configLayer(t,e),this.refresh()},t.prototype.setBackgroundColor=function(t){this.painter.setBackgroundColor&&this.painter.setBackgroundColor(t),this.refresh(),this._backgroundColor=t,this._darkMode=function(t){if(!t)return!1;if("string"==typeof t)return oi(t,1)<.4;if(t.colorStops){for(var e=t.colorStops,n=0,i=e.length,r=0;r<i;r++)n+=oi(e[r].color,1);return(n/=i)<.4}return!1}(t)},t.prototype.getBackgroundColor=function(){return this._backgroundColor},t.prototype.setDarkMode=function(t){this._darkMode=t},t.prototype.isDarkMode=function(){return this._darkMode},t.prototype.refreshImmediately=function(t){t||this.animation.update(!0),this._needsRefresh=!1,this.painter.refresh(),this._needsRefresh=!1},t.prototype.refresh=function(){this._needsRefresh=!0,this.animation.start()},t.prototype.flush=function(){this._flush(!1)},t.prototype._flush=function(t){var e,n=zi();this._needsRefresh&&(e=!0,this.refreshImmediately(t)),this._needsRefreshHover&&(e=!0,this.refreshHoverImmediately());var i=zi();e?(this._stillFrameAccum=0,this.trigger("rendered",{elapsedTime:i-n})):this._sleepAfterStill>0&&(this._stillFrameAccum++,this._stillFrameAccum>this._sleepAfterStill&&this.animation.stop())},t.prototype.setSleepAfterStill=function(t){this._sleepAfterStill=t},t.prototype.wakeUp=function(){this.animation.start(),this._stillFrameAccum=0},t.prototype.refreshHover=function(){this._needsRefreshHover=!0},t.prototype.refreshHoverImmediately=function(){this._needsRefreshHover=!1,this.painter.refreshHover&&"canvas"===this.painter.getType()&&this.painter.refreshHover()},t.prototype.resize=function(t){t=t||{},this.painter.resize(t.width,t.height),this.handler.resize()},t.prototype.clearAnimation=function(){this.animation.clear()},t.prototype.getWidth=function(){return this.painter.getWidth()},t.prototype.getHeight=function(){return this.painter.getHeight()},t.prototype.setCursorStyle=function(t){this.handler.setCursorStyle(t)},t.prototype.findHover=function(t,e){return this.handler.findHover(t,e)},t.prototype.on=function(t,e,n){return this.handler.on(t,e,n),this},t.prototype.off=function(t,e){this.handler.off(t,e)},t.prototype.trigger=function(t,e){this.handler.trigger(t,e)},t.prototype.clear=function(){for(var t=this.storage.getRoots(),e=0;e<t.length;e++)t[e]instanceof zr&&t[e].removeSelfFromZr(this);this.storage.delAllRoots(),this.painter.clear()},t.prototype.dispose=function(){var t;this.animation.stop(),this.clear(),this.storage.dispose(),this.painter.dispose(),this.handler.dispose(),this.animation=this.storage=this.painter=this.handler=null,t=this.id,delete Br[t]},t}();function Gr(t,e){var n=new Fr(M(),t,e);return Br[n.id]=n,n}function Wr(t,e){Vr[t]=e}var Hr=Object.freeze({__proto__:null,init:Gr,dispose:function(t){t.dispose()},disposeAll:function(){for(var t in Br)Br.hasOwnProperty(t)&&Br[t].dispose();Br={}},getInstance:function(t){return Br[t]},registerPainter:Wr,version:"5.4.4"}),Yr=1e-4;function Xr(t,e,n,i){var r=e[0],o=e[1],a=n[0],s=n[1],l=o-r,u=s-a;if(0===l)return 0===u?a:(a+s)/2;if(i)if(l>0){if(t<=r)return a;if(t>=o)return s}else{if(t>=r)return a;if(t<=o)return s}else{if(t===r)return a;if(t===o)return s}return(t-r)/l*u+a}function Ur(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return U(t)?(n=t,n.replace(/^\s+|\s+$/g,"")).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t;var n}function Zr(t,e,n){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),n?t:+t}function jr(t){return t.sort((function(t,e){return t-e})),t}function qr(t){if(t=+t,isNaN(t))return 0;if(t>1e-14)for(var e=1,n=0;n<15;n++,e*=10)if(Math.round(t*e)/e===t)return n;return Kr(t)}function Kr(t){var e=t.toString().toLowerCase(),n=e.indexOf("e"),i=n>0?+e.slice(n+1):0,r=n>0?n:e.length,o=e.indexOf("."),a=o<0?0:r-1-o;return Math.max(0,a-i)}function $r(t,e){var n=Math.log,i=Math.LN10,r=Math.floor(n(t[1]-t[0])/i),o=Math.round(n(Math.abs(e[1]-e[0]))/i),a=Math.min(Math.max(-r+o,0),20);return isFinite(a)?a:20}functLine truncated
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
||||
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}function fe(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}ce.fn=ce.prototype={jquery:t,constructor:ce,length:0,toArray:function(){return ae.call(this)},get:function(e){return null==e?ae.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=ce.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return ce.each(this,e)},map:function(n){return this.pushStack(ce.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(ae.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(ce.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(ce.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:oe.sort,splice:oe.splice},ce.extend=ce.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||v(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(ce.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||ce.isPlainObject(n)?n:{},i=!1,a[t]=ce.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},ce.extend({expando:"jQuery"+(t+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==i.call(e))&&(!(t=r(e))||"function"==typeof(n=ue.call(t,"constructor")&&t.constructor)&&o.call(n)===a)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){m(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(c(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},text:function(e){var t,n="",r=0,i=e.nodeType;if(!i)while(t=e[r++])n+=ce.text(t);return 1===i||11===i?e.textContent:9===i?e.documentElement.textContent:3===i||4===i?e.nodeValue:n},makeArray:function(e,t){var n=t||[];return null!=e&&(c(Object(e))?ce.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:se.call(t,e,n)},isXMLDoc:function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!l.test(t||n&&n.nodeName||"HTML")},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(c(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:le}),"function"==typeof Symbol&&(ce.fn[Symbol.iterator]=oe[Symbol.iterator]),ce.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var pe=oe.pop,de=oe.sort,he=oe.splice,ge="[\\x20\\t\\r\\n\\f]",ve=new RegExp("^"+ge+"+|((?:^|[^\\\\])(?:\\\\.)*)"+ge+"+$","g");ce.contains=function(e,t){var n=t&&t.parentNode;return e===n||!(!n||1!==n.nodeType||!(e.contains?e.contains(n):e.compareDocumentPosition&&16&e.compareDocumentPosition(n)))};var f=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;function p(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e}ce.escapeSelector=function(e){return(e+"").replace(f,p)};var ye=C,me=s;!function(){var e,b,w,o,a,T,r,C,d,i,k=me,S=ce.expando,E=0,n=0,s=W(),c=W(),u=W(),h=W(),l=function(e,t){return e===t&&(a=!0),0},f="checked|selected|async|autofocus|autoplay|conLine truncated
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php /*a:1:{s:49:"E:\Demo\PHP\yunzer\app\admin\view\login\index.php";i:1747321871;}*/ ?>
|
||||
<?php /*a:1:{s:49:"E:\Demo\PHP\yunzer\app\admin\view\login\index.php";i:1747586453;}*/ ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</div>
|
||||
<div class="layui-col-xs5">
|
||||
<div style="margin-left:10px;">
|
||||
<img src="<?php echo captcha_src(); ?>" class="layadmin-user-login-codeimg" id="img"
|
||||
<img src="<?php echo captcha_src(); ?>?t=<?php echo time(); ?>" class="layadmin-user-login-codeimg" id="img"
|
||||
onclick="reloadImg()">
|
||||
</div>
|
||||
</div>
|
||||
@@ -76,7 +76,8 @@
|
||||
});
|
||||
// 重新生成验证码
|
||||
function reloadImg() {
|
||||
$('#img').attr('src', '<?php echo captcha_src(); ?>?rand=' + Math.random());
|
||||
var timestamp = new Date().getTime();
|
||||
$('#img').attr('src', '<?php echo captcha_src(); ?>?t=' + timestamp);
|
||||
}
|
||||
|
||||
// 登录处理函数
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
<?php /*a:3:{s:56:"E:\Demo\PHP\yunzer\app\admin\view\yunzer\configvalue.php";i:1747402501;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<style>
|
||||
.config-container {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
/* box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); */
|
||||
}
|
||||
.config-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.config-header span {
|
||||
font-size: 18px;
|
||||
color: #2c3e50;
|
||||
font-weight: 500;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.config-header a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.config-header a span {
|
||||
padding: 6px 15px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.config-header a span:hover {
|
||||
background: #e9ecef;
|
||||
color: #409EFF;
|
||||
}
|
||||
.layui-form-item {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.layui-form-label {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
.layui-input {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.layui-input:focus {
|
||||
border-color: #409EFF;
|
||||
}
|
||||
.layui-textarea {
|
||||
border-radius: 4px;
|
||||
min-height: 100px;
|
||||
}
|
||||
.layui-word-aux {
|
||||
color: #909399;
|
||||
}
|
||||
.layui-btn {
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.layui-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
.upload-preview {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.upload-preview img {
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.upload-preview img:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
.save-button-container {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.save-button-container .layui-btn {
|
||||
padding: 0 50px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="config-container">
|
||||
<div class="config-header">
|
||||
<span>站点配置</span>
|
||||
<!-- <a href="<?php echo htmlentities((string) $config['admin_route']); ?>Yunzer/configlist">
|
||||
<span>站点管理</span>
|
||||
</a> -->
|
||||
</div>
|
||||
|
||||
<form class="layui-form">
|
||||
<?php foreach($lists as $lists_v): if(($lists_v['config_type'] == 1)): ?>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><?php echo htmlentities((string) $lists_v['config_info']); ?></label>
|
||||
<div class="layui-input-inline" style="width: 350px;">
|
||||
<input type="text" class="layui-input" id="<?php echo htmlentities((string) $lists_v['config_name']); ?>" name="<?php echo htmlentities((string) $lists_v['config_name']); ?>" placeholder="<?php echo htmlentities((string) $lists_v['config_desc']); ?>" value="<?php echo htmlentities((string) $lists_v['config_value']); ?>">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux"><?php echo htmlentities((string) $lists_v['config_desc']); ?></div>
|
||||
</div>
|
||||
<?php elseif(($lists_v['config_type'] == 2)): ?>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><?php echo htmlentities((string) $lists_v['config_info']); ?></label>
|
||||
<div class="layui-input-inline">
|
||||
<button type="button" class="layui-btn layui-btn-normal" id="<?php echo htmlentities((string) $lists_v['config_name']); ?>">
|
||||
<i class="layui-icon layui-icon-upload"></i> 上传图片
|
||||
</button>
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux"><?php echo htmlentities((string) $lists_v['config_desc']); ?></div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><?php echo htmlentities((string) $lists_v['config_info']); ?>预览</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-upload-list upload-preview" id="yulan_<?php echo htmlentities((string) $lists_v['config_name']); ?>" style="width:90%;">
|
||||
<?php if(!empty($lists_v['config_value'])): ?>
|
||||
<div class="upload_pic_li" style="position:relative;width:120px;margin:0 10px 10px 0">
|
||||
<img style="background-color: #efefef;height:120px;object-fit:cover;" src="<?php echo htmlentities((string) $lists_v['config_value']); ?>" class="layui-upload-img" onmouseover="show_img(this)" onmouseleave="hide_img()">
|
||||
<input type="hidden" name="<?php echo htmlentities((string) $lists_v['config_name']); ?>" value="<?php echo htmlentities((string) $lists_v['config_value']); ?>"/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','upload'],function(){
|
||||
layer = layui.layer;
|
||||
upload = layui.upload;
|
||||
$ = layui.jquery;
|
||||
|
||||
upload.render({
|
||||
elem: "#<?php echo htmlentities((string) $lists_v['config_name']); ?>",
|
||||
url: "<?php echo htmlentities((string) $config['admin_route']); ?>index/upload_img",
|
||||
multiple: true,
|
||||
done: function(res,title){
|
||||
if(res.code > 0){
|
||||
return layer.msg("上传失败,"+res.msg, {icon: 2});
|
||||
}else{
|
||||
$("#yulan_<?php echo htmlentities((string) $lists_v['config_name']); ?>").html('<div class="upload_pic_li" style="position:relative;width:120px;margin:0 10px 10px 0"><img style="width:120px;height:120px;object-fit:cover;" src="'+ res.url +'" class="layui-upload-img" onmouseover="show_img(this)" onmouseleave="hide_img()"><input type="hidden" name="<?php echo htmlentities((string) $lists_v['config_name']); ?>" value="'+res.data+'"/></div>');
|
||||
layer.msg("上传成功", {icon: 1});
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<?php elseif(($lists_v['config_type'] == 3)): ?>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><?php echo htmlentities((string) $lists_v['config_info']); ?></label>
|
||||
<div class="layui-input-block">
|
||||
<textarea class="layui-textarea" id="<?php echo htmlentities((string) $lists_v['config_name']); ?>" name="<?php echo htmlentities((string) $lists_v['config_name']); ?>" placeholder="<?php echo htmlentities((string) $lists_v['config_desc']); ?>"><?php echo htmlentities((string) $lists_v['config_value']); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</form>
|
||||
|
||||
<div class="save-button-container">
|
||||
<button type="button" class="layui-btn layui-btn-normal" onclick="save()">
|
||||
<i class="layui-icon layui-icon-ok"></i> 保存配置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function save(){
|
||||
var loadIndex = layer.load(1, {
|
||||
shade: [0.1,'#fff']
|
||||
});
|
||||
$.post('<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/configvalue',$('form').serialize(),function(res){
|
||||
layer.close(loadIndex);
|
||||
if(res.code>0){
|
||||
layer.msg(res.msg,{'icon':2});
|
||||
}else{
|
||||
layer.msg(res.msg,{'icon':1});
|
||||
setTimeout(function(){
|
||||
history.go(0);
|
||||
}, 1000);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
</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>
|
||||
@@ -0,0 +1,277 @@
|
||||
<?php /*a:3:{s:55:"E:\Demo\PHP\yunzer\app\admin\view\yunzer\buttoninfo.php";i:1745855804;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-breadcrumb">
|
||||
<a href="<?php echo htmlentities((string) $config['admin_route']); ?>Yunzer/menuInfo"><i class="layui-icon layui-icon-menu-fill"></i> 上级菜单</a>
|
||||
<a><cite>本级菜单</cite></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md6" style="text-align: right;">
|
||||
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm" onclick="add(<?php echo htmlentities((string) $smid); ?>)">
|
||||
<i class="layui-icon layui-icon-add-1"></i> 添加按钮
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header"><i class="layui-icon layui-icon-tree"></i> 菜单结构</div>
|
||||
<div class="layui-card-body" id="menuTree">
|
||||
<!-- 树形结构将在这里渲染 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md9">
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>排序</th>
|
||||
<th>类型</th>
|
||||
<th>按钮名</th>
|
||||
<th>图标</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if(is_array($lists) || $lists instanceof \think\Collection || $lists instanceof \think\Paginator): $i = 0; $__LIST__ = $lists;if( count($__LIST__)==0 ) : echo "" ;else: foreach($__LIST__ as $key=>$vo): $mod = ($i % 2 );++$i;?>
|
||||
<tr>
|
||||
<td><span class="layui-badge layui-bg-gray"><?php echo htmlentities((string) $vo['sort']); ?></span></td>
|
||||
<td>
|
||||
<?php if(($vo['type']==1)): ?>
|
||||
<span class="layui-badge layui-bg-blue">功能模块</span> <?php echo htmlentities((string) $vo['src']); elseif(($vo['type']==2)): ?>
|
||||
<span class="layui-badge layui-bg-green">超链接</span> <?php echo htmlentities((string) $vo['src']); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><b><?php echo htmlentities((string) $vo['label']); ?></b></td>
|
||||
<td><i class="layui-icon <?php echo htmlentities((string) $vo['icon_class']); ?>"></i> <?php echo htmlentities((string) $vo['icon_class']); ?></td>
|
||||
<td>
|
||||
<?php if(($vo['status']==1)): ?>
|
||||
<span class="layui-badge layui-bg-green">开启</span>
|
||||
<?php else: ?>
|
||||
<span class="layui-badge layui-bg-red">禁用</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<div class="layui-btn-group">
|
||||
<button type="button" class="layui-btn layui-btn-xs" onclick="edit(<?php echo htmlentities((string) $vo['smid']); ?>)">
|
||||
<i class="layui-icon layui-icon-edit"></i> 编辑
|
||||
</button>
|
||||
<button type="button" class="layui-btn layui-btn-xs layui-btn-danger" onclick="del(<?php echo htmlentities((string) $vo['smid']); ?>)">
|
||||
<i class="layui-icon layui-icon-delete"></i> 删除
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; endif; else: echo "" ;endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer', 'tree'], function(){
|
||||
layer = layui.layer;
|
||||
$ = layui.jquery;
|
||||
var tree = layui.tree;
|
||||
|
||||
// 构建树形结构数据
|
||||
var treeData = [{
|
||||
title: '当前菜单',
|
||||
id: <?php echo htmlentities((string) $smid); ?>,
|
||||
spread: true,
|
||||
children: []
|
||||
}];
|
||||
|
||||
// 将按钮数据添加到树中
|
||||
<?php if(is_array($lists) || $lists instanceof \think\Collection || $lists instanceof \think\Paginator): $i = 0; $__LIST__ = $lists;if( count($__LIST__)==0 ) : echo "" ;else: foreach($__LIST__ as $key=>$vo): $mod = ($i % 2 );++$i;?>
|
||||
treeData[0].children.push({
|
||||
title: '<?php echo htmlentities((string) $vo['label']); ?>',
|
||||
id: <?php echo htmlentities((string) $vo['smid']); ?>,
|
||||
icon: 'layui-icon <?php echo htmlentities((string) $vo['icon_class']); ?>'
|
||||
});
|
||||
<?php endforeach; endif; else: echo "" ;endif; ?>
|
||||
|
||||
// 渲染树形结构
|
||||
tree.render({
|
||||
elem: '#menuTree',
|
||||
data: treeData,
|
||||
showLine: true,
|
||||
click: function(obj){
|
||||
var data = obj.data;
|
||||
if(data.id != <?php echo htmlentities((string) $smid); ?>) {
|
||||
edit(data.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 添加
|
||||
function add(smid){
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '添加按钮',
|
||||
shade: 0.3,
|
||||
area: ['550px','550px'],
|
||||
content: '<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/buttonadd?smid='+smid
|
||||
});
|
||||
}
|
||||
|
||||
// 编辑
|
||||
function edit(smid){
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '编辑按钮',
|
||||
shade: 0.3,
|
||||
area: ['550px','550px'],
|
||||
content: '<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/buttonedit?smid='+smid
|
||||
});
|
||||
}
|
||||
|
||||
// 删除
|
||||
function del(smid){
|
||||
layer.confirm('确定要删除吗?', {
|
||||
icon: 3,
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
$.post('<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/buttondel',{'smid':smid},function(res){
|
||||
if(res.code>0){
|
||||
layer.alert(res.msg,{icon:2});
|
||||
}else{
|
||||
layer.msg(res.msg,{icon:1});
|
||||
setTimeout(function(){window.location.reload();},1000);
|
||||
}
|
||||
},'json');
|
||||
});
|
||||
}
|
||||
</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>
|
||||
@@ -0,0 +1,269 @@
|
||||
<?php /*a:2:{s:51:"E:\Demo\PHP\yunzer\app\admin\view\log\operation.php";i:1747584845;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;}*/ ?>
|
||||
<!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;">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
<span class="layui-badge layui-bg-blue">操作日志</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<form class="layui-form layui-form-pane" action="">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="username" placeholder="请输入用户名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">模块</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="module" placeholder="请输入模块" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">操作</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="operation" placeholder="请输入操作" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="status">
|
||||
<option value="">全部</option>
|
||||
<option value="1">成功</option>
|
||||
<option value="0">失败</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">时间范围</label>
|
||||
<div class="layui-input-inline" style="width: 300px;">
|
||||
<input type="text" name="time_range" class="layui-input" id="timeRange" placeholder="请选择时间范围">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button class="layui-btn" lay-submit lay-filter="searchForm">
|
||||
<i class="layui-icon layui-icon-search"></i> 搜索
|
||||
</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table id="operationLogTable" lay-filter="operationLogTable"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="tableToolbar">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="clearAll">
|
||||
<i class="layui-icon layui-icon-delete"></i> 清空日志
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tableBar">
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
<script src="/static/layui/layui.js"></script>
|
||||
<script>
|
||||
layui.use(['table', 'form', 'laydate'], function(){
|
||||
var table = layui.table;
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
|
||||
// 初始化时间范围选择器
|
||||
laydate.render({
|
||||
elem: '#timeRange',
|
||||
type: 'datetime',
|
||||
range: true
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.render({
|
||||
elem: '#operationLogTable',
|
||||
url: '<?php echo url("log/operation"); ?>',
|
||||
method: 'post',
|
||||
toolbar: '#tableToolbar',
|
||||
defaultToolbar: ['filter', 'exports', 'print'],
|
||||
parseData: function(res) {
|
||||
return {
|
||||
"code": res.code === 0 ? 0 : 1,
|
||||
"msg": res.msg,
|
||||
"count": res.count,
|
||||
"data": res.data
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{field: 'id', title: 'ID', width: 80, sort: true},
|
||||
{field: 'username', title: '用户名', width: 120},
|
||||
{field: 'module', title: '模块', width: 120},
|
||||
{field: 'operation', title: '操作', width: 120},
|
||||
{field: 'request_method', title: '请求方法', width: 100},
|
||||
{field: 'request_url', title: '请求URL', width: 200},
|
||||
{field: 'request_params', title: '请求参数', width: 200},
|
||||
{field: 'ip_address', title: 'IP地址', width: 130},
|
||||
{field: 'status', title: '状态', width: 100, templet: function(d){
|
||||
return d.status == 1 ?
|
||||
'<span class="layui-badge layui-bg-green">成功</span>' :
|
||||
'<span class="layui-badge layui-bg-red">失败</span>';
|
||||
}},
|
||||
{field: 'error_message', title: '错误信息', width: 150},
|
||||
{field: 'operation_time', title: '操作时间', width: 180, sort: true},
|
||||
{field: 'execution_time', title: '执行时间(ms)', width: 120, sort: true},
|
||||
{title: '操作', toolbar: '#tableBar', width: 80, fixed: 'right'}
|
||||
]],
|
||||
page: true,
|
||||
limit: 10,
|
||||
limits: [10, 20, 50, 100]
|
||||
});
|
||||
|
||||
// 监听搜索表单提交
|
||||
form.on('submit(searchForm)', function(data){
|
||||
var timeRange = data.field.time_range;
|
||||
if(timeRange){
|
||||
var times = timeRange.split(' - ');
|
||||
data.field.start_time = times[0];
|
||||
data.field.end_time = times[1];
|
||||
}
|
||||
delete data.field.time_range;
|
||||
|
||||
table.reload('operationLogTable', {
|
||||
where: data.field,
|
||||
page: {curr: 1}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// 监听工具条
|
||||
table.on('tool(operationLogTable)', function(obj){
|
||||
var data = obj.data;
|
||||
if(obj.event === 'del'){
|
||||
layer.confirm('确定删除这条日志吗?', function(index){
|
||||
$.post('<?php echo url("log/deleteOperation"); ?>', {id: data.id}, function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
obj.del();
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听头工具栏事件
|
||||
table.on('toolbar(operationLogTable)', function(obj){
|
||||
if(obj.event === 'clearAll'){
|
||||
layer.confirm('确定要清空所有操作日志吗?', function(index){
|
||||
$.post('<?php echo url("log/clearOperation"); ?>', function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
table.reload('operationLogTable');
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php /*a:3:{s:59:"E:\Demo\PHP\yunzer\app\admin\view\yunzeradmin\groupedit.php";i:1745855804;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<form class="layui-form">
|
||||
<input type="hidden" name="group_id" value="<?php echo htmlentities((string) $group['group_id']); ?>">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">角色名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="group_name" placeholder="请输入角色名称" value="<?php echo htmlentities((string) $group['group_name']); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="status" value="1" title="开启" <?php echo $group['status']==1 ? 'checked' : ''; ?>>
|
||||
<input type="radio" name="status" value="0" title="禁用" <?php echo $group['status']==0 ? 'checked' : ''; ?>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-itme">
|
||||
<label class="layui-form-label">权限菜单</label>
|
||||
<?php if(is_array($menus) || $menus instanceof \think\Collection || $menus instanceof \think\Paginator): $i = 0; $__LIST__ = $menus;if( count($__LIST__)==0 ) : echo "" ;else: foreach($__LIST__ as $key=>$vo): $mod = ($i % 2 );++$i;?>
|
||||
<hr>
|
||||
<div class="layui-input-block">
|
||||
<input type="checkbox" name="menu[<?php echo htmlentities((string) $vo['smid']); ?>]" lay-skin="primary" title="<?php echo htmlentities((string) $vo['label']); ?>" <?php echo isset($group['rights']) && $group['rights'] && in_array($vo['smid'],$group['rights'])?'checked':''; ?>>
|
||||
<hr>
|
||||
<?php if(is_array($vo['children']) || $vo['children'] instanceof \think\Collection || $vo['children'] instanceof \think\Paginator): $i = 0; $__LIST__ = $vo['children'];if( count($__LIST__)==0 ) : echo "" ;else: foreach($__LIST__ as $key=>$cvo): $mod = ($i % 2 );++$i;?>
|
||||
<input type="checkbox" name="menu[<?php echo htmlentities((string) $cvo['smid']); ?>]" lay-skin="primary" title="<?php echo htmlentities((string) $cvo['label']); ?>" <?php echo isset($group['rights']) && $group['rights'] && in_array($cvo['smid'],$group['rights'])?'checked':''; ?>>
|
||||
<?php endforeach; endif; else: echo "" ;endif; ?>
|
||||
</div>
|
||||
<?php endforeach; endif; else: echo "" ;endif; ?>
|
||||
</div>
|
||||
</form>
|
||||
<div class="layui-form-item" style="margin-top:10px;">
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn" onclick="save()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','form'],function(){
|
||||
var form = layui.form;
|
||||
layer = layui.layer;
|
||||
$ = layui.jquery;
|
||||
});
|
||||
|
||||
function save(){
|
||||
$.post("<?php echo htmlentities((string) $config['admin_route']); ?>yunzeradmin/groupedit",$('form').serialize(),function(res){
|
||||
if(res.code>0){
|
||||
layer.msg(res.msg,{'icon':2});
|
||||
}else{
|
||||
layer.msg(res.msg,{'icon':1});
|
||||
setTimeout(function(){parent.window.location.reload();},1000);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
</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>
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php /*a:3:{s:59:"E:\Demo\PHP\yunzer\app\admin\view\yunzeradmin\groupinfo.php";i:1747402501;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<div class="config-container">
|
||||
<!-- 页面头部样式 -->
|
||||
<div class="config-header" style="display: flex;flex-direction: column;flex-wrap: wrap;align-items: flex-start;">
|
||||
<div class="maintitle">
|
||||
<i class="layui-icon layui-icon-group"></i>
|
||||
<span>角色列表</span>
|
||||
</div>
|
||||
<div style="display: flex;align-items: flex-start;flex-direction: column;gap: 15px;margin-bottom: 10px;">
|
||||
<div>
|
||||
<button class="layui-btn layui-bg-blue" onclick="add()">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加
|
||||
</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary layui-border-blue" onclick="refresh()">
|
||||
<i class="layui-icon layui-icon-refresh"></i>刷新
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="layui-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>角色名</th>
|
||||
<th>状态</th>
|
||||
<th>添加时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if(is_array($group) || $group instanceof \think\Collection || $group instanceof \think\Paginator): $i = 0; $__LIST__ = $group;if( count($__LIST__)==0 ) : echo "" ;else: foreach($__LIST__ as $key=>$vo): $mod = ($i % 2 );++$i;?>
|
||||
<tr>
|
||||
<td><?php echo htmlentities((string) $vo['group_name']); ?></td>
|
||||
<td><?php echo $vo['status']==1 ? '开启' : '<span style="color:red;">禁用</span>'; ?></td>
|
||||
<td><?php echo date('Y-m-d H:i:s',$vo['create_time']); ?></td>
|
||||
<td>
|
||||
<button type="button" class="layui-btn layui-btn-primary layui-btn-xs"
|
||||
onclick="edit(<?php echo htmlentities((string) $vo['group_id']); ?>)">
|
||||
<i class="layui-icon layui-icon-edit"></i>编辑
|
||||
</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary layui-btn-xs"
|
||||
onclick="del(<?php echo htmlentities((string) $vo['group_id']); ?>)">
|
||||
<i class="layui-icon layui-icon-delete"></i>删除
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; endif; else: echo "" ;endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer'], function () {
|
||||
layer = layui.layer;
|
||||
$ = layui.jquery;
|
||||
});
|
||||
// 添加
|
||||
function add() {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '添加角色',
|
||||
shade: 0.3,
|
||||
area: ['450px', '550px'],
|
||||
content: "<?php echo htmlentities((string) $config['admin_route']); ?>yunzeradmin/groupadd"
|
||||
});
|
||||
}
|
||||
// 编辑
|
||||
function edit(group_id) {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '编辑角色',
|
||||
shade: 0.3,
|
||||
area: ['450px', '550px'],
|
||||
content: "<?php echo htmlentities((string) $config['admin_route']); ?>yunzeradmin/groupedit?group_id=" + group_id
|
||||
});
|
||||
}
|
||||
// 删除
|
||||
function del(group_id) {
|
||||
layer.confirm('确定要删除吗?', {
|
||||
icon: 3,
|
||||
btn: ['确定', '取消']
|
||||
}, function () {
|
||||
$.post("<?php echo htmlentities((string) $config['admin_route']); ?>yunzeradmin/groupdel", { 'group_id': group_id }, function (res) {
|
||||
if (res.code > 0) {
|
||||
layer.alert(res.msg, { icon: 2 });
|
||||
} else {
|
||||
layer.msg(res.msg, { icon: 1 });
|
||||
setTimeout(function () { window.location.reload(); }, 1000);
|
||||
}
|
||||
}, 'json');
|
||||
});
|
||||
}
|
||||
//刷新列表
|
||||
function refresh() {
|
||||
window.location.reload();
|
||||
}
|
||||
</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>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php /*a:3:{s:51:"E:\Demo\PHP\yunzer\app\admin\view\index\welcome.php";i:1745855804;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<?php /*a:3:{s:51:"E:\Demo\PHP\yunzer\app\admin\view\index\welcome.php";i:1747583088;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -93,80 +93,207 @@
|
||||
</script>
|
||||
</head>
|
||||
<body style="padding:10px; box-sizing: border-box;">
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<style>
|
||||
.dashboard-container {
|
||||
padding: 20px;
|
||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||
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 {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
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 {
|
||||
color: #3881fd;
|
||||
font-weight: 300;
|
||||
font-size: 28px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.welcome-header p {
|
||||
font-size: 15px;
|
||||
opacity: 0.9;
|
||||
margin: 0;
|
||||
}
|
||||
.stats-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
margin-bottom: 30px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.stat-card {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
|
||||
padding: 20px;
|
||||
min-width: 200px;
|
||||
flex: 1;
|
||||
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 5px 15px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.stat-card .stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #3881fd;
|
||||
margin: 10px 0;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
margin: 12px 0;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
.stat-card .stat-title {
|
||||
color: #7f8c8d;
|
||||
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-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.quick-actions h2 {
|
||||
color: #2c3e50;
|
||||
color: #1e293b;
|
||||
font-size: 18px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 500;
|
||||
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: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.action-button {
|
||||
background-color: #f8f9fa;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 10px 15px;
|
||||
color: #3881fd;
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 12px 16px;
|
||||
color: #1e293b;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
.action-button:hover {
|
||||
background-color: #e9ecef;
|
||||
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: #1e293b;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.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>
|
||||
|
||||
@@ -179,34 +306,84 @@
|
||||
<div class="stats-container">
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">用户总数</div>
|
||||
<div class="stat-value">1,234</div>
|
||||
<div class="stat-value"><?php echo htmlentities((string) number_format($stats['total_users'])); ?></div>
|
||||
<div class="stat-icon">👥</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">今日访问</div>
|
||||
<div class="stat-value">256</div>
|
||||
<div class="stat-value"><?php echo htmlentities((string) number_format($stats['daily_visits'])); ?></div>
|
||||
<div class="stat-icon">📊</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">数据总量</div>
|
||||
<div class="stat-value">8,642</div>
|
||||
<div class="stat-title">文章总数</div>
|
||||
<div class="stat-value"><?php echo htmlentities((string) number_format($stats['total_articles'])); ?></div>
|
||||
<div class="stat-icon">📝</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-title">系统消息</div>
|
||||
<div class="stat-value">12</div>
|
||||
<div class="stat-title">资源总数</div>
|
||||
<div class="stat-value"><?php echo htmlentities((string) number_format($stats['total_resources'])); ?></div>
|
||||
<div class="stat-icon">📦</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="quick-actions">
|
||||
<h2>快捷操作</h2>
|
||||
<div class="action-buttons">
|
||||
<button class="action-button">用户管理</button>
|
||||
<button class="action-button">内容发布</button>
|
||||
<button class="action-button">数据统计</button>
|
||||
<button class="action-button">系统设置</button>
|
||||
<button class="action-button">清除缓存</button>
|
||||
<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) $activity['icon']); ?></div>
|
||||
<div class="activity-content">
|
||||
<div class="activity-title"><?php echo htmlentities((string) $activity['title']); ?></div>
|
||||
<div class="activity-time"><?php echo htmlentities((string) $activity['time']); ?></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();
|
||||
@@ -217,12 +394,10 @@ function updateTime() {
|
||||
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) + '日 ' +
|
||||
@@ -233,11 +408,296 @@ function updateTime() {
|
||||
document.getElementById('current-time').innerHTML = timeString;
|
||||
}
|
||||
|
||||
// 页面加载完立即执行一次
|
||||
updateTime();
|
||||
// 获取文章统计数据
|
||||
function getArticleCounts() {
|
||||
fetch('<?php echo url("article/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();
|
||||
} else {
|
||||
console.warn('文章统计接口返回异常:', res);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('获取文章统计失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// 每秒更新一次时间
|
||||
// 获取资源统计数据
|
||||
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();
|
||||
} else {
|
||||
console.warn('资源统计接口返回异常:', res);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('获取资源统计失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
updateTime();
|
||||
setInterval(updateTime, 1000);
|
||||
|
||||
// 页面加载完成后获取统计数据
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
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 htmlentities((string) 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 htmlentities((string) json_encode($chartData['visitTrend']['visits'])); ?>,
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
opacity: 0.1
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
},
|
||||
lineStyle: {
|
||||
width: 3
|
||||
}
|
||||
}, {
|
||||
name: '独立访客',
|
||||
data: <?php echo htmlentities((string) 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 htmlentities((string) json_encode($chartData['userGrowth']['dates'])); ?>
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '新增用户',
|
||||
type: 'bar',
|
||||
data: <?php echo htmlentities((string) json_encode($chartData['userGrowth']['newUsers'])); ?>,
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '总用户数',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: <?php echo htmlentities((string) json_encode($chartData['userGrowth']['totalUsers'])); ?>,
|
||||
itemStyle: {
|
||||
color: '#10b981'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
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 htmlentities((string) json_encode($chartData['resourceStats']['dates'])); ?>
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '新增资源',
|
||||
type: 'bar',
|
||||
data: <?php echo htmlentities((string) json_encode($chartData['resourceStats']['resources'])); ?>,
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '下载量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: <?php echo htmlentities((string) json_encode($chartData['resourceStats']['downloads'])); ?>,
|
||||
itemStyle: {
|
||||
color: '#10b981'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
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 htmlentities((string) json_encode($chartData['articleStats']['dates'])); ?>
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '新增文章',
|
||||
type: 'bar',
|
||||
data: <?php echo htmlentities((string) json_encode($chartData['articleStats']['articles'])); ?>,
|
||||
itemStyle: {
|
||||
color: '#3881fd'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '访问量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: <?php echo htmlentities((string) json_encode($chartData['articleStats']['views'])); ?>,
|
||||
itemStyle: {
|
||||
color: '#10b981'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
chart.setOption(option);
|
||||
}
|
||||
|
||||
// 初始化所有图表
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initVisitTrend();
|
||||
initUserGrowth();
|
||||
initResourceStats();
|
||||
initArticleStats();
|
||||
|
||||
// 监听窗口大小变化,重绘图表
|
||||
window.addEventListener('resize', function() {
|
||||
var charts = document.querySelectorAll('.chart-container');
|
||||
charts.forEach(function(chart) {
|
||||
echarts.getInstanceByDom(chart)?.resize();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php /*a:2:{s:47:"E:\Demo\PHP\yunzer\app\admin\view\log\login.php";i:1747584845;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;}*/ ?>
|
||||
<!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;">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
<span class="layui-badge layui-bg-blue">登录日志</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<form class="layui-form layui-form-pane" action="">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="username" placeholder="请输入用户名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">IP地址</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="ip" placeholder="请输入IP地址" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="status">
|
||||
<option value="">全部</option>
|
||||
<option value="1">成功</option>
|
||||
<option value="0">失败</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">时间范围</label>
|
||||
<div class="layui-input-inline" style="width: 300px;">
|
||||
<input type="text" name="time_range" class="layui-input" id="timeRange" placeholder="请选择时间范围">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button class="layui-btn" lay-submit lay-filter="searchForm">
|
||||
<i class="layui-icon layui-icon-search"></i> 搜索
|
||||
</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table id="loginLogTable" lay-filter="loginLogTable"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="tableToolbar">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="clearAll">
|
||||
<i class="layui-icon layui-icon-delete"></i> 清空日志
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tableBar">
|
||||
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
<script src="/static/layui/layui.js"></script>
|
||||
<script>
|
||||
layui.use(['table', 'form', 'laydate'], function(){
|
||||
var table = layui.table;
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
|
||||
// 初始化时间范围选择器
|
||||
laydate.render({
|
||||
elem: '#timeRange',
|
||||
type: 'datetime',
|
||||
range: true
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.render({
|
||||
elem: '#loginLogTable',
|
||||
url: '<?php echo url("log/login"); ?>',
|
||||
method: 'post',
|
||||
toolbar: '#tableToolbar',
|
||||
defaultToolbar: ['filter', 'exports', 'print'],
|
||||
parseData: function(res) {
|
||||
return {
|
||||
"code": res.code === 0 ? 0 : 1,
|
||||
"msg": res.msg,
|
||||
"count": res.count,
|
||||
"data": res.data
|
||||
};
|
||||
},
|
||||
cols: [[
|
||||
{field: 'id', title: 'ID', width: 80, sort: true},
|
||||
{field: 'username', title: '用户名', width: 120},
|
||||
{field: 'ip_address', title: 'IP地址', width: 130},
|
||||
{field: 'location', title: '登录地点', width: 120},
|
||||
{field: 'device_type', title: '设备类型', width: 100},
|
||||
{field: 'user_agent', title: '浏览器', width: 200},
|
||||
{field: 'login_status', title: '状态', width: 100, templet: function(d){
|
||||
return d.login_status == 1 ?
|
||||
'<span class="layui-badge layui-bg-green">成功</span>' :
|
||||
'<span class="layui-badge layui-bg-red">失败</span>';
|
||||
}},
|
||||
{field: 'failure_reason', title: '失败原因', width: 150},
|
||||
{field: 'login_time', title: '登录时间', width: 180, sort: true},
|
||||
{title: '操作', toolbar: '#tableBar', width: 80, fixed: 'right'}
|
||||
]],
|
||||
page: true,
|
||||
limit: 10,
|
||||
limits: [10, 20, 50, 100]
|
||||
});
|
||||
|
||||
// 监听搜索表单提交
|
||||
form.on('submit(searchForm)', function(data){
|
||||
var timeRange = data.field.time_range;
|
||||
if(timeRange){
|
||||
var times = timeRange.split(' - ');
|
||||
data.field.start_time = times[0];
|
||||
data.field.end_time = times[1];
|
||||
}
|
||||
delete data.field.time_range;
|
||||
|
||||
table.reload('loginLogTable', {
|
||||
where: data.field,
|
||||
page: {curr: 1}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// 监听工具条
|
||||
table.on('tool(loginLogTable)', function(obj){
|
||||
var data = obj.data;
|
||||
if(obj.event === 'del'){
|
||||
layer.confirm('确定删除这条日志吗?', function(index){
|
||||
$.post('<?php echo url("log/deleteLogin"); ?>', {id: data.id}, function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
obj.del();
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听头工具栏事件
|
||||
table.on('toolbar(loginLogTable)', function(obj){
|
||||
if(obj.event === 'clearAll'){
|
||||
layer.confirm('确定要清空所有登录日志吗?', function(index){
|
||||
$.post('<?php echo url("log/clearLogin"); ?>', function(res){
|
||||
if(res.code === 0){
|
||||
layer.msg(res.msg, {icon: 1});
|
||||
table.reload('loginLogTable');
|
||||
}else{
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php /*a:3:{s:52:"E:\Demo\PHP\yunzer\app\admin\view\yunzer\menuadd.php";i:1745855804;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<form class="layui-form">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">菜单名</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="label" placeholder="请输入菜单名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">图标</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="icon_class" lay-verify="required" lay-search="">
|
||||
<option value="">请输入layui图标</option>
|
||||
<?php foreach($iconfont as $icon_v): ?>
|
||||
<option value="<?php echo htmlentities((string) $icon_v['icon_css']); ?>"><?php echo htmlentities((string) $icon_v['icon_css']); ?> <?php echo htmlentities((string) $icon_v['icon_name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="type" lay-filter="type">
|
||||
<option value='0' selected>顶级菜单</option>
|
||||
<option value='1'>内部代码</option>
|
||||
<option value='2'>超链接</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" style="display:none;" id="src1">
|
||||
<label class="layui-form-label">内部代码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="src1" placeholder="请输入:模块/方法">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" style="display:none;" id="src2">
|
||||
<label class="layui-form-label">链接地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="src2" placeholder="请输入http网址">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="number" class="layui-input" name="sort" placeholder="值越大越靠前">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="status" value="1" title="开启" checked>
|
||||
<input type="radio" name="status" value="0" title="禁用">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="layui-form-item" style="margin-top:10px;">
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn" onclick="save()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','form'],function(){
|
||||
var form = layui.form;
|
||||
layer = layui.layer;
|
||||
$ = layui.jquery;
|
||||
|
||||
form.on('select(type)', function(data){
|
||||
if(data.value == 1){
|
||||
$("#src1").show();
|
||||
$("#src2").hide();
|
||||
$("#src3").hide();
|
||||
}else if(data.value == 2){
|
||||
$("#src1").hide();
|
||||
$("#src2").show();
|
||||
$("#src3").hide();
|
||||
}else{
|
||||
$("#src1").hide();
|
||||
$("#src2").hide();
|
||||
$("#src3").hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function save(){
|
||||
$.post('<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/menuadd',$('form').serialize(),function(res){
|
||||
if(res.code>0){
|
||||
layer.msg(res.msg,{'icon':2});
|
||||
}else{
|
||||
layer.msg(res.msg,{'icon':1});
|
||||
setTimeout(function(){parent.window.location.reload();},1000);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
</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>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php /*a:1:{s:49:"E:\Demo\PHP\yunzer\app\admin\view\index\index.php";i:1747402501;}*/ ?>
|
||||
<?php /*a:1:{s:49:"E:\Demo\PHP\yunzer\app\admin\view\index\index.php";i:1747582419;}*/ ?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
<li class="layui-nav-item" data-name="index/welcome">
|
||||
<a href="javascript:;" lay-tips="工作台" lay-direction="2"
|
||||
onclick="menuFire('index/welcome',1)">
|
||||
<i class="layui-icon layui-icon-home" style="margin-top: -30px;"></i>
|
||||
<i class="layui-icon layui-icon-home" style="margin-top: -20px;"></i>
|
||||
<cite>工作台</cite>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
<?php /*a:3:{s:53:"E:\Demo\PHP\yunzer\app\admin\view\yunzer\menuinfo.php";i:1747402501;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<div class="config-container">
|
||||
<!-- 页面头部样式 -->
|
||||
<div class="config-header" style="display: flex;flex-direction: column;flex-wrap: wrap;align-items: flex-start;">
|
||||
<div class="maintitle">
|
||||
<i class="layui-icon layui-icon-picture"></i>
|
||||
<span>菜单管理</span>
|
||||
</div>
|
||||
<div style="display: flex;align-items: flex-start;flex-direction: column;gap: 15px;margin-bottom: 10px;">
|
||||
<div>
|
||||
<button class="layui-btn layui-bg-blue" onclick="add()">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加菜单
|
||||
</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary layui-border-blue" onclick="refresh()">
|
||||
<i class="layui-icon layui-icon-refresh"></i>刷新
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="test7" class="demo-tree"></div>
|
||||
<table class="layui-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center">类型</th>
|
||||
<th style="text-align:center">菜单名</th>
|
||||
<th style="text-align:center">图标</th>
|
||||
<th style="text-align:center">排序</th>
|
||||
<th style="text-align:center">状态</th>
|
||||
<th style="text-align:center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if(is_array($lists) || $lists instanceof \think\Collection || $lists instanceof \think\Paginator): $i = 0; $__LIST__ = $lists;if( count($__LIST__)==0 ) : echo "" ;else: foreach($__LIST__ as $key=>$vo): $mod = ($i % 2 );++$i;?>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<?php if(($vo['type']==1)): ?>
|
||||
功能模块:<?php echo htmlentities((string) $vo['src']); elseif(($vo['type']==2)): ?>
|
||||
超链接:<?php echo htmlentities((string) $vo['src']); else: ?>
|
||||
顶级
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td align="center"><?php echo htmlentities((string) $vo['label']); ?></td>
|
||||
<td align="center"><i class="layui-icon <?php echo htmlentities((string) $vo['icon_class']); ?>"></i> <?php echo htmlentities((string) $vo['icon_class']); ?></td>
|
||||
<td align="center"><?php echo htmlentities((string) $vo['sort']); ?></td>
|
||||
<td align="center"><?php echo $vo['status']==1 ? '开启' : '<span style="color:red;">禁用</span>'; ?></td>
|
||||
<td align="center">
|
||||
<?php if(($vo['type'] == 0)): ?>
|
||||
<button type="button" class="layui-btn layui-btn-xs layui-btn-normal"
|
||||
onclick="buttonInfo(<?php echo htmlentities((string) $vo['smid']); ?>)">下级菜单</button>
|
||||
<?php endif; ?>
|
||||
<button type="button" class="layui-btn layui-btn-xs layui-btn-primary" onclick="edit(<?php echo htmlentities((string) $vo['smid']); ?>)">
|
||||
<i class="layui-icon layui-icon-edit"></i>编辑
|
||||
</button>
|
||||
<button type="button" class="layui-btn layui-btn-xs layui-btn-primary" onclick="del(<?php echo htmlentities((string) $vo['smid']); ?>)">
|
||||
<i class="layui-icon layui-icon-delete"></i>删除
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; endif; else: echo "" ;endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer'], function () {
|
||||
layer = layui.layer;
|
||||
$ = layui.jquery;
|
||||
});
|
||||
// 添加
|
||||
function add() {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '添加菜单',
|
||||
shade: 0.3,
|
||||
area: ['550px', '550px'],
|
||||
content: '<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/menuadd'
|
||||
});
|
||||
}
|
||||
// 编辑
|
||||
function edit(smid) {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '编辑菜单',
|
||||
shade: 0.3,
|
||||
area: ['550px', '550px'],
|
||||
content: '<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/menuedit?smid=' + smid
|
||||
});
|
||||
}
|
||||
// 删除
|
||||
function del(smid) {
|
||||
layer.confirm('确定要删除吗?', {
|
||||
icon: 3,
|
||||
btn: ['确定', '取消']
|
||||
}, function () {
|
||||
$.post('<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/menudel', { 'smid': smid }, function (res) {
|
||||
if (res.code > 0) {
|
||||
layer.alert(res.msg, { icon: 2 });
|
||||
} else {
|
||||
layer.msg(res.msg, { icon: 1 });
|
||||
setTimeout(function () { window.location.reload(); }, 1000);
|
||||
}
|
||||
}, 'json');
|
||||
});
|
||||
}
|
||||
// 按钮列表
|
||||
function buttonInfo(smid) {
|
||||
window.location.href = "<?php echo htmlentities((string) $config['admin_route']); ?>yunzer/buttoninfo?smid=" + smid;
|
||||
}
|
||||
|
||||
//刷新列表
|
||||
function refresh() {
|
||||
window.location.reload();
|
||||
}
|
||||
</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>
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php /*a:3:{s:55:"E:\Demo\PHP\yunzer\app\admin\view\yunzer\buttonedit.php";i:1745855804;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<form class="layui-form">
|
||||
<input type="hidden" name="smid" value="<?php echo htmlentities((string) $lists['smid']); ?>">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">按钮名</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="label" placeholder="请输入按钮名" value="<?php echo htmlentities((string) $lists['label']); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">图标</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="icon_class" lay-verify="required" lay-search="">
|
||||
<option value="">请输入layui图标</option>
|
||||
<?php foreach($iconfont as $icon_v): ?>
|
||||
<option value="<?php echo htmlentities((string) $icon_v['icon_css']); ?>" <?php if(($icon_v['icon_css'] == $lists['icon_class'])): ?>selected<?php endif; ?>><?php echo htmlentities((string) $icon_v['icon_css']); ?> <?php echo htmlentities((string) $icon_v['icon_name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="type" lay-filter="type">
|
||||
<option value='1' <?php echo $lists['type']==1 ? 'selected' : ''; ?>>内部代码</option>
|
||||
<option value='2' <?php echo $lists['type']==2 ? 'selected' : ''; ?>>超链接</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" <?php echo $lists['type']==1 ? 'style="display : none;"':''; ?> id="src1">
|
||||
<label class="layui-form-label">内部代码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="src1" placeholder="请输入:/项目/模块/方法" <?php if($lists['type']==1): ?>value="<?php echo htmlentities((string) $lists['src']); ?>"<?php endif; ?>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" <?php echo $lists['type']==2 ? 'style="display : none;"':''; ?> id="src2">
|
||||
<label class="layui-form-label">链接地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="src2" placeholder="请输入http网址" <?php if($lists['type']==2): ?>value="<?php echo htmlentities((string) $lists['src']); ?>"<?php endif; ?>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="number" class="layui-input" name="sort" placeholder="值越大越靠前" value="<?php echo htmlentities((string) $lists['sort']); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="status" value="1" title="开启" <?php echo $lists['status']==1 ? 'checked' : ''; ?>>
|
||||
<input type="radio" name="status" value="0" title="禁用" <?php echo $lists['status']==0 ? 'checked' : ''; ?>>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="layui-form-item" style="margin-top:10px;">
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn" onclick="save()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','form'],function(){
|
||||
form = layui.form;
|
||||
layer = layui.layer;
|
||||
$ = layui.jquery;
|
||||
|
||||
type(<?php echo htmlentities((string) $lists['type']); ?>);
|
||||
form.on('select(type)', function(data){
|
||||
type(data.value);
|
||||
});
|
||||
});
|
||||
function type(value){
|
||||
if(value == 1){
|
||||
$("#src1").show();
|
||||
$("#src2").hide();
|
||||
$("#src3").hide();
|
||||
}else if(value == 2){
|
||||
$("#src1").hide();
|
||||
$("#src2").show();
|
||||
$("#src3").hide();
|
||||
}else{
|
||||
$("#src1").show();
|
||||
$("#src2").hide();
|
||||
$("#src3").hide();
|
||||
}
|
||||
}
|
||||
function save(){
|
||||
$.post('<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/buttonedit',$('form').serialize(),function(res){
|
||||
if(res.code>0){
|
||||
layer.msg(res.msg,{'icon':2});
|
||||
}else{
|
||||
layer.msg(res.msg,{'icon':1});
|
||||
setTimeout(function(){parent.window.location.reload();},1000);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
</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>
|
||||
@@ -0,0 +1,217 @@
|
||||
<?php /*a:3:{s:54:"E:\Demo\PHP\yunzer\app\admin\view\yunzer\buttonadd.php";i:1745855804;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;s:49:"E:\Demo\PHP\yunzer\app\admin\view\public\tail.php";i:1745855804;}*/ ?>
|
||||
<!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;">
|
||||
<form class="layui-form">
|
||||
<input type="hidden" name="smid" value="<?php echo htmlentities((string) $smid); ?>">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">按钮名</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="label" placeholder="请输入按钮名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">图标</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="icon_class" lay-verify="required" lay-search="">
|
||||
<option value="">请输入layui图标</option>
|
||||
<?php foreach($iconfont as $icon_v): ?>
|
||||
<option value="<?php echo htmlentities((string) $icon_v['icon_css']); ?>"><?php echo htmlentities((string) $icon_v['icon_css']); ?> <?php echo htmlentities((string) $icon_v['icon_name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="type" lay-filter="type">
|
||||
<option value='1' selected>内部代码</option>
|
||||
<option value='2'>超链接</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" id="src1">
|
||||
<label class="layui-form-label">内部代码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="src1" placeholder="请输入:模块/方法">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" style="display:none;" id="src2">
|
||||
<label class="layui-form-label">链接地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" class="layui-input" name="src2" placeholder="请输入http网址">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="number" class="layui-input" name="sort" placeholder="值越大越靠前">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="status" value="1" title="开启" checked>
|
||||
<input type="radio" name="status" value="0" title="禁用">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="layui-form-item" style="margin-top:10px;">
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn" onclick="save()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','form'],function(){
|
||||
var form = layui.form;
|
||||
layer = layui.layer;
|
||||
$ = layui.jquery;
|
||||
|
||||
form.on('select(type)', function(data){
|
||||
if(data.value == 1){
|
||||
$("#src1").show();
|
||||
$("#src2").hide();
|
||||
$("#src3").hide();
|
||||
}else if(data.value == 2){
|
||||
$("#src1").hide();
|
||||
$("#src2").show();
|
||||
$("#src3").hide();
|
||||
}else{
|
||||
$("#src1").show();
|
||||
$("#src2").hide();
|
||||
$("#src3").hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
function save(){
|
||||
$.post('<?php echo htmlentities((string) $config["admin_route"]); ?>yunzer/buttonadd',$('form').serialize(),function(res){
|
||||
if(res.code>0){
|
||||
layer.msg(res.msg,{'icon':2});
|
||||
}else{
|
||||
layer.msg(res.msg,{'icon':1});
|
||||
setTimeout(function(){parent.window.location.reload();},1000);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
</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>
|
||||
@@ -0,0 +1,343 @@
|
||||
<?php /*a:2:{s:56:"E:\Demo\PHP\yunzer\app\admin\view\yunzeradmin\banner.php";i:1747402501;s:51:"E:\Demo\PHP\yunzer\app\admin\view\public\header.php";i:1746890051;}*/ ?>
|
||||
<!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;">
|
||||
<!-- 主体内容 -->
|
||||
<div class="config-container">
|
||||
<!-- 页面头部样式 -->
|
||||
<div class="config-header" style="display: flex;flex-direction: column;flex-wrap: wrap;align-items: flex-start;">
|
||||
<div class="maintitle">
|
||||
<i class="layui-icon layui-icon-picture"></i>
|
||||
<span>Banner管理</span>
|
||||
</div>
|
||||
<div style="display: flex;align-items: flex-start;flex-direction: column;gap: 15px;margin-bottom: 10px;">
|
||||
<div>
|
||||
<button class="layui-btn layui-bg-blue" id="addBanner">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加Banner
|
||||
</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary layui-border-blue" onclick="refresh()">
|
||||
<i class="layui-icon layui-icon-refresh"></i>刷新
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-fluid">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
<table id="bannerTable" lay-filter="bannerTable"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Banner表单 -->
|
||||
<div id="bannerForm" style="display: none;">
|
||||
<form class="layui-form banner-form">
|
||||
<input type="hidden" name="id">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">标题</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="title" required lay-verify="required" placeholder="请输入标题"
|
||||
class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">图片</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-upload-drag" id="uploadImage">
|
||||
<i class="layui-icon layui-icon-upload"></i>
|
||||
<p>点击上传或拖拽图片至此处</p>
|
||||
<div id="uploadPreview" style="display: none;">
|
||||
<img src="" alt="Banner图片" class="banner-upload-preview">
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="image" id="imageInput">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">链接</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="url" placeholder="请输入链接地址" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="number" name="sort" value="0" class="layui-input" placeholder="数字越大越靠前">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="status" value="1" title="启用" checked>
|
||||
<input type="radio" name="status" value="0" title="禁用">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="saveBanner">保存</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
layui.use(['table', 'form', 'upload', 'layer'], function () {
|
||||
var table = layui.table,
|
||||
form = layui.form,
|
||||
upload = layui.upload,
|
||||
layer = layui.layer;
|
||||
|
||||
// 表格列配置
|
||||
var tableColumns = [[
|
||||
{ field: 'id', title: 'ID', width: 80, align: 'center' },
|
||||
{ field: 'title', title: '标题', align: 'center' },
|
||||
{
|
||||
field: 'image', title: '图片', width: 180, align: 'center', templet: function (d) {
|
||||
return '<img src="' + d.image + '" class="banner-preview-img" onclick="previewImage(\'' + d.image + '\')">';
|
||||
}
|
||||
},
|
||||
{ field: 'url', title: '链接', align: 'center', width: 300 },
|
||||
{ field: 'sort', title: '排序', align: 'center', width: 100, sort: true },
|
||||
{ field: 'create_time', title: '创建时间', align: 'center', width: 180, sort: true },
|
||||
{
|
||||
title: '操作', align: 'center', width: 240, templet: function (d) {
|
||||
return '<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>' +
|
||||
'<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>';
|
||||
}
|
||||
}
|
||||
]];
|
||||
|
||||
// 初始化表格
|
||||
table.render({
|
||||
elem: '#bannerTable',
|
||||
url: '/admin/yunzeradmin/bannerlist',
|
||||
method: 'get',
|
||||
page: true,
|
||||
cols: tableColumns,
|
||||
limit: 10,
|
||||
limits: [10, 20, 30, 50],
|
||||
text: { none: '暂无相关数据' }
|
||||
});
|
||||
|
||||
// 上传组件配置
|
||||
var uploadConfig = {
|
||||
elem: '#uploadImage',
|
||||
url: '/admin/upload/image',
|
||||
accept: 'images',
|
||||
acceptMime: 'image/*',
|
||||
done: function (res) {
|
||||
if (res.code === 0) {
|
||||
$('#uploadPreview').show().find('img').attr('src', res.data.url);
|
||||
$('#imageInput').val(res.data.url);
|
||||
layer.msg('上传成功');
|
||||
} else {
|
||||
layer.msg('上传失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化上传组件
|
||||
upload.render(uploadConfig);
|
||||
|
||||
// 监听表格工具条事件
|
||||
table.on('tool(bannerTable)', function (obj) {
|
||||
var data = obj.data;
|
||||
if (obj.event === 'edit') {
|
||||
showBannerForm(data);
|
||||
} else if (obj.event === 'del') {
|
||||
layer.confirm('确定删除此Banner?', function (index) {
|
||||
deleteBanner(data.id, obj);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 添加Banner按钮点击事件
|
||||
$('#addBanner').on('click', function () {
|
||||
showBannerForm();
|
||||
});
|
||||
|
||||
// 监听表单提交
|
||||
form.on('submit(saveBanner)', function (data) {
|
||||
var url = data.field.id ? '/admin/yunzeradmin/banneredit' : '/admin/yunzeradmin/banneradd';
|
||||
$.post(url, data.field, function (res) {
|
||||
if (res.code === 0) {
|
||||
layer.closeAll('page');
|
||||
table.reload('bannerTable');
|
||||
layer.msg('保存成功');
|
||||
} else {
|
||||
layer.msg(res.msg);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// 显示Banner表单
|
||||
function showBannerForm(data) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: data ? '编辑Banner' : '添加Banner',
|
||||
content: $('#bannerForm'),
|
||||
area: ['800px', '600px'],
|
||||
success: function (layero) {
|
||||
form.render();
|
||||
if (data) {
|
||||
form.val('bannerForm', data);
|
||||
if (data.image) {
|
||||
$('#uploadPreview').show().find('img').attr('src', data.image);
|
||||
$('#imageInput').val(data.image);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 删除Banner
|
||||
function deleteBanner(id, obj) {
|
||||
$.post('/admin/yunzeradmin/bannerdel', { id: id }, function (res) {
|
||||
if (res.code === 0) {
|
||||
obj.del();
|
||||
layer.msg('删除成功');
|
||||
} else {
|
||||
layer.msg(res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 预览图片
|
||||
function previewImage(url) {
|
||||
layer.photos({
|
||||
photos: {
|
||||
"data": [{
|
||||
"src": url
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<!-- 页面样式 -->
|
||||
<style>
|
||||
.layui-table-cell {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.layui-table-cell img {
|
||||
height: 36px;
|
||||
width: auto;
|
||||
max-width: 80px;
|
||||
}
|
||||
|
||||
.banner-preview-img {
|
||||
max-width: 80px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.banner-form {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.banner-upload-preview {
|
||||
max-width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php /*a:5:{s:52:"E:\Demo\PHP\yunzer\app\index\view\program\detail.php";i:1747417030;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\head.php";i:1746890051;s:61:"E:\Demo\PHP\yunzer\app\index\view\component\header-simple.php";i:1747415782;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\footer.php";i:1747402501;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\foot.php";i:1746808046;}*/ ?>
|
||||
<?php /*a:5:{s:52:"E:\Demo\PHP\yunzer\app\index\view\program\detail.php";i:1747417109;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\head.php";i:1746890051;s:61:"E:\Demo\PHP\yunzer\app\index\view\component\header-simple.php";i:1747415782;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\footer.php";i:1747402501;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\foot.php";i:1746808046;}*/ ?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
|
||||
Reference in new issue
Block a user