完善角色与消息权限:收紧板管内容处置,彻底删除仅站长,并统一管理删帖/评弹窗。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -41,6 +41,7 @@ import {
|
||||
type AdminContentStatus,
|
||||
type PublicSettings,
|
||||
} from "@/lib/api";
|
||||
import { canModerateAuthor } from "@/lib/roles";
|
||||
import { formatRelative } from "@/lib/format";
|
||||
import { toast } from "@/lib/toast";
|
||||
import { realtime, RT_MODERATION_CHANGED } from "@/lib/realtime";
|
||||
@@ -290,6 +291,8 @@ export default function ContentAdmin({
|
||||
initialCounts,
|
||||
initError,
|
||||
canConfigureSettings,
|
||||
canPurge,
|
||||
viewerRole,
|
||||
initialSettings,
|
||||
}: {
|
||||
initialKind: ContentKind;
|
||||
@@ -301,6 +304,8 @@ export default function ContentAdmin({
|
||||
initialCounts: AdminContentCounts;
|
||||
initError: string;
|
||||
canConfigureSettings: boolean;
|
||||
canPurge: boolean;
|
||||
viewerRole: string;
|
||||
initialSettings: PublicSettings;
|
||||
}) {
|
||||
// 窄屏分段:lg 以下只显示一栏;PC 双栏同时可见
|
||||
@@ -663,46 +668,50 @@ export default function ContentAdmin({
|
||||
) : null}
|
||||
{p.deleted ? (
|
||||
<>
|
||||
<ContentAction
|
||||
label="恢复"
|
||||
ok
|
||||
disabled={busy}
|
||||
icon={
|
||||
busy ? (
|
||||
<Loader2 size={13} className="animate-spin" />
|
||||
) : (
|
||||
<RotateCcw size={13} />
|
||||
)
|
||||
}
|
||||
onClick={() =>
|
||||
runAction(
|
||||
key,
|
||||
() => apiAdminRestorePost(p.id),
|
||||
"帖子已恢复",
|
||||
() => reloadPosts()
|
||||
)
|
||||
}
|
||||
/>
|
||||
<ContentAction
|
||||
label="清除"
|
||||
danger
|
||||
disabled={busy}
|
||||
icon={<Trash2 size={13} />}
|
||||
onClick={() =>
|
||||
askConfirm(
|
||||
"彻底删除帖子",
|
||||
`「${p.title}」将从数据库永久删除,且其下评论一并清除,不可撤销。`,
|
||||
() =>
|
||||
apiAdminPurgePost(p.id).then(() => {
|
||||
toast("帖子已彻底删除", "ok");
|
||||
reloadPosts();
|
||||
}),
|
||||
true
|
||||
)
|
||||
}
|
||||
/>
|
||||
{canModerateAuthor({ role: viewerRole }, p.user?.role) ? (
|
||||
<ContentAction
|
||||
label="恢复"
|
||||
ok
|
||||
disabled={busy}
|
||||
icon={
|
||||
busy ? (
|
||||
<Loader2 size={13} className="animate-spin" />
|
||||
) : (
|
||||
<RotateCcw size={13} />
|
||||
)
|
||||
}
|
||||
onClick={() =>
|
||||
runAction(
|
||||
key,
|
||||
() => apiAdminRestorePost(p.id),
|
||||
"帖子已恢复",
|
||||
() => reloadPosts()
|
||||
)
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
{canPurge ? (
|
||||
<ContentAction
|
||||
label="清除"
|
||||
danger
|
||||
disabled={busy}
|
||||
icon={<Trash2 size={13} />}
|
||||
onClick={() =>
|
||||
askConfirm(
|
||||
"彻底删除帖子",
|
||||
`「${p.title}」将从数据库永久删除,且其下评论一并清除,不可撤销。`,
|
||||
() =>
|
||||
apiAdminPurgePost(p.id).then(() => {
|
||||
toast("帖子已彻底删除", "ok");
|
||||
reloadPosts();
|
||||
}),
|
||||
true
|
||||
)
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
) : canModerateAuthor({ role: viewerRole }, p.user?.role) ? (
|
||||
<ContentAction
|
||||
label="删除"
|
||||
danger
|
||||
@@ -710,7 +719,7 @@ export default function ContentAdmin({
|
||||
icon={<Trash2 size={13} />}
|
||||
onClick={() => setStaffDeletePost(p)}
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -803,46 +812,50 @@ export default function ContentAdmin({
|
||||
/>
|
||||
{c.deleted ? (
|
||||
<>
|
||||
<ContentAction
|
||||
label="恢复"
|
||||
ok
|
||||
disabled={busy}
|
||||
icon={
|
||||
busy ? (
|
||||
<Loader2 size={13} className="animate-spin" />
|
||||
) : (
|
||||
<RotateCcw size={13} />
|
||||
)
|
||||
}
|
||||
onClick={() =>
|
||||
runAction(
|
||||
key,
|
||||
() => apiAdminRestoreComment(c.id),
|
||||
"评论已恢复",
|
||||
() => reloadComments()
|
||||
)
|
||||
}
|
||||
/>
|
||||
<ContentAction
|
||||
label="清除"
|
||||
danger
|
||||
disabled={busy}
|
||||
icon={<Trash2 size={13} />}
|
||||
onClick={() =>
|
||||
askConfirm(
|
||||
"彻底删除评论",
|
||||
"该评论将永久删除且不可恢复。",
|
||||
() =>
|
||||
apiAdminPurgeComment(c.id).then(() => {
|
||||
toast("评论已彻底删除", "ok");
|
||||
reloadComments();
|
||||
}),
|
||||
true
|
||||
)
|
||||
}
|
||||
/>
|
||||
{canModerateAuthor({ role: viewerRole }, c.user?.role) ? (
|
||||
<ContentAction
|
||||
label="恢复"
|
||||
ok
|
||||
disabled={busy}
|
||||
icon={
|
||||
busy ? (
|
||||
<Loader2 size={13} className="animate-spin" />
|
||||
) : (
|
||||
<RotateCcw size={13} />
|
||||
)
|
||||
}
|
||||
onClick={() =>
|
||||
runAction(
|
||||
key,
|
||||
() => apiAdminRestoreComment(c.id),
|
||||
"评论已恢复",
|
||||
() => reloadComments()
|
||||
)
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
{canPurge ? (
|
||||
<ContentAction
|
||||
label="清除"
|
||||
danger
|
||||
disabled={busy}
|
||||
icon={<Trash2 size={13} />}
|
||||
onClick={() =>
|
||||
askConfirm(
|
||||
"彻底删除评论",
|
||||
"该评论将永久删除且不可恢复。",
|
||||
() =>
|
||||
apiAdminPurgeComment(c.id).then(() => {
|
||||
toast("评论已彻底删除", "ok");
|
||||
reloadComments();
|
||||
}),
|
||||
true
|
||||
)
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
) : canModerateAuthor({ role: viewerRole }, c.user?.role) ? (
|
||||
<ContentAction
|
||||
label="删除"
|
||||
danger
|
||||
@@ -850,7 +863,7 @@ export default function ContentAdmin({
|
||||
icon={<Trash2 size={13} />}
|
||||
onClick={() => setStaffDeleteComment(c)}
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
type AdminContentStatus,
|
||||
} from "@/lib/api";
|
||||
import { getMeCached, getPublicSettingsCached } from "@/lib/serverData";
|
||||
import { canModerateAny, isSuperOrOwner } from "@/lib/roles";
|
||||
import { canModerateAny, isSuperOrOwner, isOwner } from "@/lib/roles";
|
||||
import Forbidden from "../Forbidden";
|
||||
import ContentAdmin, { type ContentKind } from "./ContentAdmin";
|
||||
|
||||
@@ -93,6 +93,8 @@ export default async function AdminContentPage({ searchParams }: ContentPageProp
|
||||
initialCounts={counts}
|
||||
initError={initError}
|
||||
canConfigureSettings={isSuperOrOwner(me.user.role)}
|
||||
canPurge={isOwner(me.user.role)}
|
||||
viewerRole={me.user.role}
|
||||
initialSettings={settings}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user