feat: 帖子全局/板块置顶支持权重排序,优化列表与详情渲染
This commit is contained in:
@@ -806,7 +806,8 @@ export default function PostDetailPage() {
|
||||
const handlePin = async () => {
|
||||
if (!post) return;
|
||||
try {
|
||||
const r = await api.adminPinPost(postId, !post.pinned);
|
||||
const next = post.pinned > 0 ? 0 : 1;
|
||||
const r = await api.adminPinPost(postId, next);
|
||||
setPost(p => p ? { ...p, pinned: r.pinned } : p);
|
||||
clearAllFeedCache();
|
||||
window.dispatchEvent(new Event('posts-refresh'));
|
||||
@@ -819,7 +820,8 @@ export default function PostDetailPage() {
|
||||
const handleBoardPin = async () => {
|
||||
if (!post) return;
|
||||
try {
|
||||
const r = await api.adminBoardPinPost(postId, !post.board_pinned);
|
||||
const next = (post.board_pinned ?? 0) > 0 ? 0 : 1;
|
||||
const r = await api.adminBoardPinPost(postId, next);
|
||||
setPost(p => p ? { ...p, board_pinned: r.board_pinned } : p);
|
||||
clearAllFeedCache();
|
||||
window.dispatchEvent(new Event('posts-refresh'));
|
||||
@@ -995,10 +997,10 @@ export default function PostDetailPage() {
|
||||
|
||||
<div className="post-detail-head">
|
||||
<h1 className="post-detail-title">
|
||||
{post.pinned && (
|
||||
{post.pinned > 0 && (
|
||||
<span className="post-pin-badge post-pin-badge--detail" title="全局置顶">全局置顶</span>
|
||||
)}
|
||||
{post.board_pinned && (
|
||||
{(post.board_pinned ?? 0) > 0 && (
|
||||
<span className="post-pin-badge post-pin-badge--board post-pin-badge--detail" title="板块置顶">板块置顶</span>
|
||||
)}
|
||||
{post.featured && <FeaturedIcon className="mr-2" size={18} />}
|
||||
|
||||
@@ -246,9 +246,9 @@ export default function AdminDashboardPage() {
|
||||
</td>
|
||||
<td className="space-x-1">
|
||||
{p.featured ? <Badge variant="orange">推荐</Badge> : null}
|
||||
{p.pinned ? <Badge variant="green">全局置顶</Badge> : null}
|
||||
{p.board_pinned ? <Badge variant="green">板块置顶</Badge> : null}
|
||||
{!p.featured && !p.pinned && !p.board_pinned ? '—' : null}
|
||||
{p.pinned > 0 ? <Badge variant="green">全局置顶</Badge> : null}
|
||||
{(p.board_pinned ?? 0) > 0 ? <Badge variant="green">板块置顶</Badge> : null}
|
||||
{!p.featured && p.pinned <= 0 && (p.board_pinned ?? 0) <= 0 ? '—' : null}
|
||||
</td>
|
||||
<td>{new Date(p.created_at).toLocaleString('zh-CN')}</td>
|
||||
</tr>
|
||||
|
||||
@@ -141,9 +141,13 @@ export default function AdminPostsPage() {
|
||||
setSearch('');
|
||||
};
|
||||
|
||||
const togglePin = async (post: PostItem) => {
|
||||
const togglePin = async (post: PostItem, nextValue?: number) => {
|
||||
try {
|
||||
const r = await api.adminPinPost(post.id, !post.pinned);
|
||||
let value = nextValue;
|
||||
if (value === undefined) {
|
||||
value = post.pinned > 0 ? 0 : 1;
|
||||
}
|
||||
const r = await api.adminPinPost(post.id, value);
|
||||
clearAllFeedCache();
|
||||
window.dispatchEvent(new Event('posts-refresh'));
|
||||
notify.success(r.message);
|
||||
@@ -153,9 +157,13 @@ export default function AdminPostsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleBoardPin = async (post: PostItem) => {
|
||||
const toggleBoardPin = async (post: PostItem, nextValue?: number) => {
|
||||
try {
|
||||
const r = await api.adminBoardPinPost(post.id, !post.board_pinned);
|
||||
let value = nextValue;
|
||||
if (value === undefined) {
|
||||
value = (post.board_pinned ?? 0) > 0 ? 0 : 1;
|
||||
}
|
||||
const r = await api.adminBoardPinPost(post.id, value);
|
||||
clearAllFeedCache();
|
||||
window.dispatchEvent(new Event('posts-refresh'));
|
||||
notify.success(r.message);
|
||||
@@ -417,8 +425,8 @@ export default function AdminPostsPage() {
|
||||
<td className="max-w-[120px] truncate text-muted-foreground">{p.tags || '—'}</td>
|
||||
<td>{p.comment_count ?? 0}</td>
|
||||
<td>{p.featured ? <Badge variant="orange">是</Badge> : '—'}</td>
|
||||
<td>{p.pinned ? <Badge variant="green">是</Badge> : '—'}</td>
|
||||
<td>{p.board_pinned ? <Badge variant="green">是</Badge> : '—'}</td>
|
||||
<td>{p.pinned > 0 ? <Badge variant="green">置顶 {p.pinned}</Badge> : '—'}</td>
|
||||
<td>{(p.board_pinned ?? 0) > 0 ? <Badge variant="green">置顶 {p.board_pinned}</Badge> : '—'}</td>
|
||||
<td>{p.edit_locked ? <Badge variant="destructive">是</Badge> : '—'}</td>
|
||||
<td>{p.comments_locked ? <Badge variant="destructive">是</Badge> : '—'}</td>
|
||||
<td>{p.like_count}</td>
|
||||
@@ -444,11 +452,55 @@ export default function AdminPostsPage() {
|
||||
<Button size="sm" variant="outline" onClick={() => toggleFeature(p)}>
|
||||
{p.featured ? '取消推荐' : '推荐'}
|
||||
</Button>
|
||||
<Button size="sm" variant="outline" onClick={() => togglePin(p)}>
|
||||
{p.pinned ? '取消全局置顶' : '全局置顶'}
|
||||
<Button size="sm" variant="outline" onClick={() => {
|
||||
const cur = p.pinned;
|
||||
if (cur > 0) {
|
||||
// 已置顶:弹出输入框让管理员调整顺序值
|
||||
const input = window.prompt(`全局置顶顺序(当前: ${cur},输入 0 取消置顶)`, String(cur));
|
||||
if (input == null) return;
|
||||
const n = parseInt(input, 10);
|
||||
if (Number.isNaN(n) || n < 0) {
|
||||
notify.warning('请输入有效的非负整数');
|
||||
return;
|
||||
}
|
||||
void togglePin(p, n);
|
||||
} else {
|
||||
// 未置顶:输入框让管理员设置初始值
|
||||
const input = window.prompt('设置全局置顶顺序(输入 1 即置顶,0 表示不置顶)', '1');
|
||||
if (input == null) return;
|
||||
const n = parseInt(input, 10);
|
||||
if (Number.isNaN(n) || n < 0) {
|
||||
notify.warning('请输入有效的非负整数');
|
||||
return;
|
||||
}
|
||||
void togglePin(p, n);
|
||||
}
|
||||
}}>
|
||||
{p.pinned > 0 ? `全局置顶(${p.pinned})` : '全局置顶'}
|
||||
</Button>
|
||||
<Button size="sm" variant="outline" onClick={() => toggleBoardPin(p)}>
|
||||
{p.board_pinned ? '取消板块置顶' : '板块置顶'}
|
||||
<Button size="sm" variant="outline" onClick={() => {
|
||||
const cur = p.board_pinned ?? 0;
|
||||
if (cur > 0) {
|
||||
const input = window.prompt(`板块置顶顺序(当前: ${cur},输入 0 取消置顶)`, String(cur));
|
||||
if (input == null) return;
|
||||
const n = parseInt(input, 10);
|
||||
if (Number.isNaN(n) || n < 0) {
|
||||
notify.warning('请输入有效的非负整数');
|
||||
return;
|
||||
}
|
||||
void toggleBoardPin(p, n);
|
||||
} else {
|
||||
const input = window.prompt('设置板块置顶顺序(输入 1 即置顶,0 表示不置顶)', '1');
|
||||
if (input == null) return;
|
||||
const n = parseInt(input, 10);
|
||||
if (Number.isNaN(n) || n < 0) {
|
||||
notify.warning('请输入有效的非负整数');
|
||||
return;
|
||||
}
|
||||
void toggleBoardPin(p, n);
|
||||
}
|
||||
}}>
|
||||
{(p.board_pinned ?? 0) > 0 ? `板块置顶(${p.board_pinned})` : '板块置顶'}
|
||||
</Button>
|
||||
<Button size="sm" variant="outline" onClick={() => toggleLock(p)}>
|
||||
{p.edit_locked ? <><LockOpen size={14} /> 解锁编辑</> : <><Lock size={14} /> 锁定编辑</>}
|
||||
|
||||
Reference in New Issue
Block a user