feat(plaza-ops): add post management API for admin console
Expose categories listing, category filter on review queue, and invalidate feed caches when ops hides a published post. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+72
-3
@@ -251,7 +251,69 @@ export function createPlazaPostService(
|
||||
};
|
||||
};
|
||||
|
||||
const createPost = async (userId, input) => {
|
||||
const findPostByPublicationId = async (publicationId, { userId = null } = {}) => {
|
||||
const params = [publicationId];
|
||||
let userClause = '';
|
||||
if (userId) {
|
||||
userClause = ' AND pp.user_id = ?';
|
||||
params.push(userId);
|
||||
}
|
||||
const [rows] = await pool.query(
|
||||
`SELECT pp.id, pp.status
|
||||
FROM plaza_posts pp
|
||||
WHERE pp.publication_id = ?${userClause} AND pp.status != 'hidden'
|
||||
LIMIT 1`,
|
||||
params,
|
||||
);
|
||||
return rows[0] ?? null;
|
||||
};
|
||||
|
||||
const republishExistingPost = async (userId, postId, options = {}) => {
|
||||
const now = Date.now();
|
||||
const status = autoApprove || options.forcePublished ? 'published' : 'pending_review';
|
||||
const hotScore = status === 'published' ? await resolveHotScore(now) : 0;
|
||||
const [result] = await pool.query(
|
||||
`UPDATE plaza_posts
|
||||
SET status = ?, hot_score = ?, hot_updated_at = ?, updated_at = ?, published_at = ?
|
||||
WHERE id = ? AND user_id = ? AND status IN ('hidden', 'rejected')`,
|
||||
[status, hotScore, status === 'published' ? now : null, now, now, postId, userId],
|
||||
);
|
||||
if (result.affectedRows === 0) {
|
||||
throw plazaError('帖子不存在或无法重新发布', 'POST_NOT_FOUND');
|
||||
}
|
||||
if (status === 'published') {
|
||||
await plazaRedis?.invalidateFeedCaches?.();
|
||||
if (options.deferPostPublishedHooks) {
|
||||
void onPostPublished?.(postId);
|
||||
} else {
|
||||
await onPostPublished?.(postId);
|
||||
}
|
||||
}
|
||||
return { id: postId, status };
|
||||
};
|
||||
|
||||
const publishPostForPublication = async (userId, input, options = {}) => {
|
||||
const publicationId = String(input?.publication_id ?? '').trim();
|
||||
if (!publicationId) throw plazaError('publication_id 不能为空', 'invalid_input');
|
||||
|
||||
const [existingRows] = await pool.query(
|
||||
`SELECT id, status FROM plaza_posts WHERE publication_id = ? AND user_id = ? LIMIT 1`,
|
||||
[publicationId, userId],
|
||||
);
|
||||
const existing = existingRows[0];
|
||||
if (existing) {
|
||||
if (existing.status === 'published' || existing.status === 'pending_review') {
|
||||
throw plazaError('该内容已发布到广场', 'ALREADY_PUBLISHED', { post_id: existing.id });
|
||||
}
|
||||
if (existing.status === 'hidden' || existing.status === 'rejected') {
|
||||
return republishExistingPost(userId, existing.id, options);
|
||||
}
|
||||
}
|
||||
|
||||
return createPost(userId, input, options);
|
||||
};
|
||||
|
||||
const createPost = async (userId, input, options = {}) => {
|
||||
const publicationId = String(input?.publication_id ?? '').trim();
|
||||
if (!publicationId) throw plazaError('publication_id 不能为空', 'invalid_input');
|
||||
|
||||
@@ -269,7 +331,7 @@ export function createPlazaPostService(
|
||||
const allowComment = input?.allow_comment == null ? true : Boolean(input.allow_comment);
|
||||
const now = Date.now();
|
||||
const postId = idFactory();
|
||||
const status = autoApprove ? 'published' : 'pending_review';
|
||||
const status = autoApprove || options.forcePublished ? 'published' : 'pending_review';
|
||||
const hotScore = status === 'published' ? await resolveHotScore(now) : 0;
|
||||
|
||||
const conn = await pool.getConnection();
|
||||
@@ -317,7 +379,11 @@ export function createPlazaPostService(
|
||||
|
||||
if (status === 'published') {
|
||||
await plazaRedis?.invalidateFeedCaches?.();
|
||||
await onPostPublished?.(postId);
|
||||
if (options.deferPostPublishedHooks) {
|
||||
void onPostPublished?.(postId);
|
||||
} else {
|
||||
await onPostPublished?.(postId);
|
||||
}
|
||||
}
|
||||
|
||||
return { id: postId, status };
|
||||
@@ -591,6 +657,7 @@ export function createPlazaPostService(
|
||||
`UPDATE plaza_posts SET status = 'hidden', updated_at = ? WHERE id = ?`,
|
||||
[now, postId],
|
||||
);
|
||||
await plazaRedis?.invalidateFeedCaches?.();
|
||||
return { id: postId, status: 'hidden' };
|
||||
}
|
||||
throw plazaError('不支持的审核操作', 'invalid_input');
|
||||
@@ -619,6 +686,8 @@ export function createPlazaPostService(
|
||||
ensureCategories,
|
||||
listCategories,
|
||||
createPost,
|
||||
publishPostForPublication,
|
||||
findPostByPublicationId,
|
||||
updatePost,
|
||||
hidePost,
|
||||
hidePostsByPublicationId,
|
||||
|
||||
Reference in New Issue
Block a user