diff --git a/README.MD b/README.MD index 47231a5..fd21e91 100644 --- a/README.MD +++ b/README.MD @@ -32,8 +32,6 @@ - 增加系统显示设置 - 增加浏览器信息显示设置 - 修复pjax模式下的404跳转 - ---- - 2025.07.07 表情短代码解析集成 - 1.1.5 @@ -54,4 +52,8 @@ - 新增支持[success]、[primary]、[danger]、[warning]、[info]、[dark]等alert类短代码,自动渲染为对应的Bootstrap风格提示框。 - 新增支持[collapse title='xxx']内容[/collapse]折叠面板短代码,自动渲染为带唯一ID的Bootstrap折叠结构。 - 新增支持[download file='xxx.zip' size='12MB']文件地址[/download]下载短代码,自动渲染为带文件名、大小、声明和下载地址的下载信息块。 - - 新增支持[reply]隐藏内容[/reply]回复可见短代码,未满足条件时前端显示提示,已评论且审核通过后显示隐藏内容。 \ No newline at end of file + - 新增支持[reply]隐藏内容[/reply]回复可见短代码,未满足条件时前端显示提示,已评论且审核通过后显示隐藏内容。 + + - 1.2.0 + + - 新增支持首页登录 \ No newline at end of file diff --git a/assets/js/puock.js b/assets/js/puock.js index df3e4fe..c06d494 100644 --- a/assets/js/puock.js +++ b/assets/js/puock.js @@ -143,6 +143,10 @@ class Puock { }); // form ajax submit $(document).on("submit", ".ajax-form", (e) => { + // 如果是登录弹窗表单,允许原生提交 + if ($(e.target).attr('id') === 'front-login-form') { + return true; + } e.preventDefault(); const form = $(this.ct(e)); const formEls = form.find(":input") @@ -208,6 +212,32 @@ class Puock { } return false; }) + // 登录弹窗表单AJAX提交(集成Puock插件接口) + $(document).off('submit', '#front-login-form'); + $(document).on('submit', '#front-login-form', function(e) { + e.preventDefault(); + var $form = $(this); + var data = $form.serialize(); + $.ajax({ + url: '/index.php/ajaxlogin/', + type: 'POST', + data: data, + dataType: 'json', + success: function(res) { + if (res.success) { + window.Puock.toast(res.msg || '登录成功', TYPE_SUCCESS); + setTimeout(function() { + window.location.reload(); + }, 800); + } else { + window.Puock.toast(res.msg || '登录失败', TYPE_DANGER); + } + }, + error: function() { + window.Puock.toast('请求失败', TYPE_DANGER); + } + }); + }); } pageLinkBlankOpenInit() { @@ -415,7 +445,7 @@ class Puock { this.pageLinkBlankOpenInit() this.initGithubCard(); this.keyUpHandle(); - this.loadHitokoto(); + // this.loadHitokoto(); // this.asyncCacheViews(); this.swiperInit(); // this.validateInit(); @@ -771,12 +801,14 @@ class Puock { } parseFormData(formEl, args = {}) { + // 先获取表单所有字段 const dataArr = formEl.serializeArray(); - const data = {...args}; + const data = {}; for (let i = 0; i < dataArr.length; i++) { data[dataArr[i].name] = dataArr[i].value; } - return jQuery.param(data); + // 合并额外参数 + return jQuery.param(Object.assign(data, args)); } eventCommentPreSubmit() { @@ -881,19 +913,26 @@ class Puock { eventOpenCommentBox() { $(document).off("click", ".comment-reply"); - $(document).on("click", ".comment-reply", (e) => { + $(document).on("click", ".comment-reply", function(e) { e.preventDefault(); - this.data.comment.replyId = $(this.ct(e)).attr("data-coid"); - if ($.trim(this.data.comment.replyId) === '') { - this.toast('结构有误', TYPE_DANGER); + const replyBtn = $(e.currentTarget); + const replyId = replyBtn.attr("data-coid"); + if ($.trim(replyId) === '') { + window.Puock.toast('结构有误', TYPE_DANGER); return; } - const cf = $("#comment-form"), - commentLi = $(this.ct(e)).closest('.post-comment'); + const cf = $("#comment-form"); + const commentLi = replyBtn.closest('.post-comment'); + // 只在表单在原位时插入占位符 + if (!$("#comment-form-place-holder").length && cf.parent().attr("id") === "comment-form-box") { + cf.before('
'); + } + // 每次都append到目标评论下方 commentLi.append(cf); $("#comment-cancel").removeClass("d-none"); $("#comment").val(""); - $("#comment_parent").val(this.data.comment.replyId); + $("#comment_parent").val(replyId); + window.Puock.data.comment.replyId = replyId; // 滚动至表单 if (cf.length && cf[0].scrollIntoView) { cf[0].scrollIntoView({behavior: "smooth", block: "center"}); @@ -904,12 +943,17 @@ class Puock { eventCloseCommentBox() { $(document).off("click", "#comment-cancel"); $(document).on("click", "#comment-cancel", () => { - const cf = $("#comment-form"), - cb = $(".post-comment .box-sw").parent(); - cf.removeClass("box-sw"); - $("#comment-form-box").append(cf); + const cf = $("#comment-form"); + const holder = $("#comment-form-place-holder"); + if (holder.length) { + holder.before(cf); + holder.remove(); + } else { + $("#comment-form-box").append(cf); + } $("#comment-cancel").addClass("d-none"); this.data.comment.replyId = null; + $("#comment_parent").val(''); }); } @@ -1141,25 +1185,6 @@ class Puock { }); } - loadHitokoto() { - setTimeout(() => { - $(".widget-puock-hitokoto").each((_, v) => { - const el = $(v); - const api = el.attr("data-api") || "https://v1.hitokoto.cn/" - $.get(api, (res) => { - el.find(".t").text(res.hitokoto ?? res.content ?? "无内容"); - el.find('.f').text(res.from); - el.find('.fb').removeClass("d-none"); - }, 'json').fail((err) => { - console.error(err) - el.find(".t").text("加载失败:" + err.responseText || err); - el.remove(".fb"); - }) - }) - }, 300) - } - - toast(msg, type = TYPE_PRIMARY, options = {}) { options = Object.assign({ duration: 2600, diff --git a/comments.php b/comments.php index 8d00fd7..8f296e2 100644 --- a/comments.php +++ b/comments.php @@ -59,7 +59,7 @@ - + @@ -217,59 +217,4 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/functions.php b/functions.php index fc23fe9..c929f01 100644 --- a/functions.php +++ b/functions.php @@ -186,14 +186,30 @@ function getAllCommenters() { $db = Typecho_Db::get(); $commenters = array(); - // 查询所有评论者信息并按邮箱分组统计 - $query = $db->select('author, mail, COUNT(*) as comment_count, url') + $isSqlite = strpos(strtolower(get_class($db->getAdapter())), 'sqlite') !== false; + if ($isSqlite) { + // SQLite 不支持 ANY_VALUE + $query = $db->select('author', 'mail', 'COUNT(*) as comment_count', 'url') + ->from('table.comments') + ->where('status = ?', 'approved') + ->where('authorId != ?', 1) + ->group('mail') + ->order('comment_count', Typecho_Db::SORT_DESC); + } else { + // MySQL 用 ANY_VALUE 兼容 ONLY_FULL_GROUP_BY + $query = $db->select( + 'ANY_VALUE(author) as author', + 'mail', + 'COUNT(*) as comment_count', + 'ANY_VALUE(url) as url' + ) ->from('table.comments') - ->where('status = ?', 'approved') // 只统计已通过审核的评论 - ->where('authorId != ?', 1) // 排除ID为1的管理员 + ->where('authorId != ?', 1) + ->where('status = ?', 'approved') ->group('mail') ->order('comment_count', Typecho_Db::SORT_DESC); - + } + $rows = $db->fetchAll($query); // 获取 Gravatar 镜像设置 @@ -964,8 +980,7 @@ function parse_smiley_shortcode($content) { } return $content; } -?> -getPrefix(); + + // 获取当前登录用户对象 + $currentUser = Typecho_Widget::widget('Widget_User'); + + // 如果用户未登录,获取默认uid=1的用户 + if (!$currentUser->hasLogin()) { + $defaultUser = $db->fetchRow($db->select()->from('table.users')->where('uid = ?', 1)); + $email = $defaultUser['mail']; + $nickname = $defaultUser['screenName']; + } else { + // 用户已登录,使用当前用户信息 + $email = $currentUser->mail; + $nickname = $currentUser->screenName; + } + + // 获取用户设置的 Gravatar 镜像 + $cnavatar = Helper::options()->cnavatar ? Helper::options()->cnavatar : 'https://cravatar.cn/avatar/'; + $hash = md5($email); + $avatar = rtrim($cnavatar, '/') . '/' . $hash . '?s=80&d=identicon'; + + // 其余统计信息保持不变 + $userCount = $db->fetchObject($db->select(array('COUNT(*)' => 'num'))->from('table.users'))->num; + $postCount = $db->fetchObject($db->select(array('COUNT(*)' => 'num'))->from('table.contents')->where('type = ?', 'post')->where('status = ?', 'publish'))->num; + $commentCount = $db->fetchObject($db->select(array('COUNT(*)' => 'num'))->from('table.comments'))->num; + $totalViews = $db->fetchObject( + $db->select(array('SUM(views)' => 'viewsum'))->from('table.contents')->where('type = ?', 'post') + )->viewsum; + if ($totalViews === null) $totalViews = 0; + + return [ + 'email' => $email, + 'nickname' => $nickname, + 'avatar' => $avatar, + 'userCount' => $userCount, + 'postCount' => $postCount, + 'commentCount' => $commentCount, + 'totalViews' => $totalViews, + 'isLogin' => $currentUser->hasLogin() // 添加一个是否登录的标志 + ]; +} + +// Typecho AJAX 登录接口,支持前端 AJAX 提交并返回 JSON +if (!empty($_GET['ajaxLogin']) && $_GET['ajaxLogin'] == 1) { + header('Content-Type: application/json; charset=utf-8'); + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + echo json_encode(['success' => false, 'msg' => '请求方式错误']); + exit; + } + $name = isset($_POST['name']) ? trim($_POST['name']) : ''; + $password = isset($_POST['password']) ? $_POST['password'] : ''; + $referer = isset($_POST['referer']) ? $_POST['referer'] : '/'; + if (!$name || !$password) { + echo json_encode(['success' => false, 'msg' => '用户名或密码不能为空']); + exit; + } + $user = Typecho_Widget::widget('Widget_User'); + try { + $user->login($name, $password, isset($_POST['remember']) ? 1 : 0); + echo json_encode(['success' => true, 'msg' => '登录成功', 'redirect' => $referer]); + } catch (Typecho_Exception $e) { + echo json_encode(['success' => false, 'msg' => $e->getMessage()]); + } + exit; +} \ No newline at end of file diff --git a/header.php b/header.php index 67cdbbf..b14c3e9 100644 --- a/header.php +++ b/header.php @@ -83,6 +83,15 @@ + user->hasLogin()): ?> +
  • + + 用户中心 + +
  • + +
  • +
  • @@ -130,8 +139,8 @@
  • 分类 - - diff --git a/index.php b/index.php index d03c19b..f45c9ae 100644 --- a/index.php +++ b/index.php @@ -4,7 +4,7 @@ * * @package Typecho Pouck Theme * @author 老孙博客 - * @version 1.1.9 + * @version 1.2.0 * @link http://www.imsun.org */ diff --git a/sidebar.php b/sidebar.php index 728d448..47946f0 100644 --- a/sidebar.php +++ b/sidebar.php @@ -18,57 +18,34 @@ - -getPrefix(); -// 1. 获取uid=1的用户信息 -$user = $db->fetchRow($db->select()->from('table.users')->where('uid = ?', 1)); -$email = $user['mail']; -$nickname = $user['screenName']; -// 获取用户设置的 Gravatar 镜像 -$cnavatar = Helper::options()->cnavatar ? Helper::options()->cnavatar : 'https://cravatar.cn/avatar/'; -$hash = md5($email); -$avatar = rtrim($cnavatar, '/') . '/' . $hash . '?s=80&d=identicon'; -// 2. 获取用户总数 -$userCount = $db->fetchObject($db->select(array('COUNT(*)' => 'num'))->from('table.users'))->num; -// 3. 获取文章总数(只统计 type='post' 且 status='publish') -$postCount = $db->fetchObject($db->select(array('COUNT(*)' => 'num'))->from('table.contents')->where('type = ?', 'post')->where('status = ?', 'publish'))->num; -// 4. 获取评论总数 -$commentCount = $db->fetchObject($db->select(array('COUNT(*)' => 'num'))->from('table.comments'))->num; -// 5. 获取文章浏览总量(累加所有文章的 views 字段) -$totalViews = $db->fetchObject( - $db->select(array('SUM(views)' => 'viewsum'))->from('table.contents')->where('type = ?', 'post') -)->viewsum; -if ($totalViews === null) $totalViews = 0; -?> + + options->sidebarBlock) && in_array('ShowAdmin', $this->options->sidebarBlock)): ?>
    - ' class='lazy avatar' data-src='' > + ' class='lazy avatar' data-src='' >
    -
    +
    options->description(); ?>
    用户数
    -
    +
    文章数
    -
    +
    评论数
    -
    +
    阅读量
    -
    +