feat(评论系统): 新增评论审核功能及界面优化
实现新评论需审核后显示的功能,包括后台设置开关、API支持、前端状态提示 优化管理后台界面样式和分页组件 添加成功消息提示组件及样式 更新相关文档说明
This commit is contained in:
@@ -157,6 +157,9 @@ export class CWDComments {
|
||||
if (serverConfig.adminEnabled && serverConfig.adminBadge) {
|
||||
this.config.adminBadge = serverConfig.adminBadge;
|
||||
}
|
||||
if (typeof serverConfig.requireReview === 'boolean') {
|
||||
this.config.requireReview = serverConfig.requireReview;
|
||||
}
|
||||
|
||||
const api = createApiClient(this.config);
|
||||
this.api = api;
|
||||
@@ -256,6 +259,29 @@ export class CWDComments {
|
||||
existingError.remove();
|
||||
}
|
||||
|
||||
const existingSuccess = this.mountPoint.querySelector('.cwd-success-inline');
|
||||
if (state.successMessage) {
|
||||
if (!existingSuccess) {
|
||||
const successEl = document.createElement('div');
|
||||
successEl.className = 'cwd-success-inline';
|
||||
successEl.innerHTML = `
|
||||
<span>${state.successMessage}</span>
|
||||
<button type="button" class="cwd-error-close" data-action="clear-success">✕</button>
|
||||
`;
|
||||
successEl.querySelector('[data-action="clear-success"]').addEventListener('click', () => {
|
||||
this.store.clearSuccess();
|
||||
});
|
||||
this.mountPoint.insertBefore(successEl, this.mountPoint.firstChild);
|
||||
} else {
|
||||
const span = existingSuccess.querySelector('span');
|
||||
if (span) {
|
||||
span.textContent = state.successMessage;
|
||||
}
|
||||
}
|
||||
} else if (existingSuccess) {
|
||||
existingSuccess.remove();
|
||||
}
|
||||
|
||||
// 创建头部统计
|
||||
let header = this.mountPoint.querySelector('.cwd-comments-header');
|
||||
if (!header) {
|
||||
@@ -352,6 +378,29 @@ export class CWDComments {
|
||||
existingError.remove();
|
||||
}
|
||||
|
||||
const existingSuccess = this.mountPoint?.querySelector('.cwd-success-inline');
|
||||
if (state.successMessage) {
|
||||
if (!existingSuccess) {
|
||||
const successEl = document.createElement('div');
|
||||
successEl.className = 'cwd-success-inline';
|
||||
successEl.innerHTML = `
|
||||
<span>${state.successMessage}</span>
|
||||
<button type="button" class="cwd-error-close" data-action="clear-success">✕</button>
|
||||
`;
|
||||
successEl.querySelector('[data-action="clear-success"]').addEventListener('click', () => {
|
||||
this.store.clearSuccess();
|
||||
});
|
||||
this.mountPoint?.insertBefore(successEl, this.mountPoint.firstChild);
|
||||
} else {
|
||||
const span = existingSuccess.querySelector('span');
|
||||
if (span) {
|
||||
span.textContent = state.successMessage;
|
||||
}
|
||||
}
|
||||
} else if (existingSuccess) {
|
||||
existingSuccess.remove();
|
||||
}
|
||||
|
||||
// 更新头部统计
|
||||
const header = this.mountPoint?.querySelector('.cwd-comments-header');
|
||||
const countEl = header?.querySelector('.cwd-comments-count-number');
|
||||
|
||||
@@ -102,6 +102,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
comments: [],
|
||||
loading: true,
|
||||
error: null,
|
||||
successMessage: '',
|
||||
|
||||
// 分页
|
||||
pagination: {
|
||||
@@ -186,6 +187,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
formErrors: {},
|
||||
submitting: true,
|
||||
error: null,
|
||||
successMessage: '',
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -197,10 +199,14 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
adminToken: auth.getToken() // Add token if exists
|
||||
});
|
||||
|
||||
// 清空评论内容
|
||||
const successMessage = config.requireReview
|
||||
? '已提交评论,待管理员审核后显示'
|
||||
: '评论已提交';
|
||||
|
||||
store.setState({
|
||||
form: { ...form, content: '' },
|
||||
submitting: false,
|
||||
successMessage,
|
||||
});
|
||||
|
||||
// 重新加载评论
|
||||
@@ -210,6 +216,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
store.setState({
|
||||
error: e instanceof Error ? e.message : '提交评论失败',
|
||||
submitting: false,
|
||||
successMessage: '',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@@ -335,6 +342,12 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
});
|
||||
}
|
||||
|
||||
function clearSuccess() {
|
||||
store.setState({
|
||||
successMessage: '',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换页码
|
||||
* @param {number} page - 页码
|
||||
@@ -366,6 +379,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
updateReplyContent,
|
||||
clearReplyError,
|
||||
clearError,
|
||||
clearSuccess,
|
||||
goToPage,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -298,7 +298,6 @@
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid var(--cwd-border, #d0d7de);
|
||||
overflow: hidden;
|
||||
background: var(--cwd-bg-avatar, #f6f8fa)
|
||||
}
|
||||
@@ -660,6 +659,19 @@
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.cwd-success-inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
color: #1a7f37;
|
||||
background: #dafbe1;
|
||||
border: 1px solid #54ae65;
|
||||
border-radius: var(--cwd-radius, 6px);
|
||||
}
|
||||
|
||||
/* ========== 其他 ========== */
|
||||
.cwd-load-more {
|
||||
display: block;
|
||||
@@ -824,4 +836,4 @@
|
||||
|
||||
.cwd-btn-text:hover {
|
||||
color: var(--cwd-primary);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user