删除私信分支链路

This commit is contained in:
2026-08-23 13:42:35 +08:00
parent 1c5c6d86bb
commit c6c2c0af6d
39 changed files with 32 additions and 1465 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ AKSRT-theme/
│ ├── Credits/ # 积分 / 钱包 / 签到 / 邀请
│ ├── Extensions/ # MeiliSearch / 推送 / IP / 内容审核
│ ├── Frontend/ # 前端渲染辅助
│ ├── Messages/ # 站内信 / 私信 / 公告 / 举报
│ ├── Messages/ # 站内信 / 公告 / 举报
│ ├── Payment/ # 订单 / 网关 / 售后 / 物流 / 分成
│ │ └── Gateways/ # 支付宝 / 微信 / PayPal / Stripe
│ ├── Settings/ # 设置门面 + 运行时 delegates
@@ -13,7 +13,6 @@ export const commonSchema = {
lazy_avatar: true,
lazy_posts_content: false,
lazy_comment: true,
lazy_private: true,
lazy_sider: true,
lazy_cover: true,
lazy_other: true,
@@ -52,7 +51,6 @@ export const commonSchema = {
{ key: 'lazy_avatar', label: '头像懒加载', type: 'switch', default: true },
{ key: 'lazy_posts_content', label: '文章内容图片懒加载', type: 'switch', default: false },
{ key: 'lazy_comment', label: '评论内容图片懒加载', type: 'switch', default: true },
{ key: 'lazy_private', label: '私信聊天图片懒加载', type: 'switch', default: true },
{ key: 'lazy_sider', label: '幻灯片图片懒加载', type: 'switch', default: true },
{ key: 'lazy_cover', label: '封面图片懒加载', type: 'switch', default: true },
{ key: 'lazy_other', label: '其它图片懒加载', type: 'switch', default: true },
@@ -7,7 +7,6 @@ export const emailSchema = {
email_footer_text: '',
email_site_branding: true,
email_template_mode: 'plain',
email_private_receive_limit: 'all',
email_reg_verify_link_enabled: true,
email_reg_verify_code_enabled: true,
email_reg_success_enabled: true,
@@ -27,19 +26,6 @@ export const emailSchema = {
{ label: '纯文本', value: 'plain' },
{ label: 'HTML', value: 'html' },
]},
{
key: 'email_private_receive_limit',
label: '私信邮件接收组',
type: 'select',
default: 'all',
options: [
{ label: '所有用户', value: 'all' },
{ label: 'VIP 及以上', value: 'vip' },
{ label: 'VIP2 及以上', value: 'vip2' },
{ label: '仅管理员', value: 'admin' },
],
help: '限制哪些用户组可以收到私信邮件通知',
},
],
},
{
@@ -12,7 +12,6 @@ export const featuresSchema = {
user_cover_img: '',
user_rewrite_slug: 'user',
user_follow_s: true,
user_message_s: true,
user_online_s: true,
user_last_active_s: true,
},
@@ -41,7 +40,6 @@ export const featuresSchema = {
{ key: 'user_cover_img', label: '默认封面', type: 'media', default: '' },
{ key: 'user_rewrite_slug', label: '用户页 slug', type: 'input', default: 'user' },
{ key: 'user_follow_s', label: '启用关注功能', type: 'switch', default: true },
{ key: 'user_message_s', label: '启用私信功能', type: 'switch', default: true },
{ key: 'user_online_s', label: '显示在线状态', type: 'switch', default: true },
{ key: 'user_last_active_s', label: '显示最后活跃', type: 'switch', default: true },
],
@@ -2,7 +2,7 @@ export const notificationsSchema = {
key: 'users.notifications',
title: '消息通知',
icon: 'fa fas fa-bell',
description: '站内通知、私信、通知策略配置。',
description: '站内通知、通知策略配置。',
defaults: {
message_s: true,
msg_center_rewrite_slug: 'message',
@@ -13,15 +13,6 @@ export const notificationsSchema = {
message_auto_clear_s: true,
message_auto_clear_time: 365,
message_auto_clear_types: ['posts', 'comment', 'favorite', 'like', 'hot', 'followed', 'system'],
private_s: true,
private_smilie_s: true,
private_code_s: false,
private_image_s: true,
private_upload_img: false,
private_quick_s: true,
private_quick_often: '你好,请问有什么可以帮你的?\n感谢你的反馈\n已处理,请查收',
private_submit_text: '发送',
private_placeholder: '请输入消息...',
},
groups: [
{
@@ -51,23 +42,7 @@ export const notificationsSchema = {
fields: [
{ key: 'message_auto_clear_s', label: '自动清理已读消息', type: 'switch', default: true },
{ key: 'message_auto_clear_time', label: '过期天数', type: 'number', default: 365, min: 1, max: 3650, help: '已读消息超过此天数将被自动清理', dependsOn: { key: 'message_auto_clear_s', value: true } },
{ key: 'message_auto_clear_types', label: '清理类型', type: 'checkbox', default: ['posts', 'comment', 'favorite', 'like', 'hot', 'followed', 'system'], options: [{ label: '文章通知', value: 'posts' }, { label: '评论回复', value: 'comment' }, { label: '收藏通知', value: 'favorite' }, { label: '点赞通知', value: 'like' }, { label: '热门通知', value: 'hot' }, { label: '关注通知', value: 'followed' }, { label: '系统通知', value: 'system' }, { label: '支付通知', value: 'pay' }, { label: '提现回复', value: 'withdraw_reply' }, { label: '勋章通知', value: 'medal' }, { label: '认证回复', value: 'auth_apply_reply' }, { label: '下载通知', value: 'download' }, { label: '积分变动', value: 'credits' }, { label: '私信', value: 'private' }, { label: '举报反馈', value: 'report' }], dependsOn: { key: 'message_auto_clear_s', value: true } },
],
},
{
key: 'private',
title: '私信设置',
icon: 'fa fas fa-envelope',
fields: [
{ key: 'private_s', label: '启用私信功能', type: 'switch', default: true },
{ key: 'private_smilie_s', label: '支持表情', type: 'switch', default: true, dependsOn: { key: 'private_s', value: true } },
{ key: 'private_code_s', label: '支持代码', type: 'switch', default: false, dependsOn: { key: 'private_s', value: true } },
{ key: 'private_image_s', label: '支持图片', type: 'switch', default: true, dependsOn: { key: 'private_s', value: true } },
{ key: 'private_upload_img', label: '支持上传图片', type: 'switch', default: false, dependsOn: { key: 'private_s', value: true } },
{ key: 'private_quick_s', label: '快捷回复', type: 'switch', default: true, dependsOn: { key: 'private_s', value: true } },
{ key: 'private_quick_often', label: '常用快捷回复', type: 'textarea', default: '你好,请问有什么可以帮你的?\n感谢你的反馈\n已处理,请查收', help: '一行一条快捷回复文案', dependsOn: { key: 'private_s', value: true } },
{ key: 'private_submit_text', label: '发送按钮文案', type: 'input', default: '发送', dependsOn: { key: 'private_s', value: true } },
{ key: 'private_placeholder', label: '输入占位符', type: 'input', default: '请输入消息...', dependsOn: { key: 'private_s', value: true } },
{ key: 'message_auto_clear_types', label: '清理类型', type: 'checkbox', default: ['posts', 'comment', 'favorite', 'like', 'hot', 'followed', 'system'], options: [{ label: '文章通知', value: 'posts' }, { label: '评论回复', value: 'comment' }, { label: '收藏通知', value: 'favorite' }, { label: '点赞通知', value: 'like' }, { label: '热门通知', value: 'hot' }, { label: '关注通知', value: 'followed' }, { label: '系统通知', value: 'system' }, { label: '支付通知', value: 'pay' }, { label: '提现回复', value: 'withdraw_reply' }, { label: '勋章通知', value: 'medal' }, { label: '认证回复', value: 'auth_apply_reply' }, { label: '下载通知', value: 'download' }, { label: '积分变动', value: 'credits' }, { label: '举报反馈', value: 'report' }], dependsOn: { key: 'message_auto_clear_s', value: true } },
],
},
],
-216
View File
@@ -369,217 +369,6 @@ html.dark .messages-nav__actions {
border-top-color: var(--color-line);
}
/* ============================================================
* Private Messages / Conversations
* ============================================================ */
.aksrt-pm__list {
display: flex;
flex-direction: column;
}
.aksrt-pm__item {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
cursor: pointer;
border-bottom: 1px solid var(--color-line, #f0f0f0);
transition: background 0.15s;
}
.aksrt-pm__item:hover {
background: var(--surface-1, #f8f9fa);
}
.aksrt-pm__item.is-unread {
background: var(--surface-2, #f0f5ff);
}
.aksrt-pm__avatar {
width: 44px;
height: 44px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
}
.aksrt-pm__info {
flex: 1;
min-width: 0;
}
.aksrt-pm__name {
font-size: 14px;
font-weight: 500;
color: var(--color-ink);
display: flex;
align-items: center;
gap: 8px;
}
.aksrt-pm__badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
border-radius: 9px;
background: var(--color-primary);
color: #fff;
font-size: 11px;
font-weight: 600;
padding: 0 5px;
}
.aksrt-pm__preview {
font-size: 12px;
color: var(--text-secondary, #8a909c);
margin-top: 3px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.aksrt-pm__time {
font-size: 11px;
color: var(--text-tertiary, #c0c4cc);
flex-shrink: 0;
}
/* Thread view */
.aksrt-pm__thread {
display: flex;
flex-direction: column;
height: 100%;
min-height: 400px;
}
.aksrt-pm__thread-header {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
border-bottom: 1px solid var(--color-line, #f0f0f0);
}
.aksrt-pm__back-btn {
background: none;
border: none;
color: var(--color-primary);
cursor: pointer;
font-size: 13px;
padding: 4px 8px;
border-radius: 4px;
}
.aksrt-pm__back-btn:hover {
background: var(--surface-1, #f0f5ff);
}
.aksrt-pm__thread-name {
font-size: 15px;
font-weight: 600;
color: var(--color-ink);
}
.aksrt-pm__messages {
flex: 1;
overflow-y: auto;
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
.aksrt-pm__msg {
display: flex;
max-width: 75%;
}
.aksrt-pm__msg--mine {
align-self: flex-end;
}
.aksrt-pm__msg--mine .aksrt-pm__msg-bubble {
background: var(--color-primary);
color: #fff;
border-radius: 12px 12px 4px 12px;
}
.aksrt-pm__msg:not(.aksrt-pm__msg--mine) .aksrt-pm__msg-bubble {
background: var(--surface-2, #f0f0f0);
color: var(--color-ink);
border-radius: 12px 12px 12px 4px;
}
.aksrt-pm__msg-bubble {
padding: 10px 14px;
font-size: 14px;
line-height: 1.5;
word-break: break-word;
}
.aksrt-pm__msg-time {
font-size: 11px;
margin-top: 4px;
opacity: 0.6;
}
.aksrt-pm__compose {
display: flex;
align-items: flex-end;
gap: 8px;
padding: 12px 16px;
border-top: 1px solid var(--color-line, #f0f0f0);
}
.aksrt-pm__compose textarea {
flex: 1;
border: 1px solid var(--color-line, #d9d9d9);
border-radius: 8px;
padding: 8px 12px;
font-size: 14px;
resize: none;
outline: none;
font-family: inherit;
}
.aksrt-pm__compose textarea:focus {
border-color: var(--color-primary);
}
.aksrt-pm__send-btn {
width: 40px;
height: 40px;
border-radius: 50%;
border: none;
background: var(--color-primary);
color: #fff;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: opacity 0.15s;
}
.aksrt-pm__send-btn:hover {
opacity: 0.85;
}
/* Dark mode */
html.dark .aksrt-pm__item:hover,
html.dark .aksrt-pm__item:hover {
background: var(--surface-2);
}
html.dark .aksrt-pm__item.is-unread,
html.dark .aksrt-pm__item.is-unread {
background: rgba(240, 68, 148, 0.08);
}
/* Page header */
.messages-center__header {
margin: 8px 0 16px;
@@ -601,11 +390,6 @@ html.dark .aksrt-pm__item.is-unread {
min-height: 40vh;
}
/* PM thread uses hidden attribute instead of inline style */
.aksrt-pm__thread[hidden] {
display: none !important;
}
.message-item__new-badge {
display: inline-block;
margin-left: 6px;
+3 -119
View File
@@ -8899,7 +8899,6 @@ body.modal-open .float-btn.wait-pay-btn .hover-show-con {
/**----文章内容------*/
.msg-content a:not([class]),
.private-content a:not([class]),
.comment-content a:not([class]),
.wp-posts-content a:not([class]) {
color: var(--focus-color);
@@ -9656,7 +9655,6 @@ img.alignleft {
margin: 20px 0;
}
.chat-next a,
.theme-pagination .ajax-next a,
.theme-pagination .order-ajax-next a {
border-radius: 30px;
@@ -9665,14 +9663,12 @@ img.alignleft {
opacity: 0.6;
}
.chat-next a:hover,
.theme-pagination .ajax-next a:hover,
.theme-pagination .order-ajax-next a:hover {
background: var(--main-border-color);
opacity: 1;
}
.chat-next a .fa,
.theme-pagination .ajax-next .fa,
.theme-pagination .ajax-next .icon,
.theme-pagination .order-ajax-next .fa,
@@ -9681,7 +9677,6 @@ img.alignleft {
transition: 0.3s;
}
.chat-next a:hover .fa,
.theme-pagination .ajax-next a:hover .fa,
.theme-pagination .ajax-next a:hover .icon,
.theme-pagination .order-ajax-next a:hover .fa,
@@ -10402,15 +10397,6 @@ img.alignleft {
transform: translate(-24px, -7px) scale(0.8);
}
.chat-lists badge {
transform: translate(-7px, -7px);
}
.private-item .avatar,
.chat-lists .avatar {
border-radius: 4px;
}
.msg-content {
line-height: 2;
white-space: pre-wrap;
@@ -10422,60 +10408,6 @@ img.alignleft {
margin-top: -2px;
}
/*--------消息中心-私信------*/
.chat-lists .msg-list > li + li {
width: calc(100% - 47px);
}
.private-window-header .avatar-img {
--this-size: 20px;
vertical-align: 1px;
}
.private-window-content {
height: 400px;
background: var(--muted-bg-color);
box-shadow: none;
border-radius: 4px;
padding: 15px 10px;
}
.private-list {
margin: 10px 0;
}
.private-list .avatar-img {
width: 32px;
height: 32px;
}
.private-list.right {
text-align: right;
}
.private-list.left .avatar-img {
float: left;
}
.private-list.right .avatar-img {
float: right;
}
.private-content {
max-width: calc(80% - 60px);
display: inline-block;
word-wrap: break-word;
white-space: pre-wrap;
padding: 6px 10px;
border-radius: 4px;
margin: 0 8px;
position: relative;
text-align: left;
min-height: 32px;
min-width: 32px;
}
.private-content::before,
.dropdown-menu::before {
content: ' ';
display: inline-block;
@@ -10489,21 +10421,6 @@ img.alignleft {
border-radius: 2px;
}
.private-content .readed-badge {
position: absolute;
font-size: 12px;
right: 100%;
top: 8px;
width: 2.5em;
transform: scale(0.9);
color: #2997f7;
}
.private-list.right .private-content::before {
left: auto;
right: -4px;
}
.dropdown .dropdown-menu::before {
top: -4px;
left: 12px;
@@ -10525,32 +10442,10 @@ img.alignleft {
left: 50%;
}
.private-next,
.chat-next {
display: block;
padding: 10px 0;
text-align: center;
opacity: 0.8;
}
.comment-content pre,
.private-content pre {
.comment-content pre {
padding: 0;
}
.private-content > pre:last-of-type {
margin-bottom: 0 !important;
}
.private-content .enlighter-default {
margin: 0;
min-width: 150px;
}
.modal-body .private-window .visible-xs-block {
display: none !important;
}
/*-------404页面-------*/
body.error404 {
background: var(--main-bg-color);
@@ -12259,16 +12154,7 @@ body.error404 {
top: 5px;
}
/***---私信---***/
.msg-private > .ajaxpager {
opacity: 1;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
}
.link-nav-submit,
.msg-private.toggle #user_chat_lists,
.msg-private:not(.toggle) #user_private_window {
.link-nav-submit {
display: none;
opacity: 0;
}
@@ -12490,9 +12376,7 @@ body.error404 {
}
.comt-tips-left .but svg,
.from-private .but svg,
.comt-tips-left .but .fa,
.from-private .but .fa {
.comt-tips-left .but .fa {
margin: 0;
}
+1 -1
View File
File diff suppressed because one or more lines are too long
-86
View File
@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
t="1605107863868"
viewBox="0 0 1024 1024"
version="1.1"
id="svg847"
sodipodi:docname="msg-private.svg"
inkscape:version="1.0.2 (e86c8708, 2021-01-15)">
<metadata
id="metadata853">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs851" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="965"
id="namedview849"
showgrid="false"
inkscape:zoom="0.34472656"
inkscape:cx="-149.38185"
inkscape:cy="435.25787"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="svg847" />
<path
d="M204.8 0h614.4Q1024 0 1024 204.8v614.4q0 204.8-204.8 204.8H204.8Q0 1024 0 819.2V204.8Q0 0 204.8 0z"
fill="#95EFC2"
p-id="52371"
id="path833" />
<path
d="M819.2 0H534.272A756.48 756.48 0 0 0 0 483.584V819.2A204.8 204.8 0 0 0 204.8 1024h614.4A204.8 204.8 0 0 0 1024 819.2V204.8A204.8 204.8 0 0 0 819.2 0z"
fill="#88EDBF"
p-id="52372"
id="path835" />
<path
d="M819.2 0h-3.84a755.2 755.2 0 0 0-539.392 1024H819.2A204.8 204.8 0 0 0 1024 819.2V204.8A204.8 204.8 0 0 0 819.2 0z"
fill="#79E8B8"
p-id="52373"
id="path837" />
<path
d="M497.152 721.152A752.384 752.384 0 0 0 560.384 1024H819.2A204.8 204.8 0 0 0 1024 819.2V204.8a204.8 204.8 0 0 0-89.088-168.96 755.2 755.2 0 0 0-437.76 685.312z"
fill="#69E2B3"
p-id="52374"
id="path839" />
<path
d="M 525.07404,242.51105 A 276.72086,275.29065 0 0 0 340.59346,722.66383 v 47.48763 a 23.060072,22.940888 0 0 0 23.06008,22.94089 h 161.4205 a 276.72086,275.29065 0 0 0 0,-550.5813 z"
fill="#d7ffe9"
p-id="52375"
id="path841"
style="stroke-width:0.898453" />
<path
d="M 732.61469,517.8017 A 276.72086,275.29065 0 0 0 490.48394,244.80514 276.72086,275.29065 0 0 0 340.59346,722.66383 v 47.48763 a 23.060072,22.940888 0 0 0 23.06008,22.94089 h 92.24028 A 276.72086,275.29065 0 0 0 732.61469,517.8017 Z"
fill="#ffffff"
p-id="52376"
id="path843"
style="stroke-width:0.898453" />
<path
d="M512 473.6q25.6 0 25.6 25.6v25.6q0 25.6-25.6 25.6t-25.6-25.6v-25.6q0-25.6 25.6-25.6zM409.6 473.6q25.6 0 25.6 25.6v25.6q0 25.6-25.6 25.6T384 524.8v-25.6q0-25.6 25.6-25.6zM614.4 473.6q25.6 0 25.6 25.6v25.6q0 25.6-25.6 25.6t-25.6-25.6v-25.6q0-25.6 25.6-25.6z"
fill="#79E8B8"
p-id="52377"
id="path845" />
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

-125
View File
@@ -1,125 +0,0 @@
/**
* AKSRT Conversation — 私信会话交互
*
* 从 page-messages.php 内联脚本提取而来。
* 处理会话列表点击、消息加载、发送、已读标记。
*
* @package AKSRT
*/
(function () {
'use strict';
var wrap = document.getElementById('aksrt-pm-conversations');
if (!wrap) return;
var ajaxUrl = wrap.getAttribute('data-ajax');
var nonce = wrap.getAttribute('data-nonce');
var listView = wrap;
var threadView = document.getElementById('aksrt-pm-thread');
var messagesEl = document.getElementById('aksrt-pm-messages');
var threadName = document.getElementById('aksrt-pm-thread-name');
var input = document.getElementById('aksrt-pm-input');
var sendBtn = document.getElementById('aksrt-pm-send');
var backBtn = document.getElementById('aksrt-pm-back');
var currentConv = 0;
var currentOther = 0;
function post(action, data) {
var fd = new FormData();
fd.append('action', action);
fd.append('_nonce', nonce);
if (data) {
for (var key in data) {
if (data.hasOwnProperty(key)) {
fd.append(key, data[key]);
}
}
}
return fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' })
.then(function (r) { return r.json(); });
}
// Click conversation item → load thread
document.addEventListener('click', function (e) {
var item = e.target.closest('.aksrt-pm__item');
if (!item) return;
currentConv = parseInt(item.getAttribute('data-conv-id'));
currentOther = parseInt(item.getAttribute('data-other-id'));
var nm = item.querySelector('.aksrt-pm__name');
if (nm) {
threadName.textContent = nm.textContent.replace(/\d+$/, '').trim();
}
loadThread(currentConv, 1);
});
// Back button
if (backBtn) {
backBtn.addEventListener('click', function () {
threadView.hidden = true;
listView.style.display = '';
});
}
// Send message
if (sendBtn) {
sendBtn.addEventListener('click', function () {
var content = input.value.trim();
if (!content || !currentConv) return;
post('aksrt_pm_send', {
conversation_id: currentConv,
recipient_id: currentOther,
content: content,
}).then(function (d) {
if (d.success) {
input.value = '';
loadThread(currentConv, 1);
}
});
});
}
// Enter to send (Shift+Enter for newline)
if (input) {
input.addEventListener('keydown', function (e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendBtn.click();
}
});
}
function loadThread(convId, page) {
post('aksrt_pm_thread', {
conversation_id: convId,
page: page,
}).then(function (d) {
if (d.success && d.data) {
renderMessages(d.data.messages || []);
listView.hidden = true;
threadView.style.display = '';
// Mark as read
post('aksrt_pm_mark_read', { conversation_id: convId });
}
});
}
function renderMessages(msgs) {
messagesEl.innerHTML = '';
msgs.forEach(function (m) {
var div = document.createElement('div');
div.className = 'aksrt-pm__msg' + (m.is_mine ? ' aksrt-pm__msg--mine' : '');
div.innerHTML =
'<div class="aksrt-pm__msg-bubble">' +
'<div class="aksrt-pm__msg-content">' + (m.content || '').replace(/</g, '&lt;') + '</div>' +
'<div class="aksrt-pm__msg-time">' + (m.created_at || '') + '</div>' +
'</div>';
messagesEl.appendChild(div);
});
messagesEl.scrollTop = messagesEl.scrollHeight;
}
})();
-1
View File
@@ -70,7 +70,6 @@ tbquire.config({
'page-edit' : 'page-edit.min',
'author' : 'author.min',
'page-navs' : 'page-navs.min',
'message' : 'message.min',
'input-expand' : 'input-expand.min',
'mini-touch' : 'mini-touch.min',
'mini-upload' : 'mini-upload.min',
-5
View File
@@ -2445,11 +2445,6 @@ function z_auto_fun() {
});
*/
//消息功能
$('.from-private,.msg-center').length &&
tbquire(['message'], function () {
scroll_down();
});
$('.dropdown-smilie,.dropdown-code,.dropdown-image,.dropdown-quick-often').length && tbquire(['input-expand']);
/**上传图片 */
$('[aksrtupload]').length && tbquire(['mini-upload']);
+1 -1
View File
File diff suppressed because one or more lines are too long
-97
View File
@@ -1,97 +0,0 @@
_win.bd.on('click', '[ajax-target="#user_private_window"]', function () {
_win.private_no_scroll = false;
});
/**消息列表滚动到最底部 */
function scroll_down() {
var $e = $('.private-window-content');
if ($e.length && !_win.private_no_scroll) {
var _top = $e.prop('scrollHeight');
_win.private_no_scroll = true;
$e.animate(
{
scrollTop: _top,
},
300,
'swing'
);
}
}
/**ctrl+回车键提交 */
_win.bd.on('keydown', '#receive', function (e) {
var keycode = e.which || e.keyCode;
if ((e.metaKey || e.ctrlKey) && keycode == 13) {
$(this).parents('.from-private').find('.send-private').click();
}
});
/**发送私信 */
_win.bd.on('click', '.send-private', function () {
var _this = $(this);
aksrt_ajax(_this, 0, function (n) {
if (n.html) {
var _par = _this.parents('.private-window');
_par.find('.private-window-content').append(n.html);
_par.find('textarea').val('');
_win.private_no_scroll = false;
auto_fun();
}
});
return !1;
});
/**消息内容翻页 */
_win.bd.on('click', '.private-next', function () {
var _loader = '<div class="text-center padding-h10 px12"><i class="loading"></i><div>';
post_ajax($(this).attr('no-scroll', true), '.private-window-content', '.private-window-content', '.private-item', _loader, '.private-pag', '.private-next', 'private-next px12', !1, '<span class="px12">' + aksrt__('message_all_loaded') + '</span>', !0, '<i class="fa fas fa-angle-up mr10"></i>' + aksrt__('message_load_more'));
return !1;
});
/*对话列表翻页 */
_win.bd.on('click', '.chat-next', function () {
post_ajax($(this), '#user_chat_lists', '#user_chat_lists', '.chat-lists', '', '.chat-pag', '.chat-next');
return !1;
});
/**切换加入黑名单
* 清空聊天记录
* 全部标为已读
*/
_win.bd.on('click', '.ajax-blacklist,.ajax-clear-msg,.ajax-readed', function () {
var _this = $(this);
var $text = _this.text();
if (confirm(aksrt_sprintf('confirm_action', $text)) == 1) {
aksrt_ajax(_this, 0, function (n) {
if (n.text) {
_this.find('text').text(n.text);
}
});
}
return !1;
});
/*删除new标签 */
_win.bd.on('click', '[ajax-target="#user_private_window"],[ajax-tab="#user_msg_content"]', function () {
$(this).find('.avatar-img badge,.msg-img badge').remove();
});
_win.bd.on('post_ajax.ed', '#user_msg_content,#user_private_window', function (e, c) {
var _new_count = $(c).find('[msg-new-count-obj]');
if (!_new_count.length) {
return;
}
var counts = $.parseJSON(_new_count.attr('msg-new-count-obj'));
$.each(counts, function (e, count) {
var _badge = $('badge[msg-cat="' + e + '"]');
if (_badge.length) {
if (count > 0) {
_badge.html(count);
} else {
_badge.remove();
}
}
});
});
-1
View File
@@ -1 +0,0 @@
function scroll_down(){var t=$(".private-window-content");if(t.length&&!_win.private_no_scroll){var n=t.prop("scrollHeight");_win.private_no_scroll=!0,t.animate({scrollTop:n},300,"swing")}}_win.bd.on("click",'[ajax-target="#user_private_window"]',function(){_win.private_no_scroll=!1}),_win.bd.on("keydown","#receive",function(t){var n=t.which||t.keyCode;(t.metaKey||t.ctrlKey)&&13==n&&$(this).parents(".from-private").find(".send-private").click()}),_win.bd.on("click",".send-private",function(){var t=$(this);return aksrt_ajax(t,0,function(n){if(n.html){var a=t.parents(".private-window");a.find(".private-window-content").append(n.html),a.find("textarea").val(""),_win.private_no_scroll=!1,auto_fun()}}),!1}),_win.bd.on("click",".private-next",function(){var t='<div class="text-center padding-h10 px12"><i class="loading"></i><div>';return post_ajax($(this).attr("no-scroll",!0),".private-window-content",".private-window-content",".private-item",t,".private-pag",".private-next","private-next px12",!1,'<span class="px12">'+aksrt__("message_all_loaded")+"</span>",!0,'<i class="fa fas fa-angle-up mr10"></i>'+aksrt__("message_load_more")),!1}),_win.bd.on("click",".chat-next",function(){return post_ajax($(this),"#user_chat_lists","#user_chat_lists",".chat-lists","",".chat-pag",".chat-next"),!1}),_win.bd.on("click",".ajax-blacklist,.ajax-clear-msg,.ajax-readed",function(){var t=$(this),n=t.text();return 1==confirm(aksrt_sprintf("confirm_action",n))&&aksrt_ajax(t,0,function(n){n.text&&t.find("text").text(n.text)}),!1}),_win.bd.on("click",'[ajax-target="#user_private_window"],[ajax-tab="#user_msg_content"]',function(){$(this).find(".avatar-img badge,.msg-img badge").remove()}),_win.bd.on("post_ajax.ed","#user_msg_content,#user_private_window",function(t,n){var a=$(n).find("[msg-new-count-obj]");if(a.length){var i=$.parseJSON(a.attr("msg-new-count-obj"));$.each(i,function(t,n){var a=$('badge[msg-cat="'+t+'"]');a.length&&(n>0?a.html(n):a.remove())})}});
-1
View File
@@ -39,7 +39,6 @@ aksrt_svgs['alipay'] = '<path d="M653.80568 617.306394c70.196759-127.645169 95.7
aksrt_svgs['baidu'] = '<path d="M412.54 94.74c13.82-2.69 28.21 0.67 40.52 7.13 18.32 10.72 32.2 27.86 41.03 46.99 18.82 40.57 19.04 88.91 2.38 130.23-7.83 18.05-19.17 35.23-35.44 46.7-14.17 10.44-32.65 15.51-50.08 12.14-14.7-2.84-28.09-10.75-38.4-21.51-16.41-16.26-26.44-37.85-32.21-59.97-7.82-32.14-6.07-66.64 5.6-97.63 7.58-20.05 19.98-38.77 37.36-51.6 8.68-6.21 18.62-10.89 29.24-12.48zM642.54 112.74c14.09-3.24 28.43 1.98 40.47 9.09 12.5 7.77 23.39 18.14 31.82 30.2 13.27 17.99 21.69 39.65 23.54 61.95 1.2 20.12-4.42 39.95-11.88 58.44-8.6 20.17-20.6 39.39-37.41 53.73-11.2 9.99-25.06 17.06-39.91 19.51-15.25 2.42-31.08 0-45.41-5.48-16.19-6.35-29.7-18.93-37.51-34.43-9.97-19.57-12.73-42-12.38-63.72 0.38-12.08 1-24.34 4.57-35.97 5.44-18.49 15.28-35.39 26.82-50.71 9.67-12.59 21.15-23.86 34.29-32.81 7.03-4.53 14.79-8.01 22.99-9.8zM228.55 276.76c14.19-2.87 29.11-0.38 42.36 5.14 27.56 12.82 48.47 37.44 59.87 65.31 4.69 11.29 5.89 23.58 6.5 35.67 1.23 21.99-0.51 44.34-7.05 65.44-5.65 17.81-15.84 34.6-30.88 46-15.06 11.23-33.63 17.35-52.32 18.33-20.48 1.2-41.53-6-56.36-20.3-14.41-13.11-24.12-30.65-30.28-48.96-6.19-18.39-9.2-38.17-6.38-57.49 3.11-23.27 9.52-46.34 20.89-66.98 5.74-10.16 12.93-19.57 21.82-27.18 9.15-7.51 20.19-12.76 31.83-14.98zM773.09 335.14c16.95-1.24 34.45 1.2 49.77 8.79 16.02 7.8 28.92 21.02 38.19 36.07 10.21 17.52 16.89 37.52 16.85 57.94 0.51 21.72 0.12 43.77-5.45 64.91-4.39 15.87-11.71 31.45-23.77 42.96-14.07 13.2-33.49 19.59-52.57 19.96-19.19 0.57-39.12-0.89-56.7-9.27-17.16-7.33-30.5-22.16-37.31-39.39-7.85-19.67-9.44-41.14-9.35-62.12-0.01-24.34 2.7-49.22 12.47-71.74 6.11-13.99 15.56-26.85 28.47-35.25 11.5-8.11 25.55-11.68 39.4-12.86zM499.58 415.76c19.31-2.26 39.11 0.99 56.87 8.84 27.51 12.15 49.18 34.47 65.89 59.02 21.56 32.4 47.59 61.52 74.73 89.3 23.38 23.32 47.52 45.93 72.92 67.05 5.74 4.96 11.94 9.4 17.25 14.85 18.04 18.41 29.75 42.69 33.91 68.05 5.31 31.4-1.18 63.71-13.33 92.79-8.36 21.32-23.98 39.76-43.85 51.21-21.13 12.43-45.72 17.37-69.93 18.95-34.13 1.93-68.29-3.36-101.12-12.43-41.83-13.18-86.85-16.16-130.03-8.51-21.43 4.49-42.94 8.86-64.77 10.85-26.62 2.82-53.48 3.1-80.2 1.62-19.06-0.37-38.15-5.73-54.21-16.1-17.72-10.45-31.47-26.56-41.39-44.4-8.27-15.27-13.79-31.93-17.34-48.89-5.11-24.73-3.54-50.94 5.59-74.56 12.72-33.67 37.73-61.18 65.64-83.21 6.93-5.78 14.54-10.69 21.4-16.56 14.15-13.89 29.74-26.2 43.84-40.14 21.96-21.36 42.44-44.56 58.28-70.89 20.78-35.88 58.42-62.08 99.85-66.84z"></path>';
aksrt_svgs['gitee'] = '<path d="M978.5 409.6H455.1c-25.1 0-45.5 20.3-45.5 45.5v113.7c0 25.1 20.3 45.5 45.5 45.5h318.6c25.1 0 45.5 20.4 45.5 45.5v22.6c0 75.4-61.2 136.5-136.5 136.5H250.3c-25.1 0-45.5-20.4-45.5-45.5V341.2c0-75.5 61.2-136.5 136.5-136.5h637c25.1 0 45.5-20.3 45.5-45.5l0.1-113.6c0-25.1-20.3-45.5-45.5-45.5H341.3C152.9 0 0 152.9 0 341.3v637.2c0 25.1 20.4 45.5 45.5 45.5h671.3c169.6 0 307.2-137.5 307.2-307.2V455.1c0-25.1-20.4-45.5-45.5-45.5z"></path>';
aksrt_svgs['comment-fill'] = '<path d="M512 115.6c-249.9 0-448.5 174-448.5 386.7 0 58 19.2 116 44.9 167.6l44.9 238.5L371 869.7c44.9 12.9 89.7 19.3 141 19.3 249.9 0 448.5-174 448.5-386.7 0-212.6-198.6-386.7-448.5-386.7zM255.7 437.9c38.4 0 64.1 25.8 64.1 64.4 0 38.7-25.6 64.4-64.1 64.4-38.4 0-64.1-25.8-64.1-64.4 0-38.6 25.7-64.4 64.1-64.4zM512 566.8c-38.4 0-64.1-25.8-64.1-64.4 0-38.7 25.6-64.4 64.1-64.4 38.4 0 64.1 25.8 64.1 64.4 0 38.6-25.7 64.4-64.1 64.4z m256.3 0c-38.4 0-64.1-25.8-64.1-64.4 0-38.7 25.6-64.4 64.1-64.4 38.4 0 64.1 25.8 64.1 64.4 0 38.6-25.7 64.4-64.1 64.4z"></path>';
aksrt_svgs['private'] = '<path d="M469.942857 512c0 25.6 19.2 51.2 51.2 51.2 25.6 0 51.2-19.2 51.2-51.2 0-25.6-19.2-51.2-51.2-51.2-25.6 0-51.2 25.6-51.2 51.2z m204.8 0c0 25.6 19.2 51.2 51.2 51.2s51.2-19.2 51.2-51.2c0-25.6-19.2-51.2-51.2-51.2s-51.2 25.6-51.2 51.2zM271.542857 512c0 25.6 19.2 51.2 51.2 51.2s44.8-25.6 44.8-51.2-19.2-51.2-51.2-51.2-44.8 25.6-44.8 51.2z m665.6-172.8c-25.6-57.6-57.6-102.4-96-147.2-38.4-38.4-89.6-76.8-140.8-96C642.742857 76.8 578.742857 64 521.142857 64 457.142857 64 399.542857 76.8 341.942857 102.4c-51.2 19.2-96 51.2-140.8 96S130.742857 288 105.142857 339.2C85.942857 396.8 73.142857 454.4 73.142857 512c0 70.4 19.2 140.8 51.2 198.4v153.6c0 25.6 19.2 44.8 44.8 44.8h153.6c64 32 128 44.8 198.4 51.2 57.6 0 115.2-12.8 172.8-32 51.2-19.2 102.4-51.2 140.8-96 38.4-38.4 76.8-89.6 96-140.8 25.6-57.6 38.4-115.2 38.4-179.2 0-57.6-12.8-115.2-32-172.8z m-153.6 435.2C713.142857 844.8 617.142857 883.2 521.142857 883.2c-57.6 0-121.6-12.8-172.8-44.8l-6.4-6.4H194.742857V691.2l-6.4-6.4C162.742857 633.6 149.942857 576 149.942857 512c0-102.4 38.4-192 108.8-262.4C329.142857 179.2 418.742857 140.8 521.142857 140.8c51.2 0 96 12.8 147.2 32 44.8 19.2 83.2 44.8 121.6 76.8 32 32 64 76.8 76.8 121.6 19.2 44.8 32 96 32 147.2-6.4 96-44.8 185.6-115.2 256z"></path>';
aksrt_svgs['hot-fill'] = '<path d="M921.053465 625.705187c0 230.830879-173.604142 398.335748-412.826638 398.335748C270.846393 1024.040935 102.44096 856.495131 102.44096 625.705187c0-122.558548 72.208844-254.573016 75.278948-260.058268a31.519733 31.519733 0 0 1 31.437864-16.128279c12.730698 1.678323 23.169051 11.052374 26.443828 23.619332 0.163739 0.77776 19.60773 74.828666 45.314734 116.049928 17.233517 27.630935 34.753576 47.197731 54.443176 60.788057-13.344718-58.782256-23.537463-147.119379-6.917968-237.789781C374.042819 63.262152 566.599736 3.743071 574.827614 1.327922a30.578235 30.578235 0 0 1 29.964214 7.204511 32.256558 32.256558 0 0 1 9.660594 29.636736c-0.327478 1.801128-32.092819 176.01929 35.367597 324.489515 6.099273 13.508457 14.613695 29.227389 23.864941 44.864452 2.578887-21.531662 6.672359-44.373235 12.894436-66.600787 24.765505-88.091515 88.74647-118.178533 91.448162-119.406575a31.31506 31.31506 0 0 1 32.338428 4.011603c9.210312 7.368249 13.631261 19.321187 11.54359 31.028516-0.327478 2.16954-9.292181 62.138903 40.852849 147.160314 45.232864 76.752598 58.291039 126.57015 58.29104 221.98898z"></path>';
aksrt_svgs['hot'] = '<path d="M429.568429 1023.994675S87.04221 973.306939 87.04221 681.468456c0-291.838482 447.485673-319.486339 348.670187-681.468456 0 0 335.358256 104.959454 253.438682 431.613756 0 0 44.543768-28.159854 78.335592-83.455566 0 0 169.471119 131.071318 169.471119 330.75028 0 199.678962-235.006778 346.1102-346.622197 345.086205 0 0 120.319374-162.303156 10.751944-267.26261-155.135193-148.479228-89.087537-244.22273-89.087537-244.22273S133.633968 697.852371 429.568429 1023.994675"></path>';
aksrt_svgs['topping'] = '<path d="M256 51.2h512a51.2 51.2 0 0 1 0 102.4H256a51.2 51.2 0 1 1 0-102.4z"></path><path d="M876.4928 432.9984l-234.1888-193.1264a204.8 204.8 0 0 0-260.608 0L147.456 432.9984A102.4 102.4 0 0 0 212.6848 614.4H307.2v153.6a204.8 204.8 0 1 0 409.6 0v-153.6h94.5152a102.4 102.4 0 0 0 65.1776-181.4016z m-302.336-108.2368L819.2 512h-102.4a102.4 102.4 0 0 0-102.4 102.4v153.6a102.4 102.4 0 1 1-204.8 0v-153.6a102.4 102.4 0 0 0-102.4-102.4H204.8l245.0432-187.2384a102.4 102.4 0 0 1 124.3136 0z"></path>';
-3
View File
@@ -249,9 +249,6 @@ if (class_exists('\AKSRT\Payment\WeChatNotify')) {
if (class_exists('\AKSRT\Messages\Message')) {
\AKSRT\Messages\Message::get_instance()->init();
}
if (class_exists('\AKSRT\Messages\PrivateMessage')) {
\AKSRT\Messages\PrivateMessage::get_instance()->init();
}
if (class_exists('\AKSRT\Messages\ReportCenter')) {
\AKSRT\Messages\ReportCenter::get_instance()->init();
}
+3 -10
View File
@@ -396,8 +396,6 @@ if (!function_exists('aksrt_single_render_author_card')) :
}
$is_self = is_user_logged_in() && get_current_user_id() === $author_id;
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
$aksrt_pm_on = class_exists('\AKSRT\Settings\Settings') && !empty(\AKSRT\Settings\Settings::private_message_settings()['enabled']);
$aksrt_msg_url = function_exists('aksrt_get_messages_page_url') ? aksrt_get_messages_page_url() : '';
$aksrt_post_settings = class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_post_page_settings')
? \AKSRT\Settings\Settings::get_post_page_settings()
: [];
@@ -448,14 +446,9 @@ if (!function_exists('aksrt_single_render_author_card')) :
<a href="<?php echo esc_url($login_url); ?>" class="but pw-1em mr6 c-red follow">
<i class="fa fas fa-heart em09" aria-hidden="true"></i> <span><?php esc_html_e('关注', 'aksrt'); ?></span>
</a>
<?php endif; ?>
<?php if (is_user_logged_in() && $aksrt_pm_on && $aksrt_msg_url !== '') : ?>
<a class="but pw-1em mr6 c-blue" href="<?php echo esc_url(add_query_arg('msg_type', 'conversation', $aksrt_msg_url)); ?>">
<i class="fa fas fa-comment em09" aria-hidden="true"></i> <?php esc_html_e('私信', 'aksrt'); ?>
</a>
<?php endif; ?>
<?php
$tip = function_exists('aksrt_get_rewards_button') ? aksrt_get_rewards_button($author_id, 'but pw-1em mr6 c-yellow', get_the_ID()) : '';
<?php endif; ?>
<?php
$tip = function_exists('aksrt_get_rewards_button') ? aksrt_get_rewards_button($author_id, 'but pw-1em mr6 c-yellow', get_the_ID()) : '';
if ($tip !== '') {
echo $tip; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if (function_exists('aksrt_render_rewards_modal_for_user')) {
@@ -226,7 +226,6 @@ function aksrt_is_lazy(string $key, bool $default = false): bool {
'lazy_avatar' => true,
'lazy_posts_content' => false,
'lazy_comment' => true,
'lazy_private' => true,
'lazy_sider' => true,
'lazy_cover' => true,
'lazy_other' => true,
@@ -19,7 +19,6 @@ $page = max(1, isset($_GET['follow_page']) ? (int) $_GET['follow_page'] : 1);
$result = $follow
? ($active_list === 'following' ? $follow->get_following((int) $user_id, $page, 20) : $follow->get_followers((int) $user_id, $page, 20))
: ['items' => [], 'total_pages' => 1];
$messages_enabled = !empty($messages_url);
?>
<div class="widget-card uc-follow-management">
<div class="profile-list-header">
@@ -39,17 +38,15 @@ $messages_enabled = !empty($messages_url);
</div>
<?php if (!empty($result['items'])) : ?>
<div class="uc-follow-management__list">
<?php foreach ($result['items'] as $item) :
$member_id = (int) ($item['user_id'] ?? 0);
$home_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($member_id) : '';
$message_url = $messages_enabled ? add_query_arg('msg_type', 'conversation', $messages_url) : '';
?>
<?php foreach ($result['items'] as $item) :
$member_id = (int) ($item['user_id'] ?? 0);
$home_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($member_id) : '';
?>
<div class="uc-follow-management__item" data-follow-user="<?php echo esc_attr((string) $member_id); ?>">
<a href="<?php echo esc_url($home_url); ?>" class="uc-follow-management__avatar"><?php echo get_avatar($member_id, 48, '', (string) ($item['display_name'] ?? '')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></a>
<div class="uc-follow-management__identity"><a href="<?php echo esc_url($home_url); ?>"><?php echo esc_html((string) ($item['display_name'] ?? '')); ?></a><span><?php echo esc_html(sprintf(__('关注于 %s', 'aksrt'), get_date_from_gmt((string) ($item['created_at'] ?? ''), get_option('date_format')))); ?></span></div>
<div class="uc-follow-management__actions">
<a class="btn-ghost btn-sm" href="<?php echo esc_url($home_url); ?>"><?php esc_html_e('主页', 'aksrt'); ?></a>
<?php if ($messages_enabled) : ?><a class="btn-ghost btn-sm" href="<?php echo esc_url($message_url); ?>"><?php esc_html_e('私信', 'aksrt'); ?></a><?php endif; ?>
<?php if ($active_list === 'following') : ?><button type="button" class="btn-outline btn-sm is-following" data-aksrt-follow="<?php echo esc_attr((string) $member_id); ?>"><i class="fa fas fa-heart" aria-hidden="true"></i><span><?php esc_html_e('已关注', 'aksrt'); ?></span></button><?php endif; ?>
</div>
</div>
-132
View File
@@ -53,53 +53,6 @@ class MessageController extends ControllerBase {
'callback' => [$this, 'mark_all_read'],
'permission_callback' => [$this, 'check_logged_in_permission'],
]);
// ── Private Messages / Conversations ──
// List conversations
register_rest_route(self::API_NAMESPACE, '/conversations', [
'methods' => 'GET',
'callback' => [$this, 'list_conversations'],
'permission_callback' => [$this, 'check_logged_in_permission'],
'args' => [
'limit' => ['default' => 20, 'sanitize_callback' => 'absint'],
],
]);
// Get thread messages
register_rest_route(self::API_NAMESPACE, '/conversations/(?P<id>\d+)/messages', [
'methods' => 'GET',
'callback' => [$this, 'get_thread'],
'permission_callback' => [$this, 'check_logged_in_permission'],
'args' => [
'page' => ['default' => 1, 'sanitize_callback' => 'absint'],
'per_page' => ['default' => 30, 'sanitize_callback' => 'absint'],
],
]);
// Send message in conversation
register_rest_route(self::API_NAMESPACE, '/conversations/(?P<id>\d+)/messages', [
'methods' => 'POST',
'callback' => [$this, 'send_message'],
'permission_callback' => [$this, 'check_logged_in_permission'],
'args' => [
'content' => ['required' => true, 'sanitize_callback' => 'sanitize_textarea_field'],
],
]);
// Create or get conversation with a user
register_rest_route(self::API_NAMESPACE, '/conversations/with/(?P<user_id>\d+)', [
'methods' => 'POST',
'callback' => [$this, 'get_or_create_conversation'],
'permission_callback' => [$this, 'check_logged_in_permission'],
]);
// Mark conversation read
register_rest_route(self::API_NAMESPACE, '/conversations/(?P<id>\d+)/read', [
'methods' => 'POST',
'callback' => [$this, 'mark_conversation_read'],
'permission_callback' => [$this, 'check_logged_in_permission'],
]);
}
// ── Notification handlers ──
@@ -160,91 +113,6 @@ class MessageController extends ControllerBase {
return $this->success(['data' => ['success' => $result]]);
}
// ── Conversation handlers ──
public function list_conversations(\WP_REST_Request $request): \WP_REST_Response {
$user_id = get_current_user_id();
$limit = min(50, (int) $request->get_param('limit'));
if (!class_exists('\AKSRT\Messages\PrivateMessage')) {
return $this->success(['data' => []]);
}
$conversations = \AKSRT\Messages\PrivateMessage::get_instance()->get_conversations($user_id, $limit);
return $this->success(['data' => $conversations]);
}
public function get_thread(\WP_REST_Request $request): \WP_REST_Response {
$user_id = get_current_user_id();
$conv_id = (int) $request->get_param('id');
$page = max(1, (int) $request->get_param('page'));
$per_page = min(50, (int) $request->get_param('per_page'));
if (!class_exists('\AKSRT\Messages\PrivateMessage')) {
return $this->error('not_available', '私信系统未启用。', 501);
}
$result = \AKSRT\Messages\PrivateMessage::get_instance()->get_thread($conv_id, $user_id, $page, $per_page);
if (is_wp_error($result)) {
return $this->error('thread_error', $result->get_error_message(), 403);
}
return $this->success(['data' => $result]);
}
public function send_message(\WP_REST_Request $request): \WP_REST_Response {
$user_id = get_current_user_id();
$conv_id = (int) $request->get_param('id');
$content = trim((string) $request->get_param('content'));
if (!$content) {
return $this->error('content_required', '消息内容不能为空。', 400);
}
if (!class_exists('\AKSRT\Messages\PrivateMessage')) {
return $this->error('not_available', '私信系统未启用。', 501);
}
$result = \AKSRT\Messages\PrivateMessage::get_instance()->send($conv_id, $user_id, $content);
if (!$result['success']) {
return $this->error('send_failed', $result['message'] ?? '发送失败。', 500);
}
return $this->success(['data' => $result]);
}
public function get_or_create_conversation(\WP_REST_Request $request): \WP_REST_Response {
$user_id = get_current_user_id();
$other_id = (int) $request->get_param('user_id');
if ($user_id === $other_id) {
return $this->error('self_message', '不能与自己创建对话。', 400);
}
if (!class_exists('\AKSRT\Messages\PrivateMessage')) {
return $this->error('not_available', '私信系统未启用。', 501);
}
$conv_id = \AKSRT\Messages\PrivateMessage::get_instance()->get_or_create_conversation($user_id, $other_id);
if (is_wp_error($conv_id)) {
return $this->error('create_failed', $conv_id->get_error_message(), 500);
}
return $this->success(['data' => ['conversation_id' => $conv_id]]);
}
public function mark_conversation_read(\WP_REST_Request $request): \WP_REST_Response {
$user_id = get_current_user_id();
$conv_id = (int) $request->get_param('id');
if (!class_exists('\AKSRT\Messages\PrivateMessage')) {
return $this->error('not_available', '私信系统未启用。', 501);
}
\AKSRT\Messages\PrivateMessage::get_instance()->mark_conversation_read($conv_id, $user_id);
return $this->success(['data' => ['success' => true]]);
}
public function check_logged_in_permission(): bool {
return is_user_logged_in();
}
-7
View File
@@ -25,7 +25,6 @@ class GlobalSchema {
['key' => 'lazy_avatar', 'label' => '头像懒加载', 'type' => 'switch', 'default' => true],
['key' => 'lazy_posts_content', 'label' => '文章内容图片懒加载', 'type' => 'switch', 'default' => false],
['key' => 'lazy_comment', 'label' => '评论内容图片懒加载', 'type' => 'switch', 'default' => true],
['key' => 'lazy_private', 'label' => '私信聊天图片懒加载', 'type' => 'switch', 'default' => true],
['key' => 'lazy_sider', 'label' => '幻灯片图片懒加载', 'type' => 'switch', 'default' => true],
['key' => 'lazy_cover', 'label' => '封面图片懒加载', 'type' => 'switch', 'default' => true],
['key' => 'lazy_other', 'label' => '其它图片懒加载', 'type' => 'switch', 'default' => true],
@@ -383,12 +382,6 @@ class GlobalSchema {
['label' => '纯文本', 'value' => 'plain'],
['label' => 'HTML', 'value' => 'html'],
]],
['key' => 'email_private_receive_limit', 'label' => '私信邮件接收组', 'type' => 'select', 'default' => 'all', 'options' => [
['label' => '所有用户', 'value' => 'all'],
['label' => 'VIP 及以上', 'value' => 'vip'],
['label' => 'VIP2 及以上', 'value' => 'vip2'],
['label' => '仅管理员', 'value' => 'admin'],
], 'help' => '限制哪些用户组可以收到私信邮件通知'],
]],
['key' => 'branding', 'title' => '邮件品牌', 'fields' => [
['key' => 'mail_showname', 'label' => '发件人名称', 'type' => 'input', 'default' => '', 'help' => '覆盖系统默认发件人名称'],
-13
View File
@@ -277,21 +277,9 @@ class SchemaUsers {
['label' => '认证回复', 'value' => 'auth_apply_reply'],
['label' => '下载通知', 'value' => 'download'],
['label' => '积分变动', 'value' => 'credits'],
['label' => '私信', 'value' => 'private'],
['label' => '举报反馈', 'value' => 'report'],
]],
]],
['key' => 'private', 'title' => '私信设置', 'fields' => [
['key' => 'private_s', 'label' => '启用私信功能', 'type' => 'switch', 'default' => true],
['key' => 'private_smilie_s', 'label' => '支持表情', 'type' => 'switch', 'default' => true],
['key' => 'private_code_s', 'label' => '支持代码', 'type' => 'switch', 'default' => false],
['key' => 'private_image_s', 'label' => '支持图片', 'type' => 'switch', 'default' => true],
['key' => 'private_upload_img', 'label' => '支持上传图片', 'type' => 'switch', 'default' => false],
['key' => 'private_quick_s', 'label' => '快捷回复', 'type' => 'switch', 'default' => true],
['key' => 'private_quick_often', 'label' => '常用快捷回复', 'type' => 'textarea', 'default' => "你好,请问有什么可以帮你的?\n感谢你的反馈\n已处理,请查收", 'desc' => '一行一条快捷回复文案'],
['key' => 'private_submit_text', 'label' => '发送按钮文案', 'type' => 'input', 'default' => '发送'],
['key' => 'private_placeholder', 'label' => '输入占位符', 'type' => 'input', 'default' => '请输入消息...'],
]],
],
],
'oauth' => [
@@ -580,7 +568,6 @@ class SchemaUsers {
['key' => 'user_cover_img', 'label' => '默认封面', 'type' => 'media', 'default' => ''],
['key' => 'user_rewrite_slug', 'label' => '用户页slug', 'type' => 'input', 'default' => 'user'],
['key' => 'user_follow_s', 'label' => '启用关注功能', 'type' => 'switch', 'default' => true],
['key' => 'user_message_s', 'label' => '启用私信功能', 'type' => 'switch', 'default' => true],
['key' => 'user_online_s', 'label' => '显示在线状态', 'type' => 'switch', 'default' => true],
['key' => 'user_last_active_s', 'label' => '显示最后活跃', 'type' => 'switch', 'default' => true],
]],
@@ -151,11 +151,6 @@ trait UserControllerAuthPhoneOperations {
return $this->error('未登录', 401);
}
$unread = 0;
if (class_exists('\AKSRT\Messages\PrivateMessage')) {
$unread = \AKSRT\Messages\PrivateMessage::get_instance()->get_unread_count($user->ID);
}
$credits = 0;
if (class_exists('\AKSRT\Credits\Credits')) {
$credits = \AKSRT\Credits\Credits::balance($user->ID);
@@ -170,7 +165,6 @@ trait UserControllerAuthPhoneOperations {
? aksrt_get_avatar_url($user->ID, ['size' => 48])
: get_avatar_url($user->ID, ['size' => 48]),
'is_admin' => current_user_can('manage_options'),
'unread' => $unread,
'credits' => $credits,
],
]);
-31
View File
@@ -108,37 +108,6 @@ trait DBMigratorPart2 {
) {$charset_collate};";
dbDelta($sql_notification);
// ---------- 6. 私信会话 ----------
$sql_conversation = "CREATE TABLE {$prefix}aksrt_conversation (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_a BIGINT UNSIGNED NOT NULL,
user_b BIGINT UNSIGNED NOT NULL,
last_message VARCHAR(255) DEFAULT '',
last_message_at DATETIME DEFAULT NULL,
unread_a INT NOT NULL DEFAULT 0,
unread_b INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY uniq_pair (user_a, user_b),
KEY idx_user_a (user_a),
KEY idx_user_b (user_b),
KEY idx_last_msg (last_message_at)
) {$charset_collate};";
dbDelta($sql_conversation);
// ---------- 7. 私信消息 ----------
$sql_conv_message = "CREATE TABLE {$prefix}aksrt_conversation_message (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
conversation_id BIGINT UNSIGNED NOT NULL,
sender_id BIGINT UNSIGNED NOT NULL,
content TEXT NOT NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (id),
KEY idx_conv_time (conversation_id, created_at),
KEY idx_sender (sender_id)
) {$charset_collate};";
dbDelta($sql_conv_message);
// ---------- 8. 订单表 ----------
$sql_order = "CREATE TABLE {$prefix}aksrt_order (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
-2
View File
@@ -21,8 +21,6 @@ trait DBMigratorPart3 {
'signin_log' => 'aksrt_signin_log',
'dl_token' => 'aksrt_dl_token',
'notification' => 'aksrt_notification',
'conversation' => 'aksrt_conversation',
'conv_message' => 'aksrt_conversation_message',
'order' => 'aksrt_order',
'order_item' => 'aksrt_order_item',
'revenue' => 'aksrt_revenue',
-10
View File
@@ -600,16 +600,6 @@ trait ScriptsPart1b {
true
);
}
$conversation_js = get_template_directory() . '/assets/js/conversation.js';
if (file_exists($conversation_js)) {
wp_enqueue_script(
'aksrt-conversation',
$base_uri . '/assets/js/conversation.js',
['loader_js'],
(string) filemtime($conversation_js),
true
);
}
}
// Unified share-data builder — single payload assembler for every share
-1
View File
@@ -572,7 +572,6 @@ trait ScriptsPart1c {
'lazy_avatar' => aksrt_is_lazy('lazy_avatar'),
'lazy_posts_content' => aksrt_is_lazy('lazy_posts_content'),
'lazy_comment' => aksrt_is_lazy('lazy_comment'),
'lazy_private' => aksrt_is_lazy('lazy_private'),
'lazy_sider' => aksrt_is_lazy('lazy_sider'),
'lazy_cover' => aksrt_is_lazy('lazy_cover'),
'lazy_other' => aksrt_is_lazy('lazy_other'),
+1 -1
View File
@@ -98,7 +98,7 @@ class Message {
* 发送站内通知(持久化到 aksrt_notification 表)
*
* @param int $to_user_id 接收人 ID
* @param string $type 通知类型 (comment_reply, download_ready, conversation, notice, ...)
* @param string $type 通知类型 (comment_reply, download_ready, notice, ...)
* @param string $content 通知内容摘要
* @param array $data 附加数据 (title, target_url, ...)
* @return bool
-381
View File
@@ -1,381 +0,0 @@
<?php
/**
* @package AKSRT
*/
namespace AKSRT\Messages;
defined('ABSPATH') || exit;
class PrivateMessage {
private static $instance = null;
public static function get_instance(): self {
if (null === self::$instance) self::$instance = new self();
return self::$instance;
}
public function init(): void {
add_action('wp_ajax_aksrt_pm_send', [$this, 'ajax_send']);
add_action('wp_ajax_aksrt_pm_conversations', [$this, 'ajax_conversations']);
add_action('wp_ajax_aksrt_pm_thread', [$this, 'ajax_thread']);
add_action('wp_ajax_aksrt_pm_mark_read', [$this, 'ajax_mark_read']);
add_action('wp_ajax_aksrt_pm_unread_count', [$this, 'ajax_unread_count']);
}
/* ------------------------------------------------------------------
* Table name helpers
* ----------------------------------------------------------------*/
private function table_conv(): string {
global $wpdb;
return $wpdb->prefix . 'aksrt_conversation';
}
private function table_msg(): string {
global $wpdb;
return $wpdb->prefix . 'aksrt_conversation_message';
}
/* ------------------------------------------------------------------
* Conversation CRUD
* ----------------------------------------------------------------*/
/**
* Get or create a 1-to-1 conversation between two users.
*/
public function get_or_create_conversation(int $user_a, int $user_b): int {
global $wpdb;
if ($user_a <= 0 || $user_b <= 0 || $user_a === $user_b) return 0;
// Ensure consistent ordering
$min_id = min($user_a, $user_b);
$max_id = max($user_a, $user_b);
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM {$this->table_conv()} WHERE user_a = %d AND user_b = %d",
$min_id, $max_id
));
if ($existing) return (int) $existing;
$wpdb->insert($this->table_conv(), [
'user_a' => $min_id,
'user_b' => $max_id,
'last_message' => '',
'last_message_at' => current_time('mysql'),
'unread_a' => 0,
'unread_b' => 0,
'created_at' => current_time('mysql'),
], ['%d', '%d', '%s', '%s', '%d', '%d', '%s']);
return (int) $wpdb->insert_id;
}
/**
* List conversations for a user (most recent first).
*
* @param int $user_id
* @param int $limit
* @return array
*/
public function get_conversations(int $user_id, int $limit = 20): array {
global $wpdb;
if ($user_id <= 0) return [];
$table_conv = $this->table_conv();
$table_msg = $this->table_msg();
$rows = $wpdb->get_results($wpdb->prepare(
"SELECT c.*,
CASE WHEN c.user_a = %d THEN c.unread_a ELSE c.unread_b END AS my_unread,
CASE WHEN c.user_a = %d THEN c.user_b ELSE c.user_a END AS other_user_id
FROM {$table_conv} c
WHERE c.user_a = %d OR c.user_b = %d
ORDER BY c.last_message_at DESC
LIMIT %d",
$user_id, $user_id, $user_id, $user_id, $limit
), ARRAY_A);
$conversations = [];
foreach ((array) $rows as $row) {
$other_id = (int) $row['other_user_id'];
$other_user = get_userdata($other_id);
$conversations[] = [
'id' => (int) $row['id'],
'other_user_id' => $other_id,
'other_name' => $other_user ? $other_user->display_name : __('用户', 'aksrt'),
'other_avatar' => $other_user ? get_avatar_url($other_id, ['size' => 48]) : '',
'last_message' => $row['last_message'] ?? '',
'last_message_at' => $row['last_message_at'] ?? '',
'unread' => (int) $row['my_unread'],
];
}
return $conversations;
}
/* ------------------------------------------------------------------
* Message CRUD
* ----------------------------------------------------------------*/
/**
* Send a message in a conversation.
*
* @param int $conversation_id
* @param int $sender_id
* @param string $content
* @return array{success: bool, message_id?: int, message: string}
*/
public function send(int $conversation_id, int $sender_id, string $content): array {
global $wpdb;
if ($conversation_id <= 0 || $sender_id <= 0) {
return ['success' => false, 'message' => __('参数无效', 'aksrt')];
}
$content = sanitize_textarea_field($content);
if ($content === '') {
return ['success' => false, 'message' => __('消息不能为空', 'aksrt')];
}
// Verify user is a participant
$conv = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$this->table_conv()} WHERE id = %d",
$conversation_id
), ARRAY_A);
if (!$conv) {
return ['success' => false, 'message' => __('会话不存在', 'aksrt')];
}
if ((int) $conv['user_a'] !== $sender_id && (int) $conv['user_b'] !== $sender_id) {
return ['success' => false, 'message' => __('无权操作', 'aksrt')];
}
$now = current_time('mysql');
// Insert message
$wpdb->insert($this->table_msg(), [
'conversation_id' => $conversation_id,
'sender_id' => $sender_id,
'content' => $content,
'created_at' => $now,
], ['%d', '%d', '%s', '%s']);
$message_id = (int) $wpdb->insert_id;
if (!$message_id) {
return ['success' => false, 'message' => __('发送失败', 'aksrt')];
}
// Update conversation metadata
$is_a = (int) $conv['user_a'] === $sender_id;
$unread_field = $is_a ? 'unread_b' : 'unread_a';
$wpdb->update($this->table_conv(), [
'last_message' => mb_substr($content, 0, 200),
'last_message_at' => $now,
$unread_field => (int) $conv[$unread_field] + 1,
], ['id' => $conversation_id]);
// Create notification for the recipient
$recipient_id = $is_a ? (int) $conv['user_b'] : (int) $conv['user_a'];
if (class_exists('AKSRT\\Messages\\Message')) {
$sender_name = '';
$sender_user = get_userdata($sender_id);
if ($sender_user) {
$sender_name = $sender_user->display_name;
}
Message::get_instance()->send(
$recipient_id,
'conversation',
mb_substr($content, 0, 100),
[
'title' => sprintf(__('%s 发来私信', 'aksrt'), $sender_name),
'target_url' => add_query_arg(['msg_type' => 'conversation']),
]
);
}
do_action('aksrt_private_message_sent', $conversation_id, $sender_id, $recipient_id, $message_id);
return ['success' => true, 'message_id' => $message_id, 'message' => __('已发送', 'aksrt')];
}
/**
* Get messages in a conversation (paginated, newest first).
*
* @param int $conversation_id
* @param int $user_id Must be a participant.
* @param int $page
* @param int $per_page
* @return array
*/
public function get_thread(int $conversation_id, int $user_id, int $page = 1, int $per_page = 30): array {
global $wpdb;
if ($conversation_id <= 0 || $user_id <= 0) return ['messages' => [], 'total' => 0];
// Verify participation
$conv = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$this->table_conv()} WHERE id = %d",
$conversation_id
), ARRAY_A);
if (!$conv || ((int) $conv['user_a'] !== $user_id && (int) $conv['user_b'] !== $user_id)) {
return ['messages' => [], 'total' => 0];
}
$offset = max(0, ($page - 1) * $per_page);
$total = (int) $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$this->table_msg()} WHERE conversation_id = %d",
$conversation_id
));
$rows = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$this->table_msg()}
WHERE conversation_id = %d
ORDER BY created_at DESC
LIMIT %d OFFSET %d",
$conversation_id, $per_page, $offset
), ARRAY_A);
$messages = [];
foreach ((array) $rows as $row) {
$sender = get_userdata((int) $row['sender_id']);
$messages[] = [
'id' => (int) $row['id'],
'sender_id' => (int) $row['sender_id'],
'sender_name' => $sender ? $sender->display_name : __('用户', 'aksrt'),
'sender_avatar' => $sender ? get_avatar_url((int) $row['sender_id'], ['size' => 32]) : '',
'content' => $row['content'] ?? '',
'is_mine' => (int) $row['sender_id'] === $user_id,
'created_at' => $row['created_at'] ?? '',
];
}
// Mark as read for this user
$this->mark_conversation_read($conversation_id, $user_id);
return [
'messages' => $messages,
'total' => $total,
'page' => $page,
'pages' => max(1, (int) ceil($total / $per_page)),
];
}
/**
* Mark all messages in a conversation as read for a user.
*/
public function mark_conversation_read(int $conversation_id, int $user_id): void {
global $wpdb;
$conv = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$this->table_conv()} WHERE id = %d",
$conversation_id
), ARRAY_A);
if (!$conv) return;
$is_a = (int) $conv['user_a'] === $user_id;
$field = $is_a ? 'unread_a' : 'unread_b';
$wpdb->update($this->table_conv(), [$field => 0], ['id' => $conversation_id]);
}
/**
* Get total unread conversation count for a user.
*/
public function get_unread_count(int $user_id): int {
global $wpdb;
if ($user_id <= 0) return 0;
$count = $wpdb->get_var($wpdb->prepare(
"SELECT SUM(CASE WHEN user_a = %d THEN unread_a ELSE unread_b END)
FROM {$this->table_conv()}
WHERE user_a = %d OR user_b = %d",
$user_id, $user_id, $user_id
));
return max(0, (int) $count);
}
/* ------------------------------------------------------------------
* AJAX Handlers
* ----------------------------------------------------------------*/
public function ajax_send(): void {
check_ajax_referer('aksrt_pm', '_nonce');
$user_id = get_current_user_id();
if ($user_id <= 0) wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
$recipient_id = (int) ($_POST['recipient_id'] ?? 0);
$content = sanitize_textarea_field((string) ($_POST['content'] ?? ''));
if ($recipient_id <= 0) wp_send_json_error(['message' => __('收件人无效', 'aksrt')]);
$conv_id = $this->get_or_create_conversation($user_id, $recipient_id);
if (!$conv_id) wp_send_json_error(['message' => __('无法创建会话', 'aksrt')]);
$result = $this->send($conv_id, $user_id, $content);
if ($result['success']) {
wp_send_json_success($result);
}
wp_send_json_error($result);
}
public function ajax_conversations(): void {
check_ajax_referer('aksrt_pm', '_nonce');
$user_id = get_current_user_id();
if ($user_id <= 0) wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
$limit = max(1, min(50, (int) ($_GET['limit'] ?? 20)));
$conversations = $this->get_conversations($user_id, $limit);
wp_send_json_success(['conversations' => $conversations]);
}
public function ajax_thread(): void {
check_ajax_referer('aksrt_pm', '_nonce');
$user_id = get_current_user_id();
if ($user_id <= 0) wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
$conv_id = (int) ($_GET['conversation_id'] ?? 0);
$page = max(1, (int) ($_GET['page'] ?? 1));
$result = $this->get_thread($conv_id, $user_id, $page);
wp_send_json_success($result);
}
public function ajax_mark_read(): void {
check_ajax_referer('aksrt_pm', '_nonce');
$user_id = get_current_user_id();
if ($user_id <= 0) wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
$conv_id = (int) ($_POST['conversation_id'] ?? 0);
$this->mark_conversation_read($conv_id, $user_id);
wp_send_json_success(['unread' => $this->get_unread_count($user_id)]);
}
public function ajax_unread_count(): void {
check_ajax_referer('aksrt_pm', '_nonce');
$user_id = get_current_user_id();
if ($user_id <= 0) wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
wp_send_json_success(['unread' => $this->get_unread_count($user_id)]);
}
}
-1
View File
@@ -194,7 +194,6 @@ trait DisplayPageGroups {
'seo' => self::get_seo_settings(),
'mail' => self::get_smtp(),
'email_events' => self::get_email_event_config(),
'email_private_receive_limit' => self::get_email_private_receive_limit(),
'footer' => self::get_footer_settings(),
'tabbar' => self::get_footer_tabbar_settings(),
'floating_buttons' => self::get_floating_buttons_settings(),
-5
View File
@@ -100,11 +100,6 @@ trait DomainGroups {
return Integration::auto_clear_settings();
}
/** 私信功能配置 */
public static function private_message_settings(): array {
return Integration::private_message_settings();
}
/**
* 获取菜单项扩展 meta 字段列表
*/
+1 -27
View File
@@ -9,13 +9,6 @@ defined('ABSPATH') || exit;
class Integration {
/** 私信邮件接收组限制 (all/vip/vip2/admin) */
public static function get_email_private_receive_limit(): string {
$limit = (string) Settings::get_value('email_private_receive_limit', 'all');
$valid = ['all', 'vip', 'vip2', 'admin'];
return in_array($limit, $valid, true) ? $limit : 'all';
}
/** 获取OAuth配置 */
public static function get_oauth(): array {
return get_option('aksrt_oauth', []);
@@ -386,7 +379,7 @@ class Integration {
if (!is_array($types)) {
$types = [];
}
$allowed = ['posts', 'comment', 'favorite', 'like', 'hot', 'followed', 'system', 'pay', 'withdraw_reply', 'medal', 'auth_apply_reply', 'download', 'credits', 'private', 'report'];
$allowed = ['posts', 'comment', 'favorite', 'like', 'hot', 'followed', 'system', 'pay', 'withdraw_reply', 'medal', 'auth_apply_reply', 'download', 'credits', 'report'];
return [
'enabled' => !empty($settings['message_auto_clear_s']),
'days' => max(1, min(3650, (int) ($settings['message_auto_clear_time'] ?? 365))),
@@ -394,25 +387,6 @@ class Integration {
];
}
/** 私信功能配置 */
public static function private_message_settings(): array {
$settings = Settings::get_all();
$quick_often = (string) ($settings['private_quick_often'] ?? "你好,请问有什么可以帮你的?\n感谢你的反馈\n已处理,请查收");
$quick_lines = array_filter(array_map('trim', preg_split('/\r\n|\r|\n/', $quick_often)));
return [
'enabled' => !array_key_exists('private_s', $settings) || !empty($settings['private_s']),
'smilie' => !empty($settings['private_smilie_s']),
'code' => !empty($settings['private_code_s']),
'image' => !empty($settings['private_image_s']),
'upload_img' => !empty($settings['private_upload_img']),
'quick_reply' => !empty($settings['private_quick_s']),
'quick_often' => array_values($quick_lines),
'submit_text' => sanitize_text_field((string) ($settings['private_submit_text'] ?? '发送')),
'placeholder' => sanitize_text_field((string) ($settings['private_placeholder'] ?? '请输入消息...')),
];
}
/**
* 获取右侧浮动按钮完整配置
* @return array {enabled, style, position, scroll_hide, scroll_down_hide, filter_blur, items}
-9
View File
@@ -729,15 +729,6 @@ class Settings {
DisplayRuntime::save_friend_links($links);
}
/** 私信邮件接收组限制 (all/vip/vip2/admin) */
public static function get_email_private_receive_limit(): string {
return Integration::get_email_private_receive_limit();
}
/** 获取OAuth配置 */
public static function get_oauth(): array {
return Integration::get_oauth();
+7 -81
View File
@@ -4,7 +4,7 @@
* Template Post Type: page
*
* 独立消息中心页面 — 两栏布局(左侧导航 + 右侧消息列表)
* 对齐 legacy msg-center:未读 / 评论 / 系统 / 私信(可开关)
* 对齐 legacy msg-center:未读 / 评论 / 系统
*
* @package AKSRT
*/
@@ -21,8 +21,6 @@ if (!is_user_logged_in()) {
}
$messages_enabled = !class_exists('\AKSRT\Settings\Settings') || \AKSRT\Settings\Settings::message_enabled();
$pm_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::private_message_settings() : ['enabled' => false];
$pm_enabled = !empty($pm_settings['enabled']);
if (!$messages_enabled) :
?>
@@ -60,13 +58,8 @@ $type_groups = [
'medal' => ['medal', 'badge', 'level_up'],
'ban_appeal' => ['ban_appeal', 'user_ban', 'restriction'],
'system' => ['notice', 'download_ready', 'upload_moderation', 'verify_email', 'auth_apply', 'auth_apply_reply'],
'conversation' => ['conversation'],
];
if ($current_type === 'conversation' && !$pm_enabled) {
$current_type = 'unread';
}
$allowed_types = array_keys($type_groups);
if (!in_array($current_type, $allowed_types, true)) {
// 兼容旧 URL:msg_type=comment_reply 等
@@ -83,7 +76,7 @@ if (!in_array($current_type, $allowed_types, true)) {
$filtered = $all_notifications;
if ($current_type === 'unread') {
$filtered = array_filter($filtered, static fn($n) => empty($n['read']));
} elseif ($current_type !== 'all' && $current_type !== 'conversation') {
} elseif ($current_type !== 'all') {
$types = $type_groups[$current_type] ?? [];
$filtered = array_filter($filtered, static function ($n) use ($types) {
$t = (string) ($n['type'] ?? 'notice');
@@ -110,31 +103,19 @@ $paged_items = array_slice($filtered, $offset, $per_page);
'medal' => 0,
'ban_appeal' => 0,
'system' => 0,
'conversation' => 0,
];
foreach ($all_notifications as $n) {
$t = (string) ($n['type'] ?? 'notice');
if (empty($n['read'])) {
$type_counts['unread']++;
}
foreach (['comment', 'credits', 'pay', 'vip', 'medal', 'ban_appeal', 'system', 'conversation'] as $group) {
foreach (['comment', 'credits', 'pay', 'vip', 'medal', 'ban_appeal', 'system'] as $group) {
if (!empty($type_groups[$group]) && is_array($type_groups[$group]) && in_array($t, $type_groups[$group], true)) {
$type_counts[$group]++;
}
}
}
if ($pm_enabled && class_exists('\AKSRT\Messages\PrivateMessage')) {
// conversation count prefers live PM conversations when available
$pm_tmp = \AKSRT\Messages\PrivateMessage::get_instance();
if (method_exists($pm_tmp, 'get_conversations')) {
$convs = $pm_tmp->get_conversations($user_id, 100);
if (is_array($convs)) {
$type_counts['conversation'] = count($convs);
}
}
}
$nav_items = [
'unread' => __('未读消息', 'aksrt'),
'all' => __('全部消息', 'aksrt'),
@@ -146,9 +127,6 @@ $nav_items = [
'ban_appeal' => __('禁封申诉', 'aksrt'),
'system' => __('系统通知', 'aksrt'),
];
if ($pm_enabled) {
$nav_items['conversation'] = __('私信消息', 'aksrt');
}
$icon_map = [
'comment_reply' => 'fa fas fa-comment-dots',
@@ -158,9 +136,8 @@ $nav_items = [
'download_ready' => 'fa fas fa-download',
'upload_moderation' => 'fa fas fa-image',
'verify_email' => 'fa fas fa-envelope-open',
'pending_comments' => 'fa fas fa-clock',
'conversation' => 'fa fas fa-envelope',
'pay' => 'fa fas fa-file-alt',
'pending_comments' => 'fa fas fa-clock',
'pay' => 'fa fas fa-file-alt',
'order_paid' => 'fa fas fa-file-alt',
'order_refund' => 'fa fas fa-undo',
'after_sale' => 'fa fas fa-undo',
@@ -196,7 +173,7 @@ if (!$messages_base) {
<?php foreach ($nav_items as $key => $label) :
$count = (int) ($type_counts[$key] ?? 0);
// 始终显示核心 tab;其余无数据时可隐藏(保留 unread/all/system)
if (!in_array($key, ['unread', 'all', 'system', 'conversation'], true) && $count < 1) {
if (!in_array($key, ['unread', 'all', 'system'], true) && $count < 1) {
continue;
}
$is_active = $current_type === $key;
@@ -221,58 +198,7 @@ if (!$messages_base) {
</aside>
<section class="messages-center__content">
<?php if ($current_type === 'conversation' && $pm_enabled) :
$pm = class_exists('\AKSRT\Messages\PrivateMessage') ? \AKSRT\Messages\PrivateMessage::get_instance() : null;
$conversations = $pm ? $pm->get_conversations($user_id, 30) : [];
$pm_nonce = wp_create_nonce('aksrt_pm');
$pm_placeholder = (string) ($pm_settings['placeholder'] ?? __('请输入消息...', 'aksrt'));
$pm_submit = (string) ($pm_settings['submit_text'] ?? __('发送', 'aksrt'));
?>
<div class="messages-conversations" id="aksrt-pm-conversations"
data-ajax="<?php echo esc_url(admin_url('admin-ajax.php')); ?>"
data-nonce="<?php echo esc_attr($pm_nonce); ?>">
<?php if (!empty($conversations)) : ?>
<div class="aksrt-pm__list">
<?php foreach ($conversations as $conv) : ?>
<div class="aksrt-pm__item<?php echo !empty($conv['unread']) ? ' is-unread' : ''; ?>"
data-conv-id="<?php echo esc_attr((string) ($conv['id'] ?? '')); ?>"
data-other-id="<?php echo esc_attr((string) ($conv['other_user_id'] ?? '')); ?>">
<img<?php echo aksrt_get_lazy_attr('lazy_private', (string) ($conv['other_avatar'] ?? ''), 'aksrt-pm__avatar', aksrt_get_lazy_thumb('sm')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt="">
<div class="aksrt-pm__info">
<div class="aksrt-pm__name">
<?php echo esc_html((string) ($conv['other_name'] ?? '')); ?>
<?php if (!empty($conv['unread'])) : ?>
<span class="aksrt-pm__badge"><?php echo esc_html((string) $conv['unread']); ?></span>
<?php endif; ?>
</div>
<div class="aksrt-pm__preview"><?php echo esc_html(mb_substr((string) ($conv['last_message'] ?? ''), 0, 50)); ?></div>
</div>
<div class="aksrt-pm__time"><?php echo esc_html(!empty($conv['last_message_at']) ? mysql2date('m-d H:i', (string) $conv['last_message_at']) : ''); ?></div>
</div>
<?php endforeach; ?>
</div>
<?php else : ?>
<div class="messages-empty">
<span class="messages-empty__icon"><i class="fa fas fa-envelope"></i></span>
<p class="messages-empty__text"><?php esc_html_e('暂无私信', 'aksrt'); ?></p>
<p class="messages-empty__hint"><?php esc_html_e('你可以在用户主页或文章作者栏发起私信。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
</div>
<div class="aksrt-pm__thread" id="aksrt-pm-thread" hidden>
<div class="aksrt-pm__thread-header">
<button type="button" class="aksrt-pm__back-btn" id="aksrt-pm-back"><i class="fa fas fa-arrow-left"></i> <?php esc_html_e('返回', 'aksrt'); ?></button>
<span class="aksrt-pm__thread-name" id="aksrt-pm-thread-name"></span>
</div>
<div class="aksrt-pm__messages" id="aksrt-pm-messages"></div>
<div class="aksrt-pm__compose">
<textarea id="aksrt-pm-input" rows="2" placeholder="<?php echo esc_attr($pm_placeholder); ?>"></textarea>
<button type="button" id="aksrt-pm-send" class="aksrt-pm__send-btn" aria-label="<?php echo esc_attr($pm_submit); ?>"><i class="fa fas fa-paper-plane"></i></button>
</div>
</div>
<?php elseif (!empty($paged_items)) : ?>
<?php if (!empty($paged_items)) : ?>
<div class="messages-list">
<?php foreach ($paged_items as $notice) :
$n_type = (string) ($notice['type'] ?? 'notice');
+5 -12
View File
@@ -43,8 +43,6 @@ $abs_fmt = $use_modified
$time_text = human_time_diff($rel_base, $now) . $rel_label;
$classes = trim('article-avatar ' . $extra_class);
$aksrt_pm_on = class_exists('\AKSRT\Settings\Settings') && !empty(\AKSRT\Settings\Settings::private_message_settings()['enabled']);
$aksrt_msg_url = function_exists('aksrt_get_messages_page_url') ? aksrt_get_messages_page_url() : '';
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
$is_self = is_user_logged_in() && get_current_user_id() === $author_id;
@@ -115,16 +113,11 @@ $is_self = is_user_logged_in() && get_current_user_id() === $author_id;
<div class="flex0 user-action">
<?php if (!$is_self) : ?>
<?php if (is_user_logged_in()) : ?>
<button type="button" class="px12-sm ml10 follow but c-red" data-aksrt-follow="<?php echo (int) $author_id; ?>">
<i class="fa fas fa-heart em09" aria-hidden="true"></i> <span><?php esc_html_e('关注', 'aksrt'); ?></span>
</button>
<?php if ($aksrt_pm_on && $aksrt_msg_url !== '') : ?>
<a href="<?php echo esc_url(add_query_arg('msg_type', 'conversation', $aksrt_msg_url)); ?>" class="ml6 but c-blue px12-sm">
<i class="fa fas fa-comment em09" aria-hidden="true"></i> <?php esc_html_e('私信', 'aksrt'); ?>
</a>
<?php endif; ?>
<?php
$reward_button = function_exists('aksrt_get_rewards_button')
<button type="button" class="px12-sm ml10 follow but c-red" data-aksrt-follow="<?php echo (int) $author_id; ?>">
<i class="fa fas fa-heart em09" aria-hidden="true"></i> <span><?php esc_html_e('关注', 'aksrt'); ?></span>
</button>
<?php
$reward_button = function_exists('aksrt_get_rewards_button')
? aksrt_get_rewards_button($author_id, 'ml6 but c-yellow px12-sm', get_the_ID())
: '';
if ($reward_button !== '') {
+3 -23
View File
@@ -55,14 +55,8 @@ if ($follower_count <= 0 && class_exists('\AKSRT\User\Follow')) {
$follower_count = (int) \AKSRT\User\Follow::get_instance()->get_follower_count($user_id);
}
$pm_enabled = class_exists('\AKSRT\Settings\Settings') && !empty(\AKSRT\Settings\Settings::private_message_settings()['enabled']);
$messages_url = function_exists('aksrt_get_messages_page_url') ? aksrt_get_messages_page_url() : '';
$pm_url = ($pm_enabled && $messages_url !== '')
? add_query_arg('msg_type', 'conversation', $messages_url)
: '';
?>
<div class="aksrt-author-hero<?php echo $show_cover ? '' : ' aksrt-author-hero--no-cover'; ?>">
?><div class="aksrt-author-hero<?php echo $show_cover ? '' : ' aksrt-author-hero--no-cover'; ?>">
<?php if ($show_cover) : ?>
<div class="aksrt-author-hero__cover">
<img<?php echo aksrt_get_lazy_attr('lazy_cover', (string) ($bg_url ? $bg_url : get_theme_file_uri('assets/img/person_background.png')), 'aksrt-author-hero__cover-img', aksrt_get_lazy_thumb('lg')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt="">
@@ -165,25 +159,11 @@ $pm_url = ($pm_enabled && $messages_url !== '')
<i class="fa fas fa-heart" aria-hidden="true"></i>
<span><?php esc_html_e('登录后关注', 'aksrt'); ?></span>
</a>
<?php endif; ?>
<?php endif; ?>
<?php endif; ?>
<?php if ($show_message && $pm_url !== '') : ?>
<?php if (is_user_logged_in()) : ?>
<a href="<?php echo esc_url($pm_url); ?>" class="btn-primary btn-sm">
<i class="fa fas fa-comment" aria-hidden="true"></i>
<span><?php esc_html_e('私信', 'aksrt'); ?></span>
</a>
<?php else : ?>
<a href="<?php echo esc_url(aksrt_get_login_url($home_url)); ?>" class="btn-primary btn-sm">
<i class="fa fas fa-comment" aria-hidden="true"></i>
<span><?php esc_html_e('私信', 'aksrt'); ?></span>
</a>
<?php endif; ?>
<?php endif; ?>
<?php endif; ?>
<?php if ($is_author && function_exists('aksrt_render_admin_quick_link')) { aksrt_render_admin_quick_link('page-display/user-home', __('用户主页设置', 'aksrt')); } ?>
<?php if ($is_author && function_exists('aksrt_render_admin_quick_link')) { aksrt_render_admin_quick_link('page-display/user-home', __('用户主页设置', 'aksrt')); } ?>
</div>
</div>
</div>
@@ -34,7 +34,6 @@ const lazyDefaults = {
lazy_avatar: true,
lazy_posts_content: false,
lazy_comment: true,
lazy_private: true,
lazy_sider: true,
lazy_cover: true,
lazy_other: true,
-2
View File
@@ -29,8 +29,6 @@ $tables = [
'aksrt_invite',
'aksrt_dl_token',
'aksrt_notification',
'aksrt_conversation',
'aksrt_conversation_message',
'aksrt_report',
'aksrt_follow',
'aksrt_user_restriction',