feat(comments): 实现评论点赞功能
- 在数据库和API中添加likes字段支持 - 新增评论点赞接口和前端交互逻辑 - 在前端展示点赞数并处理点赞操作 - 更新相关组件和存储逻辑以支持点赞功能
This commit is contained in:
@@ -19,6 +19,7 @@ export type CommentItem = {
|
|||||||
contentHtml: string;
|
contentHtml: string;
|
||||||
status: string;
|
status: string;
|
||||||
priority?: number;
|
priority?: number;
|
||||||
|
likes?: number;
|
||||||
ua?: string | null;
|
ua?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
<div class="table-cell table-cell-author">用户</div>
|
<div class="table-cell table-cell-author">用户</div>
|
||||||
<div class="table-cell table-cell-content">评论信息</div>
|
<div class="table-cell table-cell-content">评论信息</div>
|
||||||
<div class="table-cell table-cell-path">评论地址</div>
|
<div class="table-cell table-cell-path">评论地址</div>
|
||||||
|
<div class="table-cell table-cell-likes">点赞</div>
|
||||||
<div class="table-cell table-cell-status">状态</div>
|
<div class="table-cell table-cell-status">状态</div>
|
||||||
<div class="table-cell table-cell-actions">操作</div>
|
<div class="table-cell table-cell-actions">操作</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,6 +70,9 @@
|
|||||||
>{{ item.postSlug }}</a
|
>{{ item.postSlug }}</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="table-cell table-cell-likes">
|
||||||
|
<span class="cell-likes-number">{{ typeof item.likes === "number" && Number.isFinite(item.likes) && item.likes >= 0 ? item.likes : 0 }}</span>
|
||||||
|
</div>
|
||||||
<div class="table-cell table-cell-status">
|
<div class="table-cell table-cell-status">
|
||||||
<div class="cell-status-wrapper">
|
<div class="cell-status-wrapper">
|
||||||
<span class="cell-status" :class="`cell-status-${item.status}`">
|
<span class="cell-status" :class="`cell-status-${item.status}`">
|
||||||
@@ -676,6 +680,12 @@ watch(domainFilter, () => {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-cell-likes {
|
||||||
|
width: 80px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.table-cell-time {
|
.table-cell-time {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -755,6 +765,11 @@ watch(domainFilter, () => {
|
|||||||
color: #57606a;
|
color: #57606a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cell-likes-number {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #57606a;
|
||||||
|
}
|
||||||
|
|
||||||
.cell-author-wrapper {
|
.cell-author-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS Comment (
|
|||||||
content_text TEXT NOT NULL,
|
content_text TEXT NOT NULL,
|
||||||
content_html TEXT NOT NULL,
|
content_html TEXT NOT NULL,
|
||||||
parent_id INTEGER,
|
parent_id INTEGER,
|
||||||
|
likes INTEGER NOT NULL DEFAULT 0,
|
||||||
priority INTEGER NOT NULL DEFAULT 1,
|
priority INTEGER NOT NULL DEFAULT 1,
|
||||||
status TEXT DEFAULT 'approved',
|
status TEXT DEFAULT 'approved',
|
||||||
-- 建立自引用外键约束(父子评论关系)
|
-- 建立自引用外键约束(父子评论关系)
|
||||||
|
|||||||
@@ -119,13 +119,14 @@ export const importComments = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
content_text,
|
content_text,
|
||||||
content_html,
|
content_html,
|
||||||
parent_id,
|
parent_id,
|
||||||
status
|
status,
|
||||||
|
likes
|
||||||
} = comment;
|
} = comment;
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
'created', 'post_slug', 'name', 'email', 'url',
|
'created', 'post_slug', 'name', 'email', 'url',
|
||||||
'ip_address', 'device', 'os', 'browser', 'ua',
|
'ip_address', 'device', 'os', 'browser', 'ua',
|
||||||
'content_text', 'content_html', 'parent_id', 'status'
|
'content_text', 'content_html', 'parent_id', 'status', 'likes'
|
||||||
];
|
];
|
||||||
const values = [
|
const values = [
|
||||||
created || Date.now(),
|
created || Date.now(),
|
||||||
@@ -141,7 +142,8 @@ export const importComments = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
content_text || "",
|
content_text || "",
|
||||||
content_html || "",
|
content_html || "",
|
||||||
parent_id || null,
|
parent_id || null,
|
||||||
status || "approved"
|
status || "approved",
|
||||||
|
typeof likes === 'number' && Number.isFinite(likes) && likes >= 0 ? likes : 0
|
||||||
];
|
];
|
||||||
|
|
||||||
if (id !== undefined && id !== null) {
|
if (id !== undefined && id !== null) {
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export const listComments = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
contentHtml: row.content_html,
|
contentHtml: row.content_html,
|
||||||
status: row.status,
|
status: row.status,
|
||||||
priority: row.priority,
|
priority: row.priority,
|
||||||
|
likes: typeof row.likes === 'number' && Number.isFinite(row.likes) && row.likes >= 0 ? row.likes : 0,
|
||||||
ua: row.ua,
|
ua: row.ua,
|
||||||
avatar: await getCravatar(row.email, avatarPrefix || undefined)
|
avatar: await getCravatar(row.email, avatarPrefix || undefined)
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export const getComments = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
let query = `
|
let query = `
|
||||||
SELECT id, name, email, url, content_text as contentText,
|
SELECT id, name, email, url, content_text as contentText,
|
||||||
content_html as contentHtml, created, parent_id as parentId,
|
content_html as contentHtml, created, parent_id as parentId,
|
||||||
post_slug as postSlug, priority
|
post_slug as postSlug, priority, COALESCE(likes, 0) as likes
|
||||||
FROM Comment
|
FROM Comment
|
||||||
WHERE status = "approved" AND post_slug = ?
|
WHERE status = "approved" AND post_slug = ?
|
||||||
ORDER BY priority DESC, created DESC
|
ORDER BY priority DESC, created DESC
|
||||||
@@ -46,7 +46,7 @@ export const getComments = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
query = `
|
query = `
|
||||||
SELECT id, name, email, url, content_text as contentText,
|
SELECT id, name, email, url, content_text as contentText,
|
||||||
content_html as contentHtml, created, parent_id as parentId,
|
content_html as contentHtml, created, parent_id as parentId,
|
||||||
post_slug as postSlug, priority
|
post_slug as postSlug, priority, COALESCE(likes, 0) as likes
|
||||||
FROM Comment
|
FROM Comment
|
||||||
WHERE status = "approved" AND post_slug IN (${placeholders})
|
WHERE status = "approved" AND post_slug IN (${placeholders})
|
||||||
ORDER BY priority DESC, created DESC
|
ORDER BY priority DESC, created DESC
|
||||||
|
|||||||
64
cwd-api/src/api/public/likeComment.ts
Normal file
64
cwd-api/src/api/public/likeComment.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { Context } from 'hono';
|
||||||
|
import { Bindings } from '../../bindings';
|
||||||
|
|
||||||
|
export const likeComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||||
|
let body: any = null;
|
||||||
|
try {
|
||||||
|
body = await c.req.json();
|
||||||
|
} catch {
|
||||||
|
body = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawId =
|
||||||
|
(body && (body.id ?? body.commentId)) ??
|
||||||
|
c.req.query('id') ??
|
||||||
|
c.req.query('commentId') ??
|
||||||
|
null;
|
||||||
|
|
||||||
|
const parsed =
|
||||||
|
typeof rawId === 'number'
|
||||||
|
? rawId
|
||||||
|
: typeof rawId === 'string' && rawId.trim()
|
||||||
|
? Number.parseInt(rawId.trim(), 10)
|
||||||
|
: NaN;
|
||||||
|
|
||||||
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
||||||
|
return c.json({ message: 'Missing or invalid id' }, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = parsed;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const existing = await c.env.CWD_DB.prepare(
|
||||||
|
'SELECT id, likes FROM Comment WHERE id = ?'
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.first<{ id: number; likes?: number }>();
|
||||||
|
|
||||||
|
if (!existing) {
|
||||||
|
return c.json({ message: 'Comment not found' }, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
await c.env.CWD_DB.prepare(
|
||||||
|
'UPDATE Comment SET likes = COALESCE(likes, 0) + 1 WHERE id = ?'
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
const updated = await c.env.CWD_DB.prepare(
|
||||||
|
'SELECT COALESCE(likes, 0) as likes FROM Comment WHERE id = ?'
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.first<{ likes?: number }>();
|
||||||
|
|
||||||
|
const likes =
|
||||||
|
updated && typeof updated.likes === 'number' && Number.isFinite(updated.likes) && updated.likes >= 0
|
||||||
|
? updated.likes
|
||||||
|
: ((existing.likes || 0) + 1);
|
||||||
|
|
||||||
|
return c.json({ id, likes });
|
||||||
|
} catch (e: any) {
|
||||||
|
return c.json({ message: e?.message || '点赞失败' }, 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ import { getDomains } from './api/admin/getDomains';
|
|||||||
import { trackVisit } from './api/public/trackVisit';
|
import { trackVisit } from './api/public/trackVisit';
|
||||||
import { getVisitOverview, getVisitPages } from './api/admin/visitAnalytics';
|
import { getVisitOverview, getVisitPages } from './api/admin/visitAnalytics';
|
||||||
import { getLikeStatus, likePage } from './api/public/like';
|
import { getLikeStatus, likePage } from './api/public/like';
|
||||||
|
import { likeComment } from './api/public/likeComment';
|
||||||
import { listLikes } from './api/admin/listLikes';
|
import { listLikes } from './api/admin/listLikes';
|
||||||
import { getLikeStats } from './api/admin/likeStats';
|
import { getLikeStats } from './api/admin/likeStats';
|
||||||
|
|
||||||
@@ -223,6 +224,7 @@ app.post('/api/verify-admin', verifyAdminKey);
|
|||||||
app.post('/api/analytics/visit', trackVisit);
|
app.post('/api/analytics/visit', trackVisit);
|
||||||
app.get('/api/like', getLikeStatus);
|
app.get('/api/like', getLikeStatus);
|
||||||
app.post('/api/like', likePage);
|
app.post('/api/like', likePage);
|
||||||
|
app.post('/api/comments/like', likeComment);
|
||||||
app.get('/api/config/comments', async (c) => {
|
app.get('/api/config/comments', async (c) => {
|
||||||
try {
|
try {
|
||||||
const settings = await loadCommentSettings(c.env);
|
const settings = await loadCommentSettings(c.env);
|
||||||
|
|||||||
@@ -105,6 +105,28 @@ export class CommentItem extends Component {
|
|||||||
},
|
},
|
||||||
text: '回复'
|
text: '回复'
|
||||||
}),
|
}),
|
||||||
|
this.createElement('span', {
|
||||||
|
className: 'cwd-comment-like',
|
||||||
|
children: [
|
||||||
|
this.createElement('button', {
|
||||||
|
className: 'cwd-comment-like-button',
|
||||||
|
attributes: {
|
||||||
|
type: 'button',
|
||||||
|
onClick: () => this.handleLikeComment()
|
||||||
|
},
|
||||||
|
text: '赞'
|
||||||
|
}),
|
||||||
|
this.createTextElement(
|
||||||
|
'span',
|
||||||
|
String(
|
||||||
|
typeof comment.likes === 'number' && Number.isFinite(comment.likes) && comment.likes >= 0
|
||||||
|
? comment.likes
|
||||||
|
: 0
|
||||||
|
),
|
||||||
|
'cwd-comment-like-count'
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}),
|
||||||
this.createTextElement('span', formatRelativeTime(comment.created), 'cwd-comment-time')
|
this.createTextElement('span', formatRelativeTime(comment.created), 'cwd-comment-time')
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@@ -259,6 +281,12 @@ export class CommentItem extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLikeComment() {
|
||||||
|
if (this.props.onLikeComment) {
|
||||||
|
this.props.onLikeComment(this.props.comment.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleSubmitReply() {
|
handleSubmitReply() {
|
||||||
if (this.props.onSubmitReply) {
|
if (this.props.onSubmitReply) {
|
||||||
this.props.onSubmitReply(this.props.comment.id);
|
this.props.onSubmitReply(this.props.comment.id);
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ export class CommentList extends Component {
|
|||||||
onSubmitReply: (commentId) => this.handleSubmitReply(commentId),
|
onSubmitReply: (commentId) => this.handleSubmitReply(commentId),
|
||||||
onCancelReply: () => this.handleCancelReply(),
|
onCancelReply: () => this.handleCancelReply(),
|
||||||
onUpdateReplyContent: (content) => this.handleUpdateReplyContent(content),
|
onUpdateReplyContent: (content) => this.handleUpdateReplyContent(content),
|
||||||
onClearReplyError: () => this.handleClearReplyError()
|
onClearReplyError: () => this.handleClearReplyError(),
|
||||||
|
onLikeComment: (commentId) => this.handleLikeComment(commentId)
|
||||||
});
|
});
|
||||||
commentItem.render();
|
commentItem.render();
|
||||||
// 缓存 CommentItem 实例
|
// 缓存 CommentItem 实例
|
||||||
@@ -219,6 +220,12 @@ export class CommentList extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLikeComment(commentId) {
|
||||||
|
if (this.props.onLikeComment) {
|
||||||
|
this.props.onLikeComment(commentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handlePrevPage() {
|
handlePrevPage() {
|
||||||
if (this.props.onPrevPage) {
|
if (this.props.onPrevPage) {
|
||||||
this.props.onPrevPage();
|
this.props.onPrevPage();
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ export class CWDComments {
|
|||||||
this.store = createCommentStore(
|
this.store = createCommentStore(
|
||||||
this.config,
|
this.config,
|
||||||
api.fetchComments.bind(api),
|
api.fetchComments.bind(api),
|
||||||
api.submitComment.bind(api)
|
api.submitComment.bind(api),
|
||||||
|
typeof api.likeComment === 'function' ? api.likeComment.bind(api) : undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
this.unsubscribe = this.store.store.subscribe((state) => {
|
this.unsubscribe = this.store.store.subscribe((state) => {
|
||||||
@@ -379,6 +380,11 @@ export class CWDComments {
|
|||||||
onPrevPage: () => this.store.goToPage(state.pagination.page - 1),
|
onPrevPage: () => this.store.goToPage(state.pagination.page - 1),
|
||||||
onNextPage: () => this.store.goToPage(state.pagination.page + 1),
|
onNextPage: () => this.store.goToPage(state.pagination.page + 1),
|
||||||
onGoToPage: (page) => this.store.goToPage(page),
|
onGoToPage: (page) => this.store.goToPage(page),
|
||||||
|
onLikeComment: (commentId) => {
|
||||||
|
if (this.store && typeof this.store.likeComment === 'function') {
|
||||||
|
this.store.likeComment(commentId);
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
this.commentList.render();
|
this.commentList.render();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
* @param {string} config.postSlug - 文章标识符
|
* @param {string} config.postSlug - 文章标识符
|
||||||
* @param {string} config.postTitle - 文章标题(可选)
|
* @param {string} config.postTitle - 文章标题(可选)
|
||||||
* @param {string} config.postUrl - 文章 URL(可选)
|
* @param {string} config.postUrl - 文章 URL(可选)
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
export function createApiClient(config) {
|
export function createApiClient(config) {
|
||||||
const baseUrl = config.apiBaseUrl.replace(/\/$/, '');
|
const baseUrl = config.apiBaseUrl.replace(/\/$/, '');
|
||||||
@@ -178,12 +178,41 @@ export function createApiClient(config) {
|
|||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
async function likeComment(commentId) {
|
||||||
|
const id =
|
||||||
|
typeof commentId === 'number'
|
||||||
|
? commentId
|
||||||
|
: typeof commentId === 'string' && commentId.trim()
|
||||||
|
? Number.parseInt(commentId.trim(), 10)
|
||||||
|
: NaN;
|
||||||
|
if (!Number.isFinite(id) || id <= 0) {
|
||||||
|
throw new Error('Invalid comment id');
|
||||||
|
}
|
||||||
|
const response = await fetch(`${baseUrl}/api/comments/like`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ id })
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
let msg = response.statusText;
|
||||||
|
try {
|
||||||
|
const json = await response.json();
|
||||||
|
if (json.message) msg = json.message;
|
||||||
|
} catch (e) {}
|
||||||
|
throw new Error(msg);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
fetchComments,
|
fetchComments,
|
||||||
submitComment,
|
submitComment,
|
||||||
verifyAdminKey,
|
verifyAdminKey,
|
||||||
trackVisit,
|
trackVisit,
|
||||||
getLikeStatus,
|
getLikeStatus,
|
||||||
likePage
|
likePage,
|
||||||
|
likeComment
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,9 +90,10 @@ class Store {
|
|||||||
* @param {Object} config - 配置对象
|
* @param {Object} config - 配置对象
|
||||||
* @param {Function} fetchComments - 获取评论的函数
|
* @param {Function} fetchComments - 获取评论的函数
|
||||||
* @param {Function} submitComment - 提交评论的函数
|
* @param {Function} submitComment - 提交评论的函数
|
||||||
|
* @param {Function} likeCommentFn - 点赞评论的函数
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
export function createCommentStore(config, fetchComments, submitComment) {
|
export function createCommentStore(config, fetchComments, submitComment, likeCommentFn) {
|
||||||
// 从 localStorage 加载用户信息
|
// 从 localStorage 加载用户信息
|
||||||
const savedInfo = loadUserInfo();
|
const savedInfo = loadUserInfo();
|
||||||
|
|
||||||
@@ -128,6 +129,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
|||||||
replyError: null,
|
replyError: null,
|
||||||
likeCount: 0,
|
likeCount: 0,
|
||||||
liked: false,
|
liked: false,
|
||||||
|
commentLikeLoadingId: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听用户信息变化,自动保存到 localStorage
|
// 监听用户信息变化,自动保存到 localStorage
|
||||||
@@ -175,6 +177,78 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function likeComment(commentId) {
|
||||||
|
const state = store.getState();
|
||||||
|
if (!likeCommentFn || state.commentLikeLoadingId === commentId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id =
|
||||||
|
typeof commentId === 'number'
|
||||||
|
? commentId
|
||||||
|
: typeof commentId === 'string' && commentId.trim()
|
||||||
|
? Number.parseInt(commentId.trim(), 10)
|
||||||
|
: NaN;
|
||||||
|
if (!Number.isFinite(id) || id <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
store.setState({
|
||||||
|
commentLikeLoadingId: id,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const safeComments = Array.isArray(state.comments) ? state.comments : [];
|
||||||
|
const nextComments = safeComments.map((item) => {
|
||||||
|
if (!item || typeof item.id !== 'number') {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
if (item.id === id) {
|
||||||
|
const current =
|
||||||
|
typeof item.likes === 'number' && Number.isFinite(item.likes) && item.likes >= 0
|
||||||
|
? item.likes
|
||||||
|
: 0;
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
likes: current + 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (Array.isArray(item.replies) && item.replies.length > 0) {
|
||||||
|
const updatedReplies = item.replies.map((reply) => {
|
||||||
|
if (!reply || typeof reply.id !== 'number') {
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
if (reply.id === id) {
|
||||||
|
const current =
|
||||||
|
typeof reply.likes === 'number' && Number.isFinite(reply.likes) && reply.likes >= 0
|
||||||
|
? reply.likes
|
||||||
|
: 0;
|
||||||
|
return {
|
||||||
|
...reply,
|
||||||
|
likes: current + 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
replies: updatedReplies,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
store.setState({
|
||||||
|
comments: nextComments,
|
||||||
|
});
|
||||||
|
await likeCommentFn(id);
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
const latest = store.getState();
|
||||||
|
if (latest.commentLikeLoadingId === id) {
|
||||||
|
store.setState({
|
||||||
|
commentLikeLoadingId: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交评论
|
* 提交评论
|
||||||
*/
|
*/
|
||||||
@@ -395,5 +469,6 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
|||||||
clearSuccess,
|
clearSuccess,
|
||||||
goToPage,
|
goToPage,
|
||||||
setLikeState,
|
setLikeState,
|
||||||
|
likeComment,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user