做文章中心

This commit is contained in:
云泽网 2025-05-28 00:41:02 +08:00
parent 4838f1f589
commit 205343674a
14 changed files with 2895 additions and 209 deletions

View File

@ -12,6 +12,120 @@ use app\index\model\Articles\ArticlesCategory;
class ArticlesController extends BaseController
{
//文章中心
public function index()
{
// 获取前端传来的分类ID
$cateid = input('cateid/d', 0); // 使用input助手函数获取参数并转换为整数
$page = input('page/d', 1);
$limit = input('limit/d', 10);
// 获取所有顶级分类
$categories = ArticlesCategory::where('cid', 0)
->where('delete_time', null)
->where('status', 1)
->select()
->toArray();
// 获取顶级分类信息
$category = null;
if ($cateid > 0) {
$category = ArticlesCategory::where('id', $cateid)
->where('delete_time', null)
->where('status', 1)
->find();
}
// 获取所有子分类
$subCategories = [];
if ($cateid > 0) {
$subCategories = ArticlesCategory::where('cid', $cateid)
->where('delete_time', null)
->where('status', 1)
->select()
->toArray();
}
// 获取所有子分类ID
$subCategoryIds = array_column($subCategories, 'id');
if ($cateid > 0) {
$subCategoryIds[] = $cateid;
}
// 构建文章查询条件
$where = [
['delete_time', '=', null],
['status', '=', 2]
];
if (!empty($subCategoryIds)) {
$where[] = ['cate', 'in', $subCategoryIds];
}
// 查询文章
$articles = Articles::where($where)
->order('id DESC')
->page($page, $limit)
->select()
->toArray();
// 按子分类分组文章
$groupedArticles = [];
foreach ($subCategories as $subCategory) {
$groupedArticles[$subCategory['id']] = [
'id' => $subCategory['id'],
'name' => $subCategory['name'],
'desc' => $subCategory['desc'],
'image' => $subCategory['image'],
'list' => []
];
}
// 将文章分配到对应的子分类
foreach ($articles as $article) {
if (isset($groupedArticles[$article['cate']])) {
// 如果文章图片为空,使用分类图片
if (empty($article['image'])) {
$article['image'] = $groupedArticles[$article['cate']]['image'];
}
$groupedArticles[$article['cate']]['list'][] = $article;
}
}
// 获取总数
$total = Articles::where($where)->count();
// 准备返回数据
$data = [
'cate' => [
'id' => $cateid,
'name' => $category ? $category['name'] : '',
'desc' => $category ? $category['desc'] : '',
'image' => $category ? $category['image'] : '',
'subCategories' => array_values($groupedArticles),
'total' => $total,
'page' => $page,
'limit' => $limit
]
];
// 根据请求方式返回不同的输出
if (request()->isPost()) {
return json([
'code' => 1,
'msg' => '获取成功',
'data' => $data
]);
} else {
// 为视图准备数据
$viewData = [
'categories' => $categories,
'cate' => $data['cate']
];
return view('index', $viewData);
}
}
// 文章列表页
public function list()
{
@ -20,17 +134,23 @@ class ArticlesController extends BaseController
// 构建查询条件
$where = [
['delete_time', '=', null],
['status', '=', 1]
['a.delete_time', '=', null],
['a.status', '=', 2]
];
if ($cateId > 0) {
$where[] = ['cate', '=', $cateId];
$where[] = ['a.cate', '=', $cateId];
}
// 获取文章列表
$articles = Articles::where($where)
->order('id DESC')
$articles = Articles::alias('a')
->join('articles_category c', 'a.cate = c.id')
->where($where)
->field([
'a.*',
'IF(a.image IS NULL OR a.image = "", c.image, a.image) as image'
])
->order('a.id DESC')
->paginate([
'list_rows' => 10,
'query' => Request::instance()->param()
@ -51,14 +171,29 @@ class ArticlesController extends BaseController
->select()
->toArray();
// 将变量传递给视图
View::assign([
'articles' => $articles,
'category' => $category,
'categories' => $categories
]);
return view('list');
// 根据请求方式返回不同的输出
if (request()->isPost()) {
return json([
'code' => 1,
'msg' => '获取成功',
'data' => [
'articles' => $articles->items(),
'category' => $category,
'categories' => $categories,
'total' => $articles->total(),
'current_page' => $articles->currentPage(),
'per_page' => $articles->listRows()
]
]);
} else {
// 将变量传递给视图
View::assign([
'articles' => $articles,
'category' => $category,
'categories' => $categories
]);
return view('list');
}
}
// 文章详情页
@ -66,7 +201,7 @@ class ArticlesController extends BaseController
{
$id = Request::param('id/d', 0);
$article = Articles::where('id', $id)->find();
if (!$article) {
return json(['code' => 0, 'msg' => '文章不存在或已被删除']);
}
@ -74,20 +209,20 @@ class ArticlesController extends BaseController
// 获取分类名称
$cateName = ArticlesCategory::where('id', $article['cate'])
->value('name');
// 获取上一篇和下一篇文章
$prevArticle = Articles::where('id', '<', $id)
->where('delete_time', null)
->where('status', '<>', 3)
->order('id DESC')
->find();
$nextArticle = Articles::where('id', '>', $id)
->where('delete_time', null)
->where('status', '<>', 3)
->order('id ASC')
->find();
// 获取相关文章(同分类的其他文章)
$relatedArticles = Articles::alias('a')
->join('articles_category c', 'a.cate = c.id')
@ -120,7 +255,7 @@ class ArticlesController extends BaseController
]
]);
}
// 非 AJAX 请求返回视图
View::assign([
'article' => $article,
@ -162,7 +297,7 @@ class ArticlesController extends BaseController
// 返回更新后的点赞数
$newLikes = $article['likes'] + 1;
return json([
'code' => 1,
'code' => 1,
'msg' => '点赞成功',
'data' => [
'likes' => $newLikes
@ -236,12 +371,12 @@ class ArticlesController extends BaseController
public function viewStats()
{
$id = Request::param('id/d', 0);
// 获取总访问量
$totalViews = Articles::where('id', $id)
->value('views');
return json([
'code' => 1,
'data' => [
@ -273,10 +408,10 @@ class ArticlesController extends BaseController
// 更新访问次数
Articles::where('id', $id)->inc('views')->update();
// 获取更新后的访问次数
$newViews = Articles::where('id', $id)->value('views');
return json(['code' => 1, 'msg' => '更新成功', 'data' => ['views' => $newViews]]);
} catch (\Exception $e) {
return json(['code' => 0, 'msg' => '更新失败:' . $e->getMessage()]);

View File

@ -7,12 +7,120 @@ use app\index\controller\BaseController;
use think\facade\Db;
use think\facade\View;
use think\facade\Request;
use app\index\model\Resources\Resources;
use app\index\model\Resources\Resources;
use app\index\model\Resources\ResourcesCategory;
use app\index\model\Attachments;
class GameController extends BaseController
{
//资源中心
public function index()
{
// 获取前端传来的分类ID
$cateid = input('cateid/d', 0);
$page = input('page/d', 1);
$limit = input('limit/d', 10);
// 获取所有顶级分类
$categories = ResourcesCategory::where('cid', 0)
->where('delete_time', null)
->where('status', 1)
->select()
->toArray();
// 获取顶级分类信息
$category = null;
if ($cateid > 0) {
$category = ResourcesCategory::where('id', $cateid)
->where('delete_time', null)
->where('status', 1)
->find();
}
// 获取所有子分类
$subCategories = [];
if ($cateid > 0) {
$subCategories = ResourcesCategory::where('cid', $cateid)
->where('delete_time', null)
->where('status', 1)
->select()
->toArray();
}
// 获取所有子分类ID
$subCategoryIds = array_column($subCategories, 'id');
if ($cateid > 0) {
$subCategoryIds[] = $cateid;
}
// 构建游戏查询条件
$where = [
['delete_time', '=', null],
['status', '=', 1]
];
if (!empty($subCategoryIds)) {
$where[] = ['cate', 'in', $subCategoryIds];
}
// 查询游戏
$games = Resources::where($where)
->order('id DESC')
->page($page, $limit)
->select()
->toArray();
// 按子分类分组游戏
$groupedGames = [];
foreach ($subCategories as $subCategory) {
$groupedGames[$subCategory['id']] = [
'id' => $subCategory['id'],
'name' => $subCategory['name'],
'list' => []
];
}
// 将游戏分配到对应的子分类
foreach ($games as $game) {
if (isset($groupedGames[$game['cate']])) {
$groupedGames[$game['cate']]['list'][] = $game;
}
}
// 获取总数
$total = Resources::where($where)->count();
// 准备返回数据
$data = [
'cate' => [
'id' => $cateid,
'name' => $category ? $category['name'] : '',
'desc' => $category ? $category['desc'] : '',
'image' => $category ? $category['image'] : '',
'subCategories' => array_values($groupedGames),
'total' => $total,
'page' => $page,
'limit' => $limit
]
];
// 根据请求方式返回不同的输出
if (request()->isPost()) {
return json([
'code' => 1,
'msg' => '获取成功',
'data' => $data
]);
} else {
// 为视图准备数据
$viewData = [
'categories' => $categories,
'cate' => $data['cate']
];
return view('index', $viewData);
}
}
// 游戏列表页
public function list()
{
@ -21,20 +129,26 @@ class GameController extends BaseController
// 构建查询条件
$where = [
['delete_time', '=', null],
['status', '=', 1]
['a.delete_time', '=', null],
['a.status', '=', 1]
];
if ($cateId > 0) {
$where[] = ['cate', '=', $cateId];
$where[] = ['a.cate', '=', $cateId];
}
// 获取游戏列表
$games = Resources::where($where)
->order('id DESC')
$games = Resources::alias('a')
->join('resources_category c', 'a.cate = c.id')
->where($where)
->field([
'a.*',
'IF(a.icon IS NULL OR a.icon = "", c.icon, a.icon) as icon'
])
->order('a.id DESC')
->paginate([
'list_rows' => 10,
'query' => Request::param()
'query' => Request::instance()->param()
]);
// 获取分类信息
@ -52,7 +166,22 @@ class GameController extends BaseController
->select()
->toArray();
// 将变量传递给视图
// 如果是POST请求返回JSON数据
if (Request::isPost()) {
return json([
'code' => 1,
'msg' => '获取成功',
'data' => [
'games' => $games->items(),
'total' => $games->total(),
'current_page' => $games->currentPage(),
'per_page' => $games->listRows(),
'category' => $category
]
]);
}
// GET请求返回渲染的视图
View::assign([
'games' => $games,
'category' => $category,
@ -67,16 +196,16 @@ class GameController extends BaseController
{
$id = Request::param('id/d', 0);
$game = Resources::where('id', $id)->find();
if (!$game) {
return json(['code' => 0, 'msg' => '游戏不存在或已被删除']);
}
// 如果size没有从附件表中获取
if (empty($game['size']) && !empty($game['fileurl'])) {
$attachment = Attachments::where('src', $game['fileurl'])
->find();
if ($attachment && !empty($attachment['size'])) {
$size = $attachment['size'];
// 转换文件大小为合适的单位
@ -93,20 +222,20 @@ class GameController extends BaseController
// 获取分类名称
$cateName = ResourcesCategory::where('id', $game['cate'])
->value('name');
// 获取上一个和下一个游戏
$prevGame = Resources::where('id', '<', $id)
->where('delete_time', null)
->where('status', 1)
->order('id DESC')
->find();
$nextGame = Resources::where('id', '>', $id)
->where('delete_time', null)
->where('status', 1)
->order('id ASC')
->find();
// 获取相关游戏(同分类的其他游戏)
$relatedGames = Db::table('yz_resources')
->alias('g')
@ -140,7 +269,7 @@ class GameController extends BaseController
]
]);
}
// 非 AJAX 请求返回视图
View::assign([
'game' => $game,
@ -179,7 +308,7 @@ class GameController extends BaseController
if ($result) {
return json([
'code' => 1,
'code' => 1,
'msg' => '下载成功',
'data' => [
'url' => $game['url']
@ -194,11 +323,11 @@ class GameController extends BaseController
public function viewStats()
{
$id = Request::param('id/d', 0);
// 获取总访问量
$totalViews = Resources::where('id', $id)
->value('views');
return json([
'code' => 1,
'data' => [
@ -230,10 +359,10 @@ class GameController extends BaseController
// 更新访问次数
Resources::where('id', $id)->inc('views')->update();
// 获取更新后的访问次数
$newViews = Resources::where('id', $id)->value('views');
return json(['code' => 1, 'msg' => '更新成功', 'data' => ['views' => $newViews]]);
} catch (\Exception $e) {
return json(['code' => 0, 'msg' => '更新失败:' . $e->getMessage()]);

View File

@ -14,6 +14,114 @@ use app\index\model\Attachments;
class ProgramController extends BaseController
{
//资源中心
public function index()
{
// 获取前端传来的分类ID
$cateid = input('cateid/d', 0);
$page = input('page/d', 1);
$limit = input('limit/d', 10);
// 获取所有顶级分类
$categories = ResourcesCategory::where('cid', 0)
->where('delete_time', null)
->where('status', 1)
->select()
->toArray();
// 获取顶级分类信息
$category = null;
if ($cateid > 0) {
$category = ResourcesCategory::where('id', $cateid)
->where('delete_time', null)
->where('status', 1)
->find();
}
// 获取所有子分类
$subCategories = [];
if ($cateid > 0) {
$subCategories = ResourcesCategory::where('cid', $cateid)
->where('delete_time', null)
->where('status', 1)
->select()
->toArray();
}
// 获取所有子分类ID
$subCategoryIds = array_column($subCategories, 'id');
if ($cateid > 0) {
$subCategoryIds[] = $cateid;
}
// 构建资源查询条件
$where = [
['delete_time', '=', null],
['status', '=', 1]
];
if (!empty($subCategoryIds)) {
$where[] = ['cate', 'in', $subCategoryIds];
}
// 查询资源
$programs = Resources::where($where)
->order('id DESC')
->page($page, $limit)
->select()
->toArray();
// 按子分类分组资源
$groupedPrograms = [];
foreach ($subCategories as $subCategory) {
$groupedPrograms[$subCategory['id']] = [
'id' => $subCategory['id'],
'name' => $subCategory['name'],
'list' => []
];
}
// 将资源分配到对应的子分类
foreach ($programs as $program) {
if (isset($groupedPrograms[$program['cate']])) {
$groupedPrograms[$program['cate']]['list'][] = $program;
}
}
// 获取总数
$total = Resources::where($where)->count();
// 准备返回数据
$data = [
'cate' => [
'id' => $cateid,
'name' => $category ? $category['name'] : '',
'desc' => $category ? $category['desc'] : '',
'image' => $category ? $category['image'] : '',
'subCategories' => array_values($groupedPrograms),
'total' => $total,
'page' => $page,
'limit' => $limit
]
];
// 根据请求方式返回不同的输出
if (request()->isPost()) {
return json([
'code' => 1,
'msg' => '获取成功',
'data' => $data
]);
} else {
// 为视图准备数据
$viewData = [
'categories' => $categories,
'cate' => $data['cate']
];
return view('index', $viewData);
}
}
// 程序列表页
public function list()
{
@ -22,20 +130,26 @@ class ProgramController extends BaseController
// 构建查询条件
$where = [
['delete_time', '=', null],
['status', '=', 1]
['a.delete_time', '=', null],
['a.status', '=', 1]
];
if ($cateId > 0) {
$where[] = ['cate', '=', $cateId];
$where[] = ['a.cate', '=', $cateId];
}
// 获取程序列表
$programs = Resources::where($where)
->order('id DESC')
$programs = Resources::alias('a')
->join('resources_category c', 'a.cate = c.id')
->where($where)
->field([
'a.*',
'IF(a.icon IS NULL OR a.icon = "", c.icon, a.icon) as icon'
])
->order('a.id DESC')
->paginate([
'list_rows' => 10,
'query' => Request::param()
'query' => Request::instance()->param()
]);
// 获取分类信息
@ -53,7 +167,22 @@ class ProgramController extends BaseController
->select()
->toArray();
// 将变量传递给视图
// 如果是POST请求返回JSON数据
if (Request::isPost()) {
return json([
'code' => 1,
'msg' => '获取成功',
'data' => [
'programs' => $programs->items(),
'total' => $programs->total(),
'current_page' => $programs->currentPage(),
'per_page' => $programs->listRows(),
'category' => $category
]
]);
}
// GET请求返回渲染的视图
View::assign([
'programs' => $programs,
'category' => $category,

View File

@ -315,6 +315,7 @@ class UserController extends BaseController
return $this->fetch();
}
//个人资料
public function saveBasic()
{
// 检查用户是否登录
@ -582,6 +583,64 @@ class UserController extends BaseController
}
}
/**
* 获取系统通知列表
*/
public function getMessages()
{
// 检查用户是否登录
if (!cookie('user_account')) {
return json(['code' => 1, 'msg' => '请先登录']);
}
$type = $this->request->get('type', 'all'); // 获取通知类型all, unread, read
$userId = cookie('user_id');
try {
// 构建查询条件
$where = [
['status', '=', 1] // 只获取启用的通知
];
// 查询系统通知
$notices = UserMessage::where($where)
->order('is_top', 'desc') // 置顶的排在前面
->order('create_time', 'desc')
->select();
// 格式化数据
$data = [];
foreach ($notices as $notice) {
// 检查用户是否已读该通知
$isRead = UserMessage::where([
['user_id', '=', $userId],
['notice_id', '=', $notice->id],
['is_read', '=', 1]
])->find();
// 根据type过滤
if ($type == 'unread' && $isRead)
continue;
if ($type == 'read' && !$isRead)
continue;
$data[] = [
'id' => $notice->id,
'title' => $notice->title,
'content' => $notice->content,
'type' => $notice->type,
'is_top' => $notice->is_top,
'is_read' => $isRead ? 1 : 0,
'create_time' => date('Y-m-d H:i:s', $notice->create_time)
];
}
return json(['code' => 0, 'msg' => '获取成功', 'data' => $data]);
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '获取失败:' . $e->getMessage()]);
}
}
//修改密码
public function updatePassword()
{

View File

@ -0,0 +1,539 @@
{include file="component/head" /}
{include file="component/header-simple" /}
<!-- 简约现代文章中心 -->
<div class="modern-articles-page">
<!-- 简约标题区 -->
<div class="modern-header">
<div class="container">
<h1 class="modern-title">文章中心</h1>
<p class="modern-subtitle">探索知识与洞见</p>
</div>
</div>
<!-- 主要内容区 -->
<div class="container">
<div class="modern-layout">
<!-- 侧边分类导航 -->
<aside class="modern-sidebar">
<div class="sidebar-card">
<h3 class="sidebar-title">
<i class="layui-icon layui-icon-list"></i>
<span>分类导航</span>
</h3>
<ul class="category-menu">
{volist name="cate.subCategories" id="subCategory"}
<li class="menu-item {$cate.id == $subCategory.id ? 'active' : ''}" data-cateid="{$subCategory.id}">
<span>{$subCategory.name}</span>
<i class="layui-icon layui-icon-right"></i>
</li>
{/volist}
</ul>
</div>
</aside>
<!-- 文章内容区 -->
<main class="modern-main">
<!-- 文章列表 -->
<div class="article-grid" id="articleList">
{volist name="cate.subCategories" id="subCategory"}
{if $cate.id == $subCategory.id}
{if !empty($subCategory.list)}
{volist name="subCategory.list" id="article"}
<article class="article-card">
<div class="card-image">
<img src="{$article.image}" alt="{$article.title}">
<div class="image-overlay"></div>
</div>
<div class="card-content">
<div class="meta-info">
<span class="category-tag">${article.category_name || '未分类'}</span>
<time class="publish-date">${article.create_time || ''}</time>
</div>
<h3 class="article-title">${article.title}</h3>
<div class="card-footer">
<div class="stats">
<span class="views"><i class="layui-icon layui-icon-eye"></i> ${article.views || 0}</span>
<span class="likes"><i class="layui-icon layui-icon-praise"></i> ${article.likes || 0}</span>
</div>
<a href="/index/articles/detail?id=${article.id}" class="read-more">阅读更多</a>
</div>
</div>
</article>
{/volist}
{else}
<div class="empty-state">
<div class="empty-icon">
<i class="layui-icon layui-icon-template-1"></i>
</div>
<h4>暂无文章</h4>
<p>当前分类下没有找到相关文章</p>
</div>
{/if}
{/if}
{/volist}
</div>
<!-- 分页 -->
<div class="modern-pagination" id="pagination"></div>
</main>
</div>
</div>
</div>
<script>
layui.use(['laypage', 'jquery'], function(){
var laypage = layui.laypage;
var $ = layui.jquery;
// 分类切换
$('.menu-item').on('click', function() {
var cateid = $(this).data('cateid');
var $menuItems = $('.menu-item');
// 更新选中状态
$menuItems.removeClass('active');
$(this).addClass('active');
// 加载文章
loadArticles(cateid, 1);
});
// 页面加载完成后,自动触发第一个分类的点击事件
$(document).ready(function() {
var $firstMenuItem = $('.menu-item').first();
if ($firstMenuItem.length > 0) {
$firstMenuItem.click();
}
});
// 加载文章函数
function loadArticles(cateid, page) {
$.ajax({
url: '/index/articles/list',
type: 'POST',
data: {
cate: cateid,
page: page
},
beforeSend: function() {
$('#articleList').html('<div class="loading-state"><i class="layui-icon layui-icon-loading"></i>加载中...</div>');
},
success: function(res) {
if(res.code === 1) {
var html = '';
if(res.data.articles && res.data.articles.length > 0) {
res.data.articles.forEach(function(article) {
html += `<article class="article-card">
<div class="card-image">
<img src="${article.image}" alt="${article.title}">
<div class="image-overlay"></div>
</div>
<div class="card-content">
<div class="meta-info">
<span class="category-tag">${article.category_name || '未分类'}</span>
<time class="publish-date">${article.create_time || ''}</time>
</div>
<h3 class="article-title">${article.title}</h3>
<div class="card-footer">
<div class="stats">
<span class="views"><i class="layui-icon layui-icon-eye"></i> ${article.views || 0}</span>
<span class="likes"><i class="layui-icon layui-icon-praise"></i> ${article.likes || 0}</span>
</div>
<a href="/index/articles/detail?id=${article.id}" class="read-more">阅读更多</a>
</div>
</div>
</article>`;
});
} else {
html = `<div class="empty-state">
<div class="empty-icon">
<i class="layui-icon layui-icon-template-1"></i>
</div>
<h4>暂无文章</h4>
<p>当前分类下没有找到相关文章</p>
</div>`;
}
$('#articleList').html(html);
// 渲染分页
laypage.render({
elem: 'pagination',
count: res.data.total || 0,
limit: res.data.per_page || 12,
curr: res.data.current_page || 1,
theme: '#1E9FFF',
layout: ['prev', 'page', 'next'],
jump: function(obj, first) {
if(!first) {
loadArticles(cateid, obj.curr);
}
}
});
}
}
});
}
});
</script>
{include file="component/footer" /}
<style>
/* 基础样式重置 */
.modern-articles-page {
font-family: 'Helvetica Neue', Arial, 'PingFang SC', 'Microsoft YaHei', sans-serif;
color: #333;
line-height: 1.6;
background-color: #f9fafc;
padding-bottom: 60px;
}
/* 标题区样式 */
.modern-header {
background: linear-gradient(135deg, #1E9FFF 0%, #0d8aff 100%);
color: white;
padding: 80px 0 60px;
text-align: center;
margin-bottom: 40px;
}
.modern-title {
font-size: 2.5rem;
font-weight: 300;
margin-bottom: 15px;
letter-spacing: 1px;
}
.modern-subtitle {
font-size: 1.1rem;
font-weight: 300;
opacity: 0.9;
margin: 0;
}
/* 布局结构 */
.modern-layout {
display: grid;
grid-template-columns: 260px 1fr;
gap: 30px;
}
/* 侧边栏样式 */
.modern-sidebar {
position: sticky;
top: 30px;
align-self: start;
}
.sidebar-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.03);
overflow: hidden;
}
.sidebar-title {
font-size: 1.1rem;
font-weight: 500;
padding: 20px;
margin: 0;
display: flex;
align-items: center;
color: #555;
border-bottom: 1px solid #f0f0f0;
}
.sidebar-title i {
margin-right: 10px;
font-size: 1.2rem;
color: #1E9FFF;
}
.category-menu {
list-style: none;
padding: 0;
margin: 0;
}
.menu-item {
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
transition: all 0.2s ease;
border-left: 3px solid transparent;
}
.menu-item:hover {
background-color: #f8fafd;
color: #1E9FFF;
}
.menu-item.active {
background-color: #f0f7ff;
border-left-color: #1E9FFF;
color: #1E9FFF;
font-weight: 500;
}
.menu-item i {
font-size: 0.9rem;
color: #aaa;
}
.menu-item.active i,
.menu-item:hover i {
color: #1E9FFF;
}
/* 主内容区样式 */
.modern-main {
background: transparent;
}
/* 文章网格布局 */
.article-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 25px;
margin-bottom: 40px;
}
/* 文章卡片样式 */
.article-card {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.03);
transition: all 0.3s ease;
display: flex;
flex-direction: column;
}
.article-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.08);
}
.card-image {
height: 180px;
position: relative;
overflow: hidden;
}
.card-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.3), transparent);
}
.article-card:hover .card-image img {
transform: scale(1.05);
}
.card-content {
padding: 20px;
flex: 1;
display: flex;
flex-direction: column;
}
.meta-info {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
font-size: 0.85rem;
color: #666;
}
.category-tag {
background: #f0f7ff;
color: #1E9FFF;
padding: 3px 10px;
border-radius: 4px;
font-size: 0.75rem;
}
.article-title {
font-size: 1rem;
font-weight: 500;
margin: 0 0 10px;
color: #333;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.article-excerpt {
font-size: 0.9rem;
color: #666;
margin: 0 0 20px;
flex: 1;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto;
}
.stats {
font-size: 0.85rem;
color: #999;
display: flex;
gap: 15px;
}
.stats i {
margin-right: 3px;
}
.read-more {
color: #1E9FFF;
font-size: 0.9rem;
text-decoration: none;
font-weight: 500;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
}
.read-more:hover {
color: #0d8aff;
text-decoration: underline;
}
/* 分页样式 */
.modern-pagination {
text-align: center;
margin-top: 40px;
}
.layui-laypage a,
.layui-laypage span {
border-radius: 4px !important;
margin: 0 3px !important;
}
.layui-laypage a {
color: #666 !important;
}
.layui-laypage .layui-laypage-curr .layui-laypage-em {
background-color: #1E9FFF !important;
}
/* 空状态样式 */
.empty-state {
grid-column: 1 / -1;
text-align: center;
padding: 60px 20px;
background: white;
border-radius: 8px;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.03);
}
.empty-icon {
font-size: 3rem;
color: #ddd;
margin-bottom: 20px;
}
.empty-icon i {
font-size: inherit;
}
.empty-state h4 {
font-size: 1.2rem;
font-weight: 400;
color: #666;
margin: 0 0 10px;
}
.empty-state p {
color: #999;
font-size: 0.95rem;
margin: 0;
}
/* 加载状态 */
.loading-state {
grid-column: 1 / -1;
text-align: center;
padding: 40px;
color: #666;
}
.loading-state i {
font-size: 1.5rem;
margin-right: 10px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 响应式设计 */
@media (max-width: 992px) {
.modern-layout {
grid-template-columns: 1fr;
}
.modern-sidebar {
position: static;
margin-bottom: 30px;
}
.article-grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
}
@media (max-width: 768px) {
.modern-header {
padding: 60px 0 40px;
}
.modern-title {
font-size: 2rem;
}
}
@media (max-width: 576px) {
.article-grid {
grid-template-columns: 1fr;
}
.modern-title {
font-size: 1.8rem;
}
.modern-subtitle {
font-size: 1rem;
}
}
</style>
{include file="component/foot" /}

View File

@ -0,0 +1,76 @@
<div class="container py-5">
<div class="row g-4">
<!-- 左侧分类列表 -->
<div class="col-lg-3">
<div class="category-sidebar">
<div class="sidebar-header">
<i class="layui-icon layui-icon-app"></i>
<span>文章分类</span>
</div>
<div class="category-list">
{volist name="categories" id="cate"}
<div class="category-item {$category.id == $cate.id ? 'active' : ''}" data-cateid="{$cate.id}">{$cate.name}</div>
{/volist}
</div>
</div>
</div>
<!-- 右侧文章列表 -->
<div class="col-lg-9">
{if $category}
<div class="category-header mb-4">
<h2 class="category-title">{$category.name}</h2>
<p class="category-desc">{$category.desc|default=''}</p>
</div>
{/if}
<div class="article-list">
{volist name="articles" id="article"}
<div class="article-item">
<div class="row g-0">
<div class="col-md-4">
<div class="article-image">
<img src="{$article.image|default='/static/images/default.jpg'}" alt="{$article.title}">
</div>
</div>
<div class="col-md-8">
<div class="article-content">
<h3 class="article-title">
<a href="/index/articles/detail?id={$article.id}">{$article.title}</a>
</h3>
<p class="article-desc">{$article.desc|default=''}</p>
<div class="article-meta">
<div class="article-stats">
<span><i class="layui-icon layui-icon-eye"></i> {$article.views|default=0}</span>
<span><i class="layui-icon layui-icon-praise"></i> {$article.likes|default=0}</span>
<span><i class="layui-icon layui-icon-date"></i> {$article.create_time|date="Y-m-d"}</span>
</div>
<a href="/index/articles/detail?id={$article.id}" class="btn-detail">查看详情</a>
</div>
</div>
</div>
</div>
</div>
{/volist}
</div>
<!-- 分页 -->
<div class="mt-5">
{$articles|raw}
</div>
</div>
</div>
</div>
<script>
layui.use(['layer'], function () {
var layer = layui.layer;
var $ = layui.$;
// 分类切换
$('.category-item').on('click', function() {
var cateid = $(this).data('cateid');
window.location.href = '/index/articles/list?cate=' + cateid;
});
});
</script>

View File

@ -14,7 +14,7 @@
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/articles/index?cateid=1', '_blank')">更多</div>
</div>
<div class="product-list" id="webArticlesList">
<!-- 文章将通过JavaScript动态加载 -->
@ -35,7 +35,7 @@
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/articles/index?cateid=3', '_blank')">更多</div>
</div>
<div class="product-list" id="techArticlesList">
<!-- 文章将通过JavaScript动态加载 -->
@ -56,7 +56,7 @@
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/program/index?cateid=2', '_blank')">更多</div>
</div>
<div class="product-list" id="resourcesDownloadList">
<!-- 文章将通过JavaScript动态加载 -->
@ -77,7 +77,7 @@
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/program/index?cateid=1', '_blank')">更多</div>
</div>
<div class="product-list" id="programDownloadList">
<!-- 程序将通过JavaScript动态加载 -->
@ -98,7 +98,7 @@
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/game/index?cateid=8', '_blank')">更多</div>
</div>
<div class="product-list" id="gameDownloadList">
<!-- 游戏将通过JavaScript动态加载 -->

View File

@ -0,0 +1,539 @@
{include file="component/head" /}
{include file="component/header-simple" /}
<!-- 简约现代文章中心 -->
<div class="modern-games-page">
<!-- 简约标题区 -->
<div class="modern-header">
<div class="container">
<h1 class="modern-title">游戏中心</h1>
<p class="modern-subtitle">探索知识与洞见</p>
</div>
</div>
<!-- 主要内容区 -->
<div class="container">
<div class="modern-layout">
<!-- 侧边分类导航 -->
<aside class="modern-sidebar">
<div class="sidebar-card">
<h3 class="sidebar-title">
<i class="layui-icon layui-icon-list"></i>
<span>分类导航</span>
</h3>
<ul class="category-menu">
{volist name="cate.subCategories" id="subCategory"}
<li class="menu-item {$cate.id == $subCategory.id ? 'active' : ''}" data-cateid="{$subCategory.id}">
<span>{$subCategory.name}</span>
<i class="layui-icon layui-icon-right"></i>
</li>
{/volist}
</ul>
</div>
</aside>
<!-- 文章内容区 -->
<main class="modern-main">
<!-- 文章列表 -->
<div class="game-grid" id="gameList">
{volist name="cate.subCategories" id="subCategory"}
{if $cate.id == $subCategory.id}
{if !empty($subCategory.list)}
{volist name="subCategory.list" id="game"}
<game class="game-card">
<div class="card-image">
<img src="{$game.icon|default=$subCategory.icon|default='/static/images/default-game.jpg'}" alt="{$game.title}">
<div class="image-overlay"></div>
</div>
<div class="card-content">
<div class="meta-info">
<span class="category-tag">{$subCategory.name}</span>
<time class="publish-date">{$game.create_time|date="Y-m-d"}</time>
</div>
<h3 class="game-title">{$game.title}</h3>
<div class="card-footer">
<div class="stats">
<span class="views"><i class="layui-icon layui-icon-eye"></i> {$game.views|default=0}</span>
<span class="likes"><i class="layui-icon layui-icon-praise"></i> {$game.likes|default=0}</span>
</div>
<a href="/index/game/detail?id={$game.id}" class="read-more">阅读更多</a>
</div>
</div>
</game>
{/volist}
{else}
<div class="empty-state">
<div class="empty-icon">
<i class="layui-icon layui-icon-template-1"></i>
</div>
<h4>暂无文章</h4>
<p>当前分类下没有找到相关文章</p>
</div>
{/if}
{/if}
{/volist}
</div>
<!-- 分页 -->
<div class="modern-pagination" id="pagination"></div>
</main>
</div>
</div>
</div>
<script>
layui.use(['laypage', 'jquery'], function(){
var laypage = layui.laypage;
var $ = layui.jquery;
// 分类切换
$('.menu-item').on('click', function() {
var cateid = $(this).data('cateid');
var $menuItems = $('.menu-item');
// 更新选中状态
$menuItems.removeClass('active');
$(this).addClass('active');
// 加载文章
loadArticles(cateid, 1);
});
// 页面加载完成后,自动触发第一个分类的点击事件
$(document).ready(function() {
var $firstMenuItem = $('.menu-item').first();
if ($firstMenuItem.length > 0) {
$firstMenuItem.click();
}
});
// 加载文章函数
function loadArticles(cateid, page) {
$.ajax({
url: '/index/game/list',
type: 'POST',
data: {
cate: cateid,
page: page
},
beforeSend: function() {
$('#gameList').html('<div class="loading-state"><i class="layui-icon layui-icon-loading"></i>加载中...</div>');
},
success: function(res) {
if(res.code === 1) {
var html = '';
if(res.data.games && res.data.games.length > 0) {
res.data.games.forEach(function(game) {
html += `<game class="game-card">
<div class="card-image">
<img src="${game.icon || game.category_icon || '/static/images/default-game.jpg'}" alt="${game.title}">
<div class="image-overlay"></div>
</div>
<div class="card-content">
<div class="meta-info">
<span class="category-tag">${game.category_name || '未分类'}</span>
<time class="publish-date">${game.create_time || ''}</time>
</div>
<h3 class="game-title">${game.title}</h3>
<div class="card-footer">
<div class="stats">
<span class="views"><i class="layui-icon layui-icon-eye"></i> ${game.views || 0}</span>
<span class="likes"><i class="layui-icon layui-icon-praise"></i> ${game.likes || 0}</span>
</div>
<a href="/index/game/detail?id=${game.id}" class="read-more">阅读更多</a>
</div>
</div>
</game>`;
});
} else {
html = `<div class="empty-state">
<div class="empty-icon">
<i class="layui-icon layui-icon-template-1"></i>
</div>
<h4>暂无文章</h4>
<p>当前分类下没有找到相关文章</p>
</div>`;
}
$('#gameList').html(html);
// 渲染分页
laypage.render({
elem: 'pagination',
count: res.data.total || 0,
limit: res.data.per_page || 12,
curr: res.data.current_page || 1,
theme: '#1E9FFF',
layout: ['prev', 'page', 'next'],
jump: function(obj, first) {
if(!first) {
loadArticles(cateid, obj.curr);
}
}
});
}
}
});
}
});
</script>
{include file="component/footer" /}
<style>
/* 基础样式重置 */
.modern-games-page {
font-family: 'Helvetica Neue', Arial, 'PingFang SC', 'Microsoft YaHei', sans-serif;
color: #333;
line-height: 1.6;
background-color: #f9fafc;
padding-bottom: 60px;
}
/* 标题区样式 */
.modern-header {
background: linear-gradient(135deg, #1E9FFF 0%, #0d8aff 100%);
color: white;
padding: 80px 0 60px;
text-align: center;
margin-bottom: 40px;
}
.modern-title {
font-size: 2.5rem;
font-weight: 300;
margin-bottom: 15px;
letter-spacing: 1px;
}
.modern-subtitle {
font-size: 1.1rem;
font-weight: 300;
opacity: 0.9;
margin: 0;
}
/* 布局结构 */
.modern-layout {
display: grid;
grid-template-columns: 260px 1fr;
gap: 30px;
}
/* 侧边栏样式 */
.modern-sidebar {
position: sticky;
top: 30px;
align-self: start;
}
.sidebar-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.03);
overflow: hidden;
}
.sidebar-title {
font-size: 1.1rem;
font-weight: 500;
padding: 20px;
margin: 0;
display: flex;
align-items: center;
color: #555;
border-bottom: 1px solid #f0f0f0;
}
.sidebar-title i {
margin-right: 10px;
font-size: 1.2rem;
color: #1E9FFF;
}
.category-menu {
list-style: none;
padding: 0;
margin: 0;
}
.menu-item {
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
transition: all 0.2s ease;
border-left: 3px solid transparent;
}
.menu-item:hover {
background-color: #f8fafd;
color: #1E9FFF;
}
.menu-item.active {
background-color: #f0f7ff;
border-left-color: #1E9FFF;
color: #1E9FFF;
font-weight: 500;
}
.menu-item i {
font-size: 0.9rem;
color: #aaa;
}
.menu-item.active i,
.menu-item:hover i {
color: #1E9FFF;
}
/* 主内容区样式 */
.modern-main {
background: transparent;
}
/* 文章网格布局 */
.game-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 40px;
}
/* 文章卡片样式 */
.game-card {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.03);
transition: all 0.3s ease;
display: flex;
flex-direction: column;
}
.game-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.08);
}
.card-image {
height: 180px;
position: relative;
overflow: hidden;
}
.card-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.3), transparent);
}
.game-card:hover .card-image img {
transform: scale(1.05);
}
.card-content {
padding: 20px;
flex: 1;
display: flex;
flex-direction: column;
}
.meta-info {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
font-size: 0.85rem;
color: #666;
}
.category-tag {
background: #f0f7ff;
color: #1E9FFF;
padding: 3px 10px;
border-radius: 4px;
font-size: 0.75rem;
}
.game-title {
font-size: 1rem;
font-weight: 500;
margin: 0 0 10px;
color: #333;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.game-excerpt {
font-size: 0.9rem;
color: #666;
margin: 0 0 20px;
flex: 1;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto;
}
.stats {
font-size: 0.85rem;
color: #999;
display: flex;
gap: 15px;
}
.stats i {
margin-right: 3px;
}
.read-more {
color: #1E9FFF;
font-size: 0.9rem;
text-decoration: none;
font-weight: 500;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
}
.read-more:hover {
color: #0d8aff;
text-decoration: underline;
}
/* 分页样式 */
.modern-pagination {
text-align: center;
margin-top: 40px;
}
.layui-laypage a,
.layui-laypage span {
border-radius: 4px !important;
margin: 0 3px !important;
}
.layui-laypage a {
color: #666 !important;
}
.layui-laypage .layui-laypage-curr .layui-laypage-em {
background-color: #1E9FFF !important;
}
/* 空状态样式 */
.empty-state {
grid-column: 1 / -1;
text-align: center;
padding: 60px 20px;
background: white;
border-radius: 8px;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.03);
}
.empty-icon {
font-size: 3rem;
color: #ddd;
margin-bottom: 20px;
}
.empty-icon i {
font-size: inherit;
}
.empty-state h4 {
font-size: 1.2rem;
font-weight: 400;
color: #666;
margin: 0 0 10px;
}
.empty-state p {
color: #999;
font-size: 0.95rem;
margin: 0;
}
/* 加载状态 */
.loading-state {
grid-column: 1 / -1;
text-align: center;
padding: 40px;
color: #666;
}
.loading-state i {
font-size: 1.5rem;
margin-right: 10px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 响应式设计 */
@media (max-width: 992px) {
.modern-layout {
grid-template-columns: 1fr;
}
.modern-sidebar {
position: static;
margin-bottom: 30px;
}
.game-grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
}
@media (max-width: 768px) {
.modern-header {
padding: 60px 0 40px;
}
.modern-title {
font-size: 2rem;
}
}
@media (max-width: 576px) {
.game-grid {
grid-template-columns: 1fr;
}
.modern-title {
font-size: 1.8rem;
}
.modern-subtitle {
font-size: 1rem;
}
}
</style>
{include file="component/foot" /}

View File

@ -0,0 +1,76 @@
<div class="container py-5">
<div class="row g-4">
<!-- 左侧分类列表 -->
<div class="col-lg-3">
<div class="category-sidebar">
<div class="sidebar-header">
<i class="layui-icon layui-icon-app"></i>
<span>文章分类</span>
</div>
<div class="category-list">
{volist name="categories" id="cate"}
<div class="category-item {$category.id == $cate.id ? 'active' : ''}" data-cateid="{$cate.id}">{$cate.name}</div>
{/volist}
</div>
</div>
</div>
<!-- 右侧文章列表 -->
<div class="col-lg-9">
{if $category}
<div class="category-header mb-4">
<h2 class="category-title">{$category.name}</h2>
<p class="category-desc">{$category.desc|default=''}</p>
</div>
{/if}
<div class="article-list">
{volist name="games" id="article"}
<div class="article-item">
<div class="row g-0">
<div class="col-md-4">
<div class="article-image">
<img src="{$article.image|default='/static/images/default.jpg'}" alt="{$article.title}">
</div>
</div>
<div class="col-md-8">
<div class="article-content">
<h3 class="article-title">
<a href="/index/game/detail?id={$article.id}">{$article.title}</a>
</h3>
<p class="article-desc">{$article.desc|default=''}</p>
<div class="article-meta">
<div class="article-stats">
<span><i class="layui-icon layui-icon-eye"></i> {$article.views|default=0}</span>
<span><i class="layui-icon layui-icon-praise"></i> {$article.likes|default=0}</span>
<span><i class="layui-icon layui-icon-date"></i> {$article.create_time|date="Y-m-d"}</span>
</div>
<a href="/index/game/detail?id={$article.id}" class="btn-detail">查看详情</a>
</div>
</div>
</div>
</div>
</div>
{/volist}
</div>
<!-- 分页 -->
<div class="mt-5">
{$games|raw}
</div>
</div>
</div>
</div>
<script>
layui.use(['layer'], function () {
var layer = layui.layer;
var $ = layui.$;
// 分类切换
$('.category-item').on('click', function() {
var cateid = $(this).data('cateid');
window.location.href = '/index/game/list?cate=' + cateid;
});
});
</script>

View File

@ -0,0 +1,535 @@
{include file="component/head" /}
{include file="component/header-simple" /}
<!-- 简约现代文章中心 -->
<div class="modern-programs-page">
<!-- 简约标题区 -->
<div class="modern-header">
<div class="container">
<h1 class="modern-title">文章中心</h1>
<p class="modern-subtitle">探索知识与洞见</p>
</div>
</div>
<!-- 主要内容区 -->
<div class="container">
<div class="modern-layout">
<!-- 侧边分类导航 -->
<aside class="modern-sidebar">
<div class="sidebar-card">
<h3 class="sidebar-title">
<i class="layui-icon layui-icon-list"></i>
<span>分类导航</span>
</h3>
<ul class="category-menu">
{volist name="cate.subCategories" id="subCategory"}
<li class="menu-item {$cate.id == $subCategory.id ? 'active' : ''}" data-cateid="{$subCategory.id}">
<span>{$subCategory.name}</span>
<i class="layui-icon layui-icon-right"></i>
</li>
{/volist}
</ul>
</div>
</aside>
<!-- 文章内容区 -->
<main class="modern-main">
<!-- 文章列表 -->
<div class="article-grid" id="programList">
{volist name="cate.subCategories" id="subCategory"}
{if $cate.id == $subCategory.id}
{if !empty($subCategory.list)}
{volist name="subCategory.list" id="program"}
<program class="program-card">
<div class="card-image">
<img src="{$program.image|default='/static/images/default-program.jpg'}" alt="{$program.title}">
<div class="image-overlay"></div>
</div>
<div class="card-content">
<div class="meta-info">
<span class="category-tag">{$subCategory.name}</span>
<time class="publish-date">{$program.create_time|date="Y-m-d"}</time>
</div>
<h3 class="program-title">{$program.title}</h3>
<div class="card-footer">
<div class="stats">
<span class="views"><i class="layui-icon layui-icon-eye"></i> {$program.views|default=0}</span>
<span class="likes"><i class="layui-icon layui-icon-praise"></i> {$program.likes|default=0}</span>
</div>
<a href="/index/program/detail?id={$program.id}" class="read-more">阅读更多</a>
</div>
</div>
</program>
{/volist}
{else}
<div class="empty-state">
<div class="empty-icon">
<i class="layui-icon layui-icon-template-1"></i>
</div>
<h4>暂无文章</h4>
<p>当前分类下没有找到相关文章</p>
</div>
{/if}
{/if}
{/volist}
</div>
<!-- 分页 -->
<div class="modern-pagination" id="pagination"></div>
</main>
</div>
</div>
</div>
<script>
layui.use(['laypage', 'jquery'], function(){
var laypage = layui.laypage;
var $ = layui.jquery;
// 分类切换
$('.menu-item').on('click', function() {
var cateid = $(this).data('cateid');
var $menuItems = $('.menu-item');
// 更新选中状态
$menuItems.removeClass('active');
$(this).addClass('active');
// 加载文章
loadArticles(cateid, 1);
});
// 页面加载完成后,自动触发第一个分类的点击事件
$(document).ready(function() {
var $firstMenuItem = $('.menu-item').first();
if ($firstMenuItem.length > 0) {
$firstMenuItem.click();
}
});
// 加载文章函数
function loadArticles(cateid, page) {
$.ajax({
url: '/index/program/list',
type: 'POST',
data: {
cate: cateid,
page: page
},
beforeSend: function() {
$('#programList').html('<div class="loading-state"><i class="layui-icon layui-icon-loading"></i>加载中...</div>');
},
success: function(res) {
if(res.code === 1) {
var html = '';
if(res.data.programs && res.data.programs.length > 0) {
res.data.programs.forEach(function(program) {
html += `<program class="program-card">
<div class="card-image">
<img src="${program.image || '/static/images/default-program.jpg'}" alt="${program.title}">
<div class="image-overlay"></div>
</div>
<div class="card-content">
<div class="meta-info">
<span class="category-tag">${program.category_name || '未分类'}</span>
<time class="publish-date">${program.create_time || ''}</time>
</div>
<h3 class="program-title">${program.title}</h3>
<div class="card-footer">
<div class="stats">
<span class="views"><i class="layui-icon layui-icon-eye"></i> ${program.views || 0}</span>
<span class="likes"><i class="layui-icon layui-icon-praise"></i> ${program.likes || 0}</span>
</div>
<a href="/index/program/detail?id=${program.id}" class="read-more">阅读更多</a>
</div>
</div>
</program>`;
});
} else {
html = `<div class="empty-state">
<div class="empty-icon">
<i class="layui-icon layui-icon-template-1"></i>
</div>
<h4>暂无文章</h4>
<p>当前分类下没有找到相关文章</p>
</div>`;
}
$('#programList').html(html);
// 渲染分页
laypage.render({
elem: 'pagination',
count: res.data.total || 0,
limit: res.data.per_page || 12,
curr: res.data.current_page || 1,
theme: '#1E9FFF',
layout: ['prev', 'page', 'next'],
jump: function(obj, first) {
if(!first) {
loadArticles(cateid, obj.curr);
}
}
});
}
}
});
}
});
</script>
{include file="component/footer" /}
<style>
/* 基础样式重置 */
.modern-programs-page {
font-family: 'Helvetica Neue', Arial, 'PingFang SC', 'Microsoft YaHei', sans-serif;
color: #333;
line-height: 1.6;
background-color: #f9fafc;
padding-bottom: 60px;
}
/* 标题区样式 */
.modern-header {
background: linear-gradient(135deg, #1E9FFF 0%, #0d8aff 100%);
color: white;
padding: 80px 0 60px;
text-align: center;
margin-bottom: 40px;
}
.modern-title {
font-size: 2.5rem;
font-weight: 300;
margin-bottom: 15px;
letter-spacing: 1px;
}
.modern-subtitle {
font-size: 1.1rem;
font-weight: 300;
opacity: 0.9;
margin: 0;
}
/* 布局结构 */
.modern-layout {
display: grid;
grid-template-columns: 260px 1fr;
gap: 30px;
}
/* 侧边栏样式 */
.modern-sidebar {
position: sticky;
top: 30px;
align-self: start;
}
.sidebar-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.03);
overflow: hidden;
}
.sidebar-title {
font-size: 1.1rem;
font-weight: 500;
padding: 20px;
margin: 0;
display: flex;
align-items: center;
color: #555;
border-bottom: 1px solid #f0f0f0;
}
.sidebar-title i {
margin-right: 10px;
font-size: 1.2rem;
color: #1E9FFF;
}
.category-menu {
list-style: none;
padding: 0;
margin: 0;
}
.menu-item {
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
transition: all 0.2s ease;
border-left: 3px solid transparent;
}
.menu-item:hover {
background-color: #f8fafd;
color: #1E9FFF;
}
.menu-item.active {
background-color: #f0f7ff;
border-left-color: #1E9FFF;
color: #1E9FFF;
font-weight: 500;
}
.menu-item i {
font-size: 0.9rem;
color: #aaa;
}
.menu-item.active i,
.menu-item:hover i {
color: #1E9FFF;
}
/* 主内容区样式 */
.modern-main {
background: transparent;
}
/* 文章网格布局 */
.article-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 40px;
}
/* 文章卡片样式 */
.article-card {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.03);
transition: all 0.3s ease;
display: flex;
flex-direction: column;
}
.article-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.08);
}
.card-image {
height: 180px;
position: relative;
overflow: hidden;
}
.card-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.3), transparent);
}
.article-card:hover .card-image img {
transform: scale(1.05);
}
.card-content {
padding: 20px;
flex: 1;
display: flex;
flex-direction: column;
}
.meta-info {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
font-size: 0.85rem;
color: #666;
}
.category-tag {
background: #f0f7ff;
color: #1E9FFF;
padding: 3px 10px;
border-radius: 4px;
font-size: 0.75rem;
}
.program-title {
font-size: 1rem;
font-weight: 500;
margin: 0 0 10px;
color: #333;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.program-excerpt {
font-size: 0.9rem;
color: #666;
margin: 0 0 20px;
flex: 1;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto;
}
.stats {
font-size: 0.85rem;
color: #999;
display: flex;
gap: 15px;
}
.stats i {
margin-right: 3px;
}
.read-more {
color: #1E9FFF;
font-size: 0.9rem;
text-decoration: none;
font-weight: 500;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
}
.read-more:hover {
color: #0d8aff;
text-decoration: underline;
}
/* 分页样式 */
.modern-pagination {
text-align: center;
margin-top: 40px;
}
.layui-laypage a,
.layui-laypage span {
border-radius: 4px !important;
margin: 0 3px !important;
}
.layui-laypage a {
color: #666 !important;
}
.layui-laypage .layui-laypage-curr .layui-laypage-em {
background-color: #1E9FFF !important;
}
/* 空状态样式 */
.empty-state {
grid-column: 1 / -1;
text-align: center;
padding: 60px 20px;
background: white;
border-radius: 8px;
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.03);
}
.empty-icon {
font-size: 3rem;
color: #ddd;
margin-bottom: 20px;
}
.empty-icon i {
font-size: inherit;
}
.empty-state h4 {
font-size: 1.2rem;
font-weight: 400;
color: #666;
margin: 0 0 10px;
}
.empty-state p {
color: #999;
font-size: 0.95rem;
margin: 0;
}
/* 加载状态 */
.loading-state {
grid-column: 1 / -1;
text-align: center;
padding: 40px;
color: #666;
}
.loading-state i {
font-size: 1.5rem;
margin-right: 10px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 响应式设计 */
@media (max-width: 1200px) {
.article-grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 992px) {
.modern-layout {
grid-template-columns: 1fr;
}
.modern-sidebar {
position: static;
margin-bottom: 30px;
}
.article-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 576px) {
.article-grid {
grid-template-columns: 1fr;
}
.modern-title {
font-size: 1.8rem;
}
.modern-subtitle {
font-size: 1rem;
}
}
</style>
{include file="component/foot" /}

View File

@ -0,0 +1,261 @@
<div class="container py-5">
<div class="row g-4">
<!-- 左侧分类列表 -->
<div class="col-lg-3">
<div class="category-sidebar">
<div class="sidebar-header">
<i class="layui-icon layui-icon-app"></i>
<span>程序分类</span>
</div>
<div class="category-list">
{volist name="categories" id="cate"}
<div class="category-item {$category.id == $cate.id ? 'active' : ''}" data-cateid="{$cate.id}">{$cate.name}</div>
{/volist}
</div>
</div>
</div>
<!-- 右侧程序列表 -->
<div class="col-lg-9">
{if $category}
<div class="category-header mb-4">
<h2 class="category-title">{$category.name}</h2>
<p class="category-desc">{$category.desc|default=''}</p>
</div>
{/if}
<div class="program-list">
{if empty($programs)}
<div class="empty-state">
<i class="layui-icon layui-icon-face-surprised"></i>
<p>暂无程序</p>
</div>
{else}
{volist name="programs" id="program"}
<div class="program-item">
<div class="row g-0">
<div class="col-md-4">
<div class="program-image">
<img src="{$program.icon|default='/static/images/default.jpg'}" alt="{$program.title}">
</div>
</div>
<div class="col-md-8">
<div class="program-content">
<h3 class="program-title">
<a href="/index/program/detail?id={$program.id}">{$program.title}</a>
</h3>
<p class="program-desc">{$program.desc|default=''}</p>
<div class="program-meta">
<div class="program-stats">
<span><i class="layui-icon layui-icon-eye"></i> {$program.views|default=0}</span>
<span><i class="layui-icon layui-icon-download-circle"></i> {$program.downloads|default=0}</span>
<span><i class="layui-icon layui-icon-date"></i> {$program.create_time|date="Y-m-d"}</span>
</div>
<a href="/index/program/detail?id={$program.id}" class="btn-detail">查看详情</a>
</div>
</div>
</div>
</div>
</div>
{/volist}
{/if}
</div>
<!-- 分页 -->
{if !empty($programs)}
<div class="mt-5">
{$programs->render()|raw}
</div>
{/if}
</div>
</div>
</div>
<style>
.program-list {
display: flex;
flex-direction: column;
gap: 20px;
}
.program-item {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: all 0.3s ease;
}
.program-item:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.program-image {
height: 200px;
overflow: hidden;
}
.program-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.program-content {
padding: 20px;
}
.program-title {
font-size: 1.5rem;
margin-bottom: 10px;
}
.program-title a {
color: #333;
text-decoration: none;
}
.program-title a:hover {
color: #1E9FFF;
}
.program-desc {
color: #666;
margin-bottom: 15px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.program-meta {
display: flex;
justify-content: space-between;
align-items: center;
color: #999;
}
.program-stats {
display: flex;
gap: 15px;
}
.program-stats span {
display: flex;
align-items: center;
gap: 5px;
}
.btn-detail {
padding: 6px 15px;
background: #1E9FFF;
color: #fff;
border-radius: 4px;
text-decoration: none;
transition: all 0.3s ease;
}
.btn-detail:hover {
background: #0d8aff;
color: #fff;
}
.category-sidebar {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
padding: 20px;
}
.sidebar-header {
font-size: 1.2rem;
font-weight: bold;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.category-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.category-item {
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
}
.category-item:hover {
background: #f5f5f5;
}
.category-item.active {
background: #1E9FFF;
color: #fff;
}
.category-header {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.category-title {
margin: 0;
color: #333;
}
.category-desc {
margin: 10px 0 0;
color: #666;
}
.empty-state {
text-align: center;
padding: 40px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.empty-state i {
font-size: 48px;
color: #999;
margin-bottom: 15px;
}
.empty-state p {
color: #666;
font-size: 16px;
margin: 0;
}
</style>
<script>
layui.use(['layer'], function () {
var layer = layui.layer;
var $ = layui.$;
// 分类切换
$('.category-item').on('click', function() {
var cateid = $(this).data('cateid');
window.location.href = '/index/program/list?cate=' + cateid;
});
});
</script>
// 页面加载完成后,自动触发第一个分类的点击事件
$(document).ready(function() {
var $firstMenuItem = $('.category-item').first();
if ($firstMenuItem.length > 0) {
$firstMenuItem.click();
}
});
});
</script>

View File

@ -72,17 +72,6 @@
loadSecurityInfo();
});
// 加载安全信息
function loadSecurityInfo() {
fetch('/index/user/getSecurityInfo')
.then(response => response.json())
.then(data => {
if (data.code === 0) {
document.getElementById('phoneNumber').textContent = data.data.phone || '未绑定';
}
});
}
// 修改密码
function changePassword() {
layer.open({

View File

@ -1,4 +1,4 @@
<?php /*a:5:{s:52:"E:\Demo\PHP\yunzer\app\index\view\program\detail.php";i:1747755857;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\head.php";i:1747649140;s:61:"E:\Demo\PHP\yunzer\app\index\view\component\header-simple.php";i:1747754938;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\footer.php";i:1747649140;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:1748185543;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\head.php";i:1747649140;s:61:"E:\Demo\PHP\yunzer\app\index\view\component\header-simple.php";i:1748341037;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\footer.php";i:1747649140;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\foot.php";i:1746808046;}*/ ?>
<!DOCTYPE html>
<html>
@ -18,37 +18,43 @@
</head>
<body>
<?php
// 获取当前登录状态
$isLoggedIn = false;
$userInfo = [
'is_login' => false,
'name' => '',
'avatar' => '/static/images/avatar.png' // 默认头像
];
// 检查cookie
$userAccount = cookie('user_account');
if ($userAccount) {
$isLoggedIn = true;
$userInfo = [
'is_login' => true,
'name' => cookie('user_name'),
'avatar' => cookie('user_avatar') ? cookie('user_avatar') : '/static/images/avatar.png'
];
}
// 添加一个隐藏的div来存储登录状态
$loginStatus = [
'isLoggedIn' => $isLoggedIn,
'userAccount' => $userAccount ?? ''
];
?>
<!-- 添加一个隐藏的div来存储登录状态 -->
<div id="loginStatus" style="display: none;" data-is-logged-in="<?php echo htmlentities((string) $isLoggedIn); ?>" data-user-account="<?php echo isset($userAccount) ? htmlentities((string) $userAccount) : ''; ?>">
</div>
<div style="display: flex;flex-direction: column;">
<div class="topbar-one">
<div class="container">
<div style="width: 70%;">
<ul class="list-unstyled topbar-one__info">
<li class="topbar-one__info__item">
<span class="topbar-one__info__icon fas fa-phone-alt" style="margin-right: 10px;"></span>
<a href="<?php echo htmlentities((string) $config['admin_phone']); ?>"><?php echo htmlentities((string) $config['admin_phone']); ?></a>
</li>
<li class="topbar-one__info__item">
<span class="topbar-one__info__icon fas fa-envelope" style="margin-right: 10px;"></span>
<a href="mailto:<?php echo htmlentities((string) $config['admin_email']); ?>"><?php echo htmlentities((string) $config['admin_email']); ?></a>
</li>
</ul>
</div>
<div class="topbar-one__social" style="width: 30%;">
<a href="/index/user/login" class="mr-10"><i class="layui-icon layui-icon-username"></i> 登录</a>
<a href="/index/user/register" class="mr-10"><i class="layui-icon layui-icon-user"></i> 注册</a>
<a href="javascript:;" class="qrcode-trigger"><i class="layui-icon layui-icon-qrcode"></i> 公众号</a>
<div class="qrcode-popup"
style="display:none;position:absolute;right:54px;top:32px;background:#fff;padding:10px;box-shadow:0 0 10px rgba(0,0,0,0.1); z-index: 1000;">
<img src="<?php echo htmlentities((string) $config['admin_wechat']); ?>" alt="公众号二维码" style="width:180px;height:180px;">
</div>
</div>
</div>
</div>
<!-- 导航栏 -->
<div class="main-menu">
<div class="container">
<div class="main-menu__logo">
<a href="index.html"><img src="/static/images/logo1.png" width="186" alt="Logo"></a>
<a href="/index.html"><img src="/static/images/logo1.png" width="186" alt="Logo"></a>
</div>
<div class="main-menu__nav">
<ul class="main-menu__list">
@ -59,27 +65,40 @@
</ul>
</div>
<div class="main-menu__right">
<div class="username">
<?php if ($userInfo['is_login']): ?>
<span class="username-text"><?php echo htmlentities((string) $userInfo['name']); ?></span>
<?php endif; ?>
</div>
<div class="layui-inline">
<div class="layui-inline" style="position: relative;">
<img src="/static/images/avatar.webp" class="layui-circle"
style="width: 40px; height: 40px; cursor: pointer;" id="userAvatarMain">
<div class="user-dropdown" id="userDropdownMain">
<ul>
<li>
<a href="/index/user/profile"><i
class="layui-icon layui-icon-user"></i><span>个人中心</span></a>
</li>
<li>
<a href="/index/user/settings"><i
class="layui-icon layui-icon-set"></i><span>账号管理</span></a>
</li>
<li>
<a href="javascript:;" class="logout-btn"><i
class="layui-icon layui-icon-logout"></i><span>退出登录</span></a>
</li>
</ul>
<!-- 根据登录状态显示不同的内容 -->
<?php if ($isLoggedIn): ?>
<div class="layui-inline" style="position: relative;margin-left:20px;">
<img src="<?php echo htmlentities((string) $userInfo['avatar']); ?>" class="layui-circle"
style="width: 40px; height: 40px; cursor: pointer;" id="userAvatarSticky">
<div class="user-dropdown" id="userDropdownSticky">
<ul>
<li>
<a href="/index/user/profile"><i
class="layui-icon layui-icon-user"></i><span>个人中心</span></a>
</li>
<li>
<a href="/index/user/settings"><i
class="layui-icon layui-icon-set"></i><span>账号管理</span></a>
</li>
<li>
<a href="javascript:;" class="logout-btn"><i
class="layui-icon layui-icon-logout"></i><span>退出登录</span></a>
</li>
</ul>
</div>
</div>
</div>
<?php else: ?>
<div class="layui-inline">
<a href="/index/user/login" class="layui-btn layui-btn-normal">登录</a>
<a href="/index/user/register" class="layui-btn layui-btn-primary">注册</a>
</div>
<?php endif; ?>
</div>
</div>
</div>
@ -90,7 +109,7 @@
<div class="sticky-nav" style="display: none;">
<div class="container">
<div class="sticky-nav__logo">
<a href="index.html"><img src="/static/images/logo1.png" width="150" alt="Logo"></a>
<a href="/index.html"><img src="/static/images/logo1.png" width="150" alt="Logo"></a>
</div>
<div class="sticky-nav__menu">
<ul>
@ -102,27 +121,40 @@
</div>
<div class="sticky-nav__right">
<div class="main-menu__right">
<div class="username">
<?php if ($userInfo['is_login']): ?>
<span class="username-text"><?php echo htmlentities((string) $userInfo['name']); ?></span>
<?php endif; ?>
</div>
<div class="layui-inline">
<div class="layui-inline" style="position: relative;">
<img src="/static/images/avatar.webp" class="layui-circle"
style="width: 40px; height: 40px; cursor: pointer;" id="userAvatarSticky">
<div class="user-dropdown" id="userDropdownSticky">
<ul>
<li>
<a href="/index/user/profile"><i
class="layui-icon layui-icon-user"></i><span>个人中心</span></a>
</li>
<li>
<a href="/index/user/settings"><i
class="layui-icon layui-icon-set"></i><span>账号管理</span></a>
</li>
<li>
<a href="javascript:;" class="logout-btn"><i
class="layui-icon layui-icon-logout"></i><span>退出登录</span></a>
</li>
</ul>
<!-- 根据登录状态显示不同的内容 -->
<?php if ($isLoggedIn): ?>
<div class="layui-inline" style="position: relative;margin-left:20px;">
<img src="<?php echo htmlentities((string) $userInfo['avatar']); ?>" class="layui-circle"
style="width: 40px; height: 40px; cursor: pointer;" id="userAvatarSticky">
<div class="user-dropdown" id="userDropdownSticky">
<ul>
<li>
<a href="/index/user/profile"><i
class="layui-icon layui-icon-user"></i><span>个人中心</span></a>
</li>
<li>
<a href="/index/user/settings"><i
class="layui-icon layui-icon-set"></i><span>账号管理</span></a>
</li>
<li>
<a href="javascript:;" class="logout-btn"><i
class="layui-icon layui-icon-logout"></i><span>退出登录</span></a>
</li>
</ul>
</div>
</div>
</div>
<?php else: ?>
<div class="layui-inline">
<a href="/index/user/login" class="layui-btn layui-btn-normal">登录</a>
<a href="/index/user/register" class="layui-btn layui-btn-primary">注册</a>
</div>
<?php endif; ?>
</div>
</div>
</div>
@ -328,51 +360,107 @@
#test10 [carousel-item]>* {
background: none !important;
}
.main-menu__right {
display: flex;
align-items: center;
}
.username {
display: flex;
align-items: center;
}
</style>
<script>
// 在页面加载时立即执行
(function () {
// 检查是否已经刷新过
if (sessionStorage.getItem('has_refreshed') === 'true') {
return;
}
// 检查localStorage中是否有用户账号
var userAccount = localStorage.getItem('user_account');
if (userAccount) {
// 同步到cookie
document.cookie = "user_account=" + userAccount + "; path=/";
// 如果有其他必要的数据也同步到cookie
var userId = localStorage.getItem('user_id');
var userName = localStorage.getItem('user_name');
var userAvatar = localStorage.getItem('user_avatar');
if (userId) document.cookie = "user_id=" + userId + "; path=/";
if (userName) document.cookie = "user_name=" + userName + "; path=/";
if (userAvatar) document.cookie = "user_avatar=" + userAvatar + "; path=/";
// 刷新页面以应用新的cookie并标记已刷新
if (!document.cookie.includes('user_id')) {
sessionStorage.setItem('has_refreshed', 'true');
window.location.reload();
}
}
})();
layui.use(['carousel', 'form', 'layer'], function () {
var carousel = layui.carousel, form = layui.form, layer = layui.layer, $ = layui.$;
// 加载banner数据
$.ajax({
url: '/index/index/bannerlist',
type: 'GET',
success: function (res) {
if (res.code === 1) {
var bannerHtml = '';
res.banner.forEach(function (banner) {
bannerHtml += '<div>' +
'<div class="banner-content">' +
'<div class="banner-image">' +
'<img src="' + banner.image + '" alt="' + (banner.title || '') + '">' +
'</div>' +
'<div class="banner-text">' +
'<span class="banner-title">' + (banner.title || '') + '</span>' +
'<span class="banner-desc">' + (banner.desc || '') + '</span>' +
'<a href="' + (banner.url || 'javascript:;') + '" class="banner-slide">' +
'<span class="banner-btn">查看详情</span>' +
'</a>' +
'</div>' +
'</div>' +
'</div>';
});
$('#test10 div[carousel-item]').html(bannerHtml);
// 图片轮播
carousel.render({
elem: '#test10',
width: '100%',
height: '100vh',
interval: 4000,
anim: 'fade',
autoplay: true,
full: false,
arrow: 'hover'
});
}
// 检查本地存储并自动登录
function checkAutoLogin() {
// 如果已经登录,不再执行自动登录
if ($('#userAvatarMain').length > 0) {
return;
}
});
// 如果已经尝试过自动登录,不再执行
if (sessionStorage.getItem('auto_login_attempted') === 'true') {
return;
}
// 从localStorage获取用户账号
var userAccount = localStorage.getItem('user_account');
if (userAccount) {
// 标记已尝试自动登录
sessionStorage.setItem('auto_login_attempted', 'true');
// 发送自动登录请求
$.ajax({
url: '/index/user/login',
type: 'POST',
data: {
account: userAccount,
password: atob(localStorage.getItem('user_password'))
},
dataType: 'json',
success: function (res) {
if (res.code === 0) {
// 设置cookie
document.cookie = "user_id=" + res.data.id + "; path=/";
document.cookie = "user_name=" + res.data.name + "; path=/";
document.cookie = "user_avatar=" + res.data.avatar + "; path=/";
document.cookie = "user_account=" + userAccount + "; path=/";
// 同时更新localStorage
localStorage.setItem('user_id', res.data.id);
localStorage.setItem('user_name', res.data.name);
localStorage.setItem('user_avatar', res.data.avatar);
// 登录成功,强制刷新页面
window.location.href = window.location.href + '?t=' + new Date().getTime();
} else {
// 登录失败,清除所有相关存储
localStorage.removeItem('user_account');
localStorage.removeItem('user_password');
sessionStorage.removeItem('auto_login_attempted');
}
}
});
}
}
// 页面加载时检查自动登录
checkAutoLogin();
$(document).ready(function () {
// 主导航头像
@ -406,7 +494,36 @@
layer.confirm('确定要退出登录吗?', {
btn: ['确定', '取消']
}, function () {
window.location.href = '/index/user/logout';
// 先发送退出请求
$.ajax({
url: '/index/user/logout',
type: 'POST',
dataType: 'json',
success: function (res) {
if (res.code === 0) {
// 清除localStorage
localStorage.removeItem('user_account');
localStorage.removeItem('user_password');
localStorage.removeItem('user_id');
localStorage.removeItem('user_name');
localStorage.removeItem('user_avatar');
// 清除sessionStorage
sessionStorage.removeItem('auto_login_attempted');
sessionStorage.removeItem('has_refreshed');
// 清除cookie
document.cookie = "user_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "user_name=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "user_avatar=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "user_account=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "user_password=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// 强制刷新页面,不使用缓存
window.location.href = window.location.href + '?t=' + new Date().getTime();
}
}
});
});
});
@ -443,6 +560,62 @@
popup.addEventListener('mouseleave', function () {
popup.style.display = 'none';
});
form.on('submit(accountLogin)', function (data) {
$.ajax({
url: '<?php echo url("index/user/login"); ?>',
type: 'POST',
data: data.field,
dataType: 'json',
success: function (res) {
if (res.code === 0) {
// 存储登录数据设置7天过期
var expireTime = new Date().getTime() + 7 * 24 * 60 * 60 * 1000;
// 设置localStorage
localStorage.setItem('user_account', data.field.account);
localStorage.setItem('user_password', btoa(data.field.password));
localStorage.setItem('expire_time', expireTime);
localStorage.setItem('is_auto_login', 'true');
// 设置cookie
document.cookie = "user_id=" + res.data.id + "; path=/";
document.cookie = "user_name=" + res.data.name + "; path=/";
document.cookie = "user_avatar=" + res.data.avatar + "; path=/";
document.cookie = "expire_time=" + expireTime + "; path=/";
document.cookie = "is_auto_login=true; path=/";
document.cookie = "user_account=" + data.field.account + "; path=/";
document.cookie = "user_password=" + btoa(data.field.password) + "; path=/";
// 设置sessionStorage
sessionStorage.setItem('auto_login_attempted', 'true');
layer.msg('登录成功', {
icon: 1,
time: 2000,
shade: 0.3
}, function () {
// 获取当前页面URL
var currentUrl = window.location.href;
// 如果当前页面是登录页面,则跳转到首页
if (currentUrl.includes('/index/user/login')) {
window.location.href = '/index.html';
} else {
// 否则刷新当前页面
window.location.href = currentUrl + '?t=' + new Date().getTime();
}
});
} else {
layer.msg(res.msg, {
icon: 2,
time: 2000
});
}
}
});
return false;
});
});
</script>
<div class="main">
@ -504,6 +677,15 @@
</div>
</div>
<div class="disclaimers">
<div class="disclaimer-item">
<div class="disclaimer-title">免责声明:</div>
<div class="disclaimer-content">
<?php echo $config['disclaimers'] ?>
</div>
</div>
</div>
<div class="program-navigation">
<div class="prev-program" id="prevProgram">
</div>
@ -850,6 +1032,28 @@
.location-item a {
color: #000 !important;
}
.disclaimers {
color: #b1b1b1;
width: 80%;
margin: 20px auto;
margin-bottom: 60px;
}
.disclaimer-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 10px;
}
.disclaimer-content {
font-size: 14px;
line-height: 1.6;
}
.disclaimer-content p {
margin-bottom: 0;
}
</style>
<script>

View File

@ -1,4 +1,4 @@
<?php /*a:4:{s:49:"E:\Demo\PHP\yunzer\app\index\view\index\index.php";i:1746890051;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\header.php";i:1748280591;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\main.php";i:1747748380;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\footer.php";i:1747649140;}*/ ?>
<?php /*a:4:{s:49:"E:\Demo\PHP\yunzer\app\index\view\index\index.php";i:1746890051;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\header.php";i:1748341037;s:52:"E:\Demo\PHP\yunzer\app\index\view\component\main.php";i:1748359853;s:54:"E:\Demo\PHP\yunzer\app\index\view\component\footer.php";i:1747649140;}*/ ?>
<!DOCTYPE html>
<html>
@ -19,21 +19,21 @@
<?php
// 获取当前登录状态
$isLoggedIn = false;
$userInfo = [
'is_login' => false,
'name' => '',
'avatar' => '/static/images/avatar.png' // 默认头像
];
// 检查session
if (session('user_id')) {
// 检查cookie
$userAccount = cookie('user_account');
if ($userAccount) {
$isLoggedIn = true;
}
// 如果session未登录检查cookie
else {
$userAccount = cookie('user_account');
if ($userAccount) {
// 恢复session
session('user_id', cookie('user_id'));
session('user_name', cookie('user_name'));
session('user_avatar', cookie('user_avatar'));
$isLoggedIn = true;
}
$userInfo = [
'is_login' => true,
'name' => cookie('user_name'),
'avatar' => cookie('user_avatar') ? cookie('user_avatar') : '/static/images/avatar.png'
];
}
// 添加一个隐藏的div来存储登录状态
@ -41,18 +41,10 @@ $loginStatus = [
'isLoggedIn' => $isLoggedIn,
'userAccount' => $userAccount ?? ''
];
$userInfo = [
'is_login' => $isLoggedIn,
'name' => session('user_name'),
'avatar' => session('user_avatar') ? '/static/uploads/avatar/' . session('user_avatar') : '/static/images/avatar.png'
];
?>
<!-- 添加一个隐藏的div来存储登录状态 -->
<div id="loginStatus" style="display: none;"
data-is-logged-in="<?php echo htmlentities((string) $isLoggedIn); ?>"
data-user-account="<?php echo isset($userAccount) ? htmlentities((string) $userAccount) : ''; ?>">
<div id="loginStatus" style="display: none;" data-is-logged-in="<?php echo htmlentities((string) $isLoggedIn); ?>" data-user-account="<?php echo isset($userAccount) ? htmlentities((string) $userAccount) : ''; ?>">
</div>
<div style="display: flex;flex-direction: column;">
@ -94,10 +86,15 @@ $userInfo = [
</ul>
</div>
<div class="main-menu__right">
<div class="username">
<?php if ($userInfo['is_login']): ?>
<span class="username-text"><?php echo htmlentities((string) $userInfo['name']); ?></span>
<?php endif; ?>
</div>
<div class="layui-inline">
<!-- 根据登录状态显示不同的内容 -->
<?php if ($userInfo['is_login']): ?>
<div class="layui-inline" style="position: relative;">
<div class="layui-inline" style="position: relative;margin-left:20px;">
<img src="<?php echo htmlentities((string) $userInfo['avatar']); ?>" class="layui-circle"
style="width: 40px; height: 40px; cursor: pointer;" id="userAvatarMain">
<div class="user-dropdown" id="userDropdownMain">
@ -160,7 +157,7 @@ $userInfo = [
<div class="layui-inline">
<!-- 根据登录状态显示不同的内容 -->
<?php if ($userInfo['is_login']): ?>
<div class="layui-inline" style="position: relative;">
<div class="layui-inline" style="position: relative;margin-left:20px;">
<img src="<?php echo htmlentities((string) $userInfo['avatar']); ?>" class="layui-circle"
style="width: 40px; height: 40px; cursor: pointer;" id="userAvatarSticky">
<div class="user-dropdown" id="userDropdownSticky">
@ -391,11 +388,21 @@ $userInfo = [
#test10 [carousel-item]>* {
background: none !important;
}
.main-menu__right {
display: flex;
align-items: center;
}
.username {
display: flex;
align-items: center;
}
</style>
<script>
// 在页面加载时立即执行
(function() {
(function () {
// 检查是否已经刷新过
if (sessionStorage.getItem('has_refreshed') === 'true') {
return;
@ -406,16 +413,16 @@ $userInfo = [
if (userAccount) {
// 同步到cookie
document.cookie = "user_account=" + userAccount + "; path=/";
// 如果有其他必要的数据也同步到cookie
var userId = localStorage.getItem('user_id');
var userName = localStorage.getItem('user_name');
var userAvatar = localStorage.getItem('user_avatar');
if (userId) document.cookie = "user_id=" + userId + "; path=/";
if (userName) document.cookie = "user_name=" + userName + "; path=/";
if (userAvatar) document.cookie = "user_avatar=" + userAvatar + "; path=/";
// 刷新页面以应用新的cookie并标记已刷新
if (!document.cookie.includes('user_id')) {
sessionStorage.setItem('has_refreshed', 'true');
@ -656,10 +663,18 @@ $userInfo = [
time: 2000,
shade: 0.3
}, function () {
// 强制刷新页面,不使用缓存
window.location.href = window.location.href + '?t=' + new Date().getTime();
// 获取当前页面URL如果是从其他页面跳转来的则返回上一页
var currentUrl = window.location.href;
var referrer = document.referrer;
// 如果是从登录页面跳转来的,则返回上一页
if (referrer && referrer.includes('/index/user/login')) {
window.location.href = referrer;
} else {
// 否则刷新当前页面
window.location.href = currentUrl + '?t=' + new Date().getTime();
}
});
} else {
layer.msg(res.msg, {
icon: 2,
time: 2000
@ -687,7 +702,7 @@ $userInfo = [
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/articles/index?cateid=1', '_blank')">更多</div>
</div>
<div class="product-list" id="webArticlesList">
<!-- 文章将通过JavaScript动态加载 -->
@ -708,7 +723,7 @@ $userInfo = [
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/articles/index?cateid=3', '_blank')">更多</div>
</div>
<div class="product-list" id="techArticlesList">
<!-- 文章将通过JavaScript动态加载 -->
@ -729,7 +744,7 @@ $userInfo = [
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/program/index?cateid=2', '_blank')">更多</div>
</div>
<div class="product-list" id="resourcesDownloadList">
<!-- 文章将通过JavaScript动态加载 -->
@ -750,7 +765,7 @@ $userInfo = [
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/program/index?cateid=1', '_blank')">更多</div>
</div>
<div class="product-list" id="programDownloadList">
<!-- 程序将通过JavaScript动态加载 -->
@ -771,7 +786,7 @@ $userInfo = [
</div>
</div>
</div>
<div class="more-btn">更多</div>
<div class="more-btn" onclick="window.open('/index/game/index?cateid=8', '_blank')">更多</div>
</div>
<div class="product-list" id="gameDownloadList">
<!-- 游戏将通过JavaScript动态加载 -->