完善角色与消息权限:收紧板管内容处置,彻底删除仅站长,并统一管理删帖/评弹窗。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-20 14:30:08 +08:00
parent 1f2e4b2a33
commit c0462a3500
37 changed files with 1340 additions and 472 deletions

View File

@@ -14,8 +14,10 @@ import {
apiAdminRecallChatMessage,
type AdminChatMessage,
type AdminChatRoomType,
type User,
} from "@/lib/api";
import { formatRelative } from "@/lib/format";
import { canOverseeChat } from "@/lib/roles";
import { toast } from "@/lib/toast";
import Avatar from "@/components/Avatar";
import AutolinkText from "@/components/AutolinkText";
@@ -247,7 +249,8 @@ function useMessageColumn(roomType: MsgKind) {
}
/** 群聊(含大厅)| 私聊 双栏监管 */
export default function MessagesAdmin() {
export default function MessagesAdmin({ me }: { me: User }) {
const canOversee = canOverseeChat(me.role);
const [mobileKind, setMobileKind] = useState<MsgKind>("group");
const group = useMessageColumn("group");
const direct = useMessageColumn("direct");
@@ -485,37 +488,43 @@ export default function MessagesAdmin() {
<AdminPageHeader
icon={MessagesSquare}
title="消息管理"
description="分栏监管群聊与私聊;可搜索并撤回违规内容"
description={
canOversee
? "分栏监管群聊与私聊;可搜索并撤回违规内容"
: "监管授权范围内的群聊消息;可搜索并撤回违规内容(不含私聊)"
}
/>
<div className="admin-content-kind lg:hidden shrink-0" role="tablist" aria-label="消息类型">
<button
type="button"
role="tab"
aria-selected={mobileKind === "group"}
className="admin-content-kind-btn"
onClick={() => setMobileKind("group")}
>
<Users size={14} aria-hidden />
群聊
<span className="admin-content-kind-count">{group.total}</span>
</button>
<button
type="button"
role="tab"
aria-selected={mobileKind === "direct"}
className="admin-content-kind-btn"
onClick={() => setMobileKind("direct")}
>
<MessageCircle size={14} aria-hidden />
私聊
<span className="admin-content-kind-count">{direct.total}</span>
</button>
</div>
{canOversee ? (
<div className="admin-content-kind lg:hidden shrink-0" role="tablist" aria-label="消息类型">
<button
type="button"
role="tab"
aria-selected={mobileKind === "group"}
className="admin-content-kind-btn"
onClick={() => setMobileKind("group")}
>
<Users size={14} aria-hidden />
群聊
<span className="admin-content-kind-count">{group.total}</span>
</button>
<button
type="button"
role="tab"
aria-selected={mobileKind === "direct"}
className="admin-content-kind-btn"
onClick={() => setMobileKind("direct")}
>
<MessageCircle size={14} aria-hidden />
私聊
<span className="admin-content-kind-count">{direct.total}</span>
</button>
</div>
) : null}
<div className="admin-content-triptych">
<div className={canOversee ? "admin-content-triptych" : "admin-content-triptych admin-content-triptych--single"}>
{groupCol}
{directCol}
{canOversee ? directCol : null}
</div>
<ConfirmDialog