refactor(comment): 统一字段命名并改用时间戳存储创建时间
将 author 字段重命名为 name,pub_date 改为 created 并使用时间戳存储 更新相关 API、数据库 schema 和前端组件以适配新字段 同时将 user_agent 简化为 ua 并改进日期处理逻辑
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -8,8 +8,8 @@ export type AdminLoginResponse = {
|
||||
|
||||
export type CommentItem = {
|
||||
id: number;
|
||||
pubDate: string;
|
||||
author: string;
|
||||
created: number;
|
||||
name: string;
|
||||
email: string;
|
||||
avatar: string;
|
||||
postSlug: string;
|
||||
@@ -18,6 +18,7 @@ export type CommentItem = {
|
||||
contentText: string;
|
||||
contentHtml: string;
|
||||
status: string;
|
||||
ua?: string | null;
|
||||
};
|
||||
|
||||
export type CommentListResponse = {
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
v-if="item.avatar"
|
||||
:src="item.avatar"
|
||||
class="cell-avatar"
|
||||
:alt="item.author"
|
||||
:alt="item.name"
|
||||
/>
|
||||
<div class="cell-author-main">
|
||||
<div class="cell-author-name">{{ item.author }}</div>
|
||||
<div class="cell-author-name">{{ item.name }}</div>
|
||||
<div class="cell-author-email">{{ item.email }}</div>
|
||||
<span class="cell-time">{{ formatDate(item.pubDate) }}</span>
|
||||
<span class="cell-time">{{ formatDate(item.created) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -138,10 +138,10 @@ const filteredComments = computed(() => {
|
||||
return comments.value.filter((item) => item.status === statusFilter.value);
|
||||
});
|
||||
|
||||
function formatDate(value: string) {
|
||||
function formatDate(value: number) {
|
||||
const d = new Date(value);
|
||||
if (Number.isNaN(d.getTime())) {
|
||||
return value;
|
||||
return String(value);
|
||||
}
|
||||
return d.toLocaleString();
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
-- create comment table
|
||||
CREATE TABLE IF NOT EXISTS Comment (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
pub_date DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
created INTEGER NOT NULL,
|
||||
post_slug TEXT NOT NULL,
|
||||
author TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
url TEXT,
|
||||
ip_address TEXT,
|
||||
device TEXT,
|
||||
os TEXT,
|
||||
browser TEXT,
|
||||
user_agent TEXT,
|
||||
ua TEXT,
|
||||
content_text TEXT NOT NULL,
|
||||
content_html TEXT NOT NULL,
|
||||
parent_id INTEGER,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Bindings } from '../../bindings';
|
||||
export const exportComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
try {
|
||||
const { results } = await c.env.CWD_DB.prepare(
|
||||
'SELECT * FROM Comment ORDER BY pub_date DESC'
|
||||
'SELECT * FROM Comment ORDER BY created DESC'
|
||||
).all();
|
||||
|
||||
return c.json(results);
|
||||
|
||||
@@ -25,16 +25,16 @@ export const importComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
const stmts = comments.map((comment: any) => {
|
||||
const {
|
||||
id,
|
||||
pub_date,
|
||||
created,
|
||||
post_slug,
|
||||
author,
|
||||
name,
|
||||
email,
|
||||
url,
|
||||
ip_address,
|
||||
device,
|
||||
os,
|
||||
browser,
|
||||
user_agent,
|
||||
ua,
|
||||
content_text,
|
||||
content_html,
|
||||
parent_id,
|
||||
@@ -48,15 +48,26 @@ export const importComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
// 构建 SQL。
|
||||
// 能够处理 id 存在或不存在的情况
|
||||
const fields = [
|
||||
'pub_date', 'post_slug', 'author', 'email', 'url',
|
||||
'ip_address', 'device', 'os', 'browser', 'user_agent',
|
||||
'created', 'post_slug', 'name', 'email', 'url',
|
||||
'ip_address', 'device', 'os', 'browser', 'ua',
|
||||
'content_text', 'content_html', 'parent_id', 'status'
|
||||
];
|
||||
const values = [
|
||||
pub_date, post_slug, author, email, url,
|
||||
ip_address, device, os, browser, user_agent,
|
||||
content_text, content_html, parent_id, status
|
||||
].map(v => v === undefined ? null : v);
|
||||
created || Date.now(),
|
||||
post_slug || "",
|
||||
name || "Anonymous",
|
||||
email || "",
|
||||
url || null,
|
||||
ip_address || null,
|
||||
device || null,
|
||||
os || null,
|
||||
browser || null,
|
||||
ua || null,
|
||||
content_text || "",
|
||||
content_html || "",
|
||||
parent_id || null,
|
||||
status || "approved"
|
||||
];
|
||||
|
||||
if (id) {
|
||||
fields.unshift('id');
|
||||
|
||||
@@ -14,7 +14,7 @@ export const listComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
).first<{ count: number }>();
|
||||
|
||||
const { results } = await c.env.CWD_DB.prepare(
|
||||
'SELECT * FROM Comment ORDER BY pub_date DESC LIMIT ? OFFSET ?'
|
||||
'SELECT * FROM Comment ORDER BY created DESC LIMIT ? OFFSET ?'
|
||||
)
|
||||
.bind(limit, offset)
|
||||
.all();
|
||||
@@ -30,8 +30,8 @@ export const listComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
const data = await Promise.all(
|
||||
results.map(async (row: any) => ({
|
||||
id: row.id,
|
||||
pubDate: row.pub_date,
|
||||
author: row.author,
|
||||
created: row.created,
|
||||
name: row.name,
|
||||
email: row.email,
|
||||
postSlug: row.post_slug,
|
||||
url: row.url,
|
||||
@@ -39,6 +39,7 @@ export const listComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
contentText: row.content_text,
|
||||
contentHtml: row.content_html,
|
||||
status: row.status,
|
||||
ua: row.ua,
|
||||
avatar: await getCravatar(row.email, avatarPrefix || undefined)
|
||||
}))
|
||||
);
|
||||
|
||||
@@ -15,12 +15,12 @@ export const getComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
try {
|
||||
// 1. 查询审核通过的评论
|
||||
const query = `
|
||||
SELECT id, author, email, url, content_text as contentText,
|
||||
content_html as contentHtml, pub_date as pubDate, parent_id as parentId,
|
||||
SELECT id, name, email, url, content_text as contentText,
|
||||
content_html as contentHtml, created, parent_id as parentId,
|
||||
post_slug as postSlug
|
||||
FROM Comment
|
||||
WHERE post_slug = ? AND status = "approved"
|
||||
ORDER BY pub_date DESC
|
||||
ORDER BY created DESC
|
||||
`
|
||||
const { results } = await c.env.CWD_DB.prepare(query).bind(post_slug).all()
|
||||
|
||||
@@ -52,7 +52,7 @@ export const getComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
// 获取直接父评论的作者名
|
||||
const parentComment = commentMap.get(comment.parentId)
|
||||
if (parentComment) {
|
||||
comment.replyToAuthor = parentComment.author
|
||||
comment.replyToAuthor = parentComment.name
|
||||
}
|
||||
|
||||
// 向上查找根评论
|
||||
@@ -74,7 +74,7 @@ export const getComments = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
// 对每个根评论的 replies 按时间正序排列
|
||||
rootComments.forEach(root => {
|
||||
root.replies.sort((a: any, b: any) =>
|
||||
new Date(a.pubDate).getTime() - new Date(b.pubDate).getTime()
|
||||
a.created - b.created
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
if (!data || typeof data !== 'object') {
|
||||
return c.json({ message: '无效的请求体' }, 400);
|
||||
}
|
||||
const { post_slug, content: rawContent, author: rawAuthor, email, url, post_title, post_url } = data;
|
||||
const { post_slug, content: rawContent, name: rawName, email, url, post_title, post_url } = data;
|
||||
const parentId = (data as any).parent_id ?? (data as any).parentId ?? null;
|
||||
if (!post_slug || typeof post_slug !== 'string') {
|
||||
return c.json({ message: 'post_slug 必填' }, 400);
|
||||
@@ -30,7 +30,7 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
if (!rawContent || typeof rawContent !== 'string') {
|
||||
return c.json({ message: '评论内容不能为空' }, 400);
|
||||
}
|
||||
if (!rawAuthor || typeof rawAuthor !== 'string') {
|
||||
if (!rawName || typeof rawName !== 'string') {
|
||||
return c.json({ message: '昵称不能为空' }, 400);
|
||||
}
|
||||
if (!email || typeof email !== 'string') {
|
||||
@@ -39,7 +39,7 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
if (!isValidEmail(email)) {
|
||||
return c.json({ message: '邮箱格式不正确' }, 400);
|
||||
}
|
||||
const userAgent = c.req.header('user-agent') || "";
|
||||
const ua = c.req.header('user-agent') || "";
|
||||
|
||||
// 1. 获取 IP (Worker 获取 IP 的标准方式)
|
||||
const ip = c.req.header('cf-connecting-ip') || "127.0.0.1";
|
||||
@@ -47,11 +47,11 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
// 2. 检查评论频率控制 (对应 canPostComment)
|
||||
// 这里建议使用 D1 查最近一条评论的时间,或者直接放行(如果使用了 Cloudflare WAF)
|
||||
const lastComment = await c.env.CWD_DB.prepare(
|
||||
'SELECT pub_date FROM Comment WHERE ip_address = ? ORDER BY pub_date DESC LIMIT 1'
|
||||
).bind(ip).first<{ pub_date: string }>();
|
||||
'SELECT created FROM Comment WHERE ip_address = ? ORDER BY created DESC LIMIT 1'
|
||||
).bind(ip).first<{ created: number }>();
|
||||
|
||||
if (lastComment) {
|
||||
const lastTime = new Date(lastComment.pub_date).getTime();
|
||||
const lastTime = lastComment.created;
|
||||
if (Date.now() - lastTime < 10 * 1000) {
|
||||
return c.json({ message: "评论频繁,等10s后再试" }, 429);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
// 3. 准备数据
|
||||
const cleanedContent = checkContent(rawContent);
|
||||
const contentText = cleanedContent;
|
||||
const author = checkContent(rawAuthor);
|
||||
const name = checkContent(rawName);
|
||||
|
||||
// Markdown 渲染与 XSS 过滤
|
||||
const html = await marked.parse(cleanedContent, { async: true });
|
||||
@@ -89,32 +89,32 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
console.log('PostComment:request', {
|
||||
postSlug: post_slug,
|
||||
hasParent: parentId !== null && parentId !== undefined,
|
||||
author,
|
||||
name,
|
||||
email,
|
||||
ip
|
||||
});
|
||||
const uaParser = new UAParser(userAgent);
|
||||
const uaParser = new UAParser(ua);
|
||||
const uaResult = uaParser.getResult();
|
||||
|
||||
// 4. 写入 D1 数据库
|
||||
try {
|
||||
const { success } = await c.env.CWD_DB.prepare(`
|
||||
INSERT INTO Comment (
|
||||
pub_date, post_slug, author, email, url, ip_address,
|
||||
os, browser, device, user_agent, content_text, content_html,
|
||||
created, post_slug, name, email, url, ip_address,
|
||||
os, browser, device, ua, content_text, content_html,
|
||||
parent_id, status
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).bind(
|
||||
new Date().toISOString(),
|
||||
Date.now(),
|
||||
post_slug,
|
||||
author,
|
||||
name,
|
||||
email,
|
||||
url || null,
|
||||
ip,
|
||||
`${uaResult.os.name || ""} ${uaResult.os.version || ""}`.trim(),
|
||||
`${uaResult.browser.name || ""} ${uaResult.browser.version || ""}`.trim(),
|
||||
uaResult.device.model || uaResult.device.type || "Desktop",
|
||||
userAgent,
|
||||
ua,
|
||||
contentText,
|
||||
contentHtml,
|
||||
parentId || null,
|
||||
@@ -156,8 +156,8 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
const isAdminReply = !!adminEmail && email === adminEmail;
|
||||
|
||||
const parentComment = await c.env.CWD_DB.prepare(
|
||||
"SELECT author, email, content_html FROM Comment WHERE id = ?"
|
||||
).bind(parentId).first<{ author: string, email: string, content_html: string }>();
|
||||
"SELECT name, email, content_html FROM Comment WHERE id = ?"
|
||||
).bind(parentId).first<{ name: string, email: string, content_html: string }>();
|
||||
|
||||
if (parentComment && parentComment.email && parentComment.email !== email) {
|
||||
let canSendUserMail = true;
|
||||
@@ -173,14 +173,14 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
if (canSendUserMail && isValidEmail(parentComment.email)) {
|
||||
console.log('PostComment:mailDispatch:userReply:send', {
|
||||
toEmail: parentComment.email,
|
||||
toName: parentComment.author
|
||||
toName: parentComment.name
|
||||
});
|
||||
await sendCommentReplyNotification(c.env, {
|
||||
toEmail: parentComment.email,
|
||||
toName: parentComment.author,
|
||||
toName: parentComment.name,
|
||||
postTitle: data.post_title,
|
||||
parentComment: parentComment.content_html,
|
||||
replyAuthor: author,
|
||||
replyAuthor: name,
|
||||
replyContent: contentHtml,
|
||||
postUrl: data.post_url,
|
||||
}, notifySettings.smtp);
|
||||
@@ -202,7 +202,7 @@ export const postComment = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
await sendCommentNotification(c.env, {
|
||||
postTitle: data.post_title,
|
||||
postUrl: data.post_url,
|
||||
commentAuthor: author,
|
||||
commentAuthor: name,
|
||||
commentContent: contentHtml
|
||||
}, notifySettings.smtp);
|
||||
await c.env.CWD_DB.prepare(
|
||||
|
||||
@@ -25,7 +25,7 @@ export class CommentForm extends Component {
|
||||
const { formErrors, submitting } = this.props;
|
||||
const { localForm } = this.state;
|
||||
|
||||
const canSubmit = localForm.author.trim() && localForm.email.trim() && localForm.content.trim();
|
||||
const canSubmit = localForm.name.trim() && localForm.email.trim() && localForm.content.trim();
|
||||
|
||||
const root = this.createElement('form', {
|
||||
className: 'cwd-comment-form',
|
||||
@@ -46,7 +46,7 @@ export class CommentForm extends Component {
|
||||
className: 'cwd-form-row',
|
||||
children: [
|
||||
// 昵称
|
||||
this.createFormField('昵称 *', 'text', 'author', localForm.author, formErrors.author),
|
||||
this.createFormField('昵称 *', 'text', 'name', localForm.name, formErrors.name),
|
||||
// 邮箱
|
||||
this.createFormField('邮箱 *', 'email', 'email', localForm.email, formErrors.email),
|
||||
// 网址
|
||||
@@ -103,13 +103,13 @@ export class CommentForm extends Component {
|
||||
// 只在非提交状态时同步表单数据(避免覆盖用户正在输入的内容)
|
||||
if (!this.props.submitting && this.props.form !== prevProps.form) {
|
||||
// 保留当前正在输入的内容
|
||||
const currentAuthor = this.state.localForm.author || '';
|
||||
const currentName = this.state.localForm.name || '';
|
||||
const currentEmail = this.state.localForm.email || '';
|
||||
const currentUrl = this.state.localForm.url || '';
|
||||
const currentContent = this.state.localForm.content || '';
|
||||
|
||||
this.state.localForm = {
|
||||
author: this.props.form.author || currentAuthor,
|
||||
name: this.props.form.name || currentName,
|
||||
email: this.props.form.email || currentEmail,
|
||||
url: this.props.form.url || currentUrl,
|
||||
content: this.props.form.content !== undefined ? this.props.form.content : currentContent,
|
||||
@@ -134,7 +134,7 @@ export class CommentForm extends Component {
|
||||
const { formErrors, submitting } = this.props;
|
||||
const { localForm } = this.state;
|
||||
|
||||
const canSubmit = localForm.author.trim() && localForm.email.trim() && localForm.content.trim();
|
||||
const canSubmit = localForm.name.trim() && localForm.email.trim() && localForm.content.trim();
|
||||
|
||||
// 更新提交按钮状态
|
||||
const submitBtn = this.elements.root.querySelector('button[type="submit"]');
|
||||
@@ -159,8 +159,8 @@ export class CommentForm extends Component {
|
||||
updateErrors(formErrors) {
|
||||
if (!this.elements.root) return;
|
||||
|
||||
const authorInput = this.elements.root.querySelector('input[name="author"]');
|
||||
this.updateFieldError(authorInput, formErrors?.author);
|
||||
const nameInput = this.elements.root.querySelector('input[name="name"]');
|
||||
this.updateFieldError(nameInput, formErrors?.name);
|
||||
|
||||
const emailInput = this.elements.root.querySelector('input[name="email"]');
|
||||
this.updateFieldError(emailInput, formErrors?.email);
|
||||
@@ -227,12 +227,12 @@ export class CommentForm extends Component {
|
||||
* 设置输入框的值
|
||||
*/
|
||||
setInputValues(root, form) {
|
||||
const authorInput = root.querySelector('input[name="author"]');
|
||||
const nameInput = root.querySelector('input[name="name"]');
|
||||
const emailInput = root.querySelector('input[name="email"]');
|
||||
const urlInput = root.querySelector('input[name="url"]');
|
||||
const contentTextarea = root.querySelector('textarea');
|
||||
|
||||
if (authorInput) authorInput.value = form.author || '';
|
||||
if (nameInput) nameInput.value = form.name || '';
|
||||
if (emailInput) emailInput.value = form.email || '';
|
||||
if (urlInput) urlInput.value = form.url || '';
|
||||
if (contentTextarea) contentTextarea.value = form.content || '';
|
||||
|
||||
@@ -45,7 +45,7 @@ export class CommentItem extends Component {
|
||||
this.createElement('img', {
|
||||
attributes: {
|
||||
src: comment.avatar,
|
||||
alt: comment.author,
|
||||
alt: comment.name,
|
||||
loading: 'lazy'
|
||||
}
|
||||
})
|
||||
@@ -74,11 +74,11 @@ export class CommentItem extends Component {
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer'
|
||||
},
|
||||
text: comment.author
|
||||
text: comment.name
|
||||
})
|
||||
]
|
||||
})
|
||||
: this.createTextElement('span', comment.author, 'cwd-author-name'),
|
||||
: this.createTextElement('span', comment.name, 'cwd-author-name'),
|
||||
// 博主标识
|
||||
...(isAdmin ? [
|
||||
this.createTextElement('span', `${adminBadge}`, 'cwd-admin-badge')
|
||||
@@ -102,7 +102,7 @@ export class CommentItem extends Component {
|
||||
},
|
||||
text: '回复'
|
||||
}),
|
||||
this.createTextElement('span', formatRelativeTime(comment.pubDate), 'cwd-comment-time')
|
||||
this.createTextElement('span', formatRelativeTime(comment.created), 'cwd-comment-time')
|
||||
]
|
||||
})
|
||||
]
|
||||
@@ -140,7 +140,7 @@ export class CommentItem extends Component {
|
||||
const replyContainer = root.querySelector('.cwd-reply-editor-container');
|
||||
if (replyContainer) {
|
||||
this.replyEditor = new ReplyEditor(replyContainer, {
|
||||
replyToAuthor: comment.author,
|
||||
replyToAuthor: comment.name,
|
||||
content: this.props.replyContent,
|
||||
error: this.props.replyError,
|
||||
submitting: this.props.submitting,
|
||||
@@ -212,7 +212,7 @@ export class CommentItem extends Component {
|
||||
if (isReplying && replyContainer) {
|
||||
// 显示回复编辑器
|
||||
this.replyEditor = new ReplyEditor(replyContainer, {
|
||||
replyToAuthor: comment.author,
|
||||
replyToAuthor: comment.name,
|
||||
content: this.props.replyContent,
|
||||
error: this.props.replyError,
|
||||
submitting: this.props.submitting,
|
||||
|
||||
@@ -39,7 +39,7 @@ export function createApiClient(config) {
|
||||
/**
|
||||
* 提交评论
|
||||
* @param {Object} data - 评论数据
|
||||
* @param {string} data.author - 昵称
|
||||
* @param {string} data.name - 昵称
|
||||
* @param {string} data.email - 邮箱
|
||||
* @param {string} data.url - 网址(可选)
|
||||
* @param {string} data.content - 评论内容
|
||||
@@ -56,7 +56,7 @@ export function createApiClient(config) {
|
||||
post_slug: config.postSlug,
|
||||
post_title: config.postTitle,
|
||||
post_url: config.postUrl,
|
||||
author: data.author,
|
||||
name: data.name,
|
||||
email: data.email,
|
||||
url: data.url || undefined,
|
||||
content: data.content,
|
||||
|
||||
@@ -15,7 +15,7 @@ function loadUserInfo() {
|
||||
if (data) {
|
||||
const parsed = JSON.parse(data);
|
||||
return {
|
||||
author: parsed.author || '',
|
||||
name: parsed.name || '',
|
||||
email: parsed.email || '',
|
||||
url: parsed.url || ''
|
||||
};
|
||||
@@ -23,18 +23,18 @@ function loadUserInfo() {
|
||||
} catch (e) {
|
||||
console.error('读取用户信息失败:', e);
|
||||
}
|
||||
return { author: '', email: '', url: '' };
|
||||
return { name: '', email: '', url: '' };
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存用户信息到 localStorage
|
||||
* @param {string} author - 昵称
|
||||
* @param {string} name - 昵称
|
||||
* @param {string} email - 邮箱
|
||||
* @param {string} url - 网址
|
||||
*/
|
||||
function saveUserInfo(author, email, url) {
|
||||
function saveUserInfo(name, email, url) {
|
||||
try {
|
||||
const data = { author, email, url };
|
||||
const data = { name, email, url };
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
||||
} catch (e) {
|
||||
console.error('保存用户信息失败:', e);
|
||||
@@ -115,7 +115,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
|
||||
// 表单数据
|
||||
form: {
|
||||
author: savedInfo.author || '',
|
||||
name: savedInfo.name || '',
|
||||
email: savedInfo.email || '',
|
||||
url: savedInfo.url || '',
|
||||
content: ''
|
||||
@@ -131,8 +131,8 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
|
||||
// 监听用户信息变化,自动保存到 localStorage
|
||||
store.subscribe((state) => {
|
||||
if (state.form.author || state.form.email || state.form.url) {
|
||||
saveUserInfo(state.form.author, state.form.email, state.form.url);
|
||||
if (state.form.name || state.form.email || state.form.url) {
|
||||
saveUserInfo(state.form.name, state.form.email, state.form.url);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -194,7 +194,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
|
||||
try {
|
||||
await submitComment({
|
||||
author: form.author,
|
||||
name: form.name,
|
||||
email: form.email,
|
||||
url: form.url,
|
||||
content: form.content
|
||||
@@ -249,7 +249,7 @@ export function createCommentStore(config, fetchComments, submitComment) {
|
||||
|
||||
try {
|
||||
await submitComment({
|
||||
author: state.form.author,
|
||||
name: state.form.name,
|
||||
email: state.form.email,
|
||||
url: state.form.url,
|
||||
content: state.replyContent,
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
/**
|
||||
* 格式化时间(3天内显示相对时间,超过3天显示完整日期)
|
||||
* @param {string} dateStr - 日期字符串
|
||||
* @param {string|number} dateValue - 日期字符串或时间戳
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatRelativeTime(dateStr) {
|
||||
const date = new Date(dateStr);
|
||||
export function formatRelativeTime(dateValue) {
|
||||
const date = new Date(dateValue);
|
||||
const now = new Date();
|
||||
const diff = now.getTime() - date.getTime();
|
||||
|
||||
@@ -32,16 +32,16 @@ export function formatRelativeTime(dateStr) {
|
||||
}
|
||||
|
||||
// 超过3天显示完整日期
|
||||
return formatDateTime(dateStr);
|
||||
return formatDateTime(dateValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期时间
|
||||
* @param {string} dateStr - 日期字符串
|
||||
* @param {string|number} dateValue - 日期字符串或时间戳
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatDateTime(dateStr) {
|
||||
const date = new Date(dateStr);
|
||||
export function formatDateTime(dateValue) {
|
||||
const date = new Date(dateValue);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
@@ -53,11 +53,11 @@ export function formatDateTime(dateStr) {
|
||||
|
||||
/**
|
||||
* 格式化日期
|
||||
* @param {string} dateStr - 日期字符串
|
||||
* @param {string|number} dateValue - 日期字符串或时间戳
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatDate(dateStr) {
|
||||
const date = new Date(dateStr);
|
||||
export function formatDate(dateValue) {
|
||||
const date = new Date(dateValue);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
@@ -66,11 +66,11 @@ export function formatDate(dateStr) {
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
* @param {string} dateStr - 日期字符串
|
||||
* @param {string|number} dateValue - 日期字符串或时间戳
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatTime(dateStr) {
|
||||
const date = new Date(dateStr);
|
||||
export function formatTime(dateValue) {
|
||||
const date = new Date(dateValue);
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||
|
||||
@@ -45,7 +45,7 @@ export function validateCommentContent(content) {
|
||||
/**
|
||||
* 验证评论表单
|
||||
* @param {Object} data - 表单数据
|
||||
* @param {string} data.author - 昵称
|
||||
* @param {string} data.name - 昵称
|
||||
* @param {string} data.email - 邮箱
|
||||
* @param {string} data.url - 网址
|
||||
* @param {string} data.content - 评论内容
|
||||
@@ -55,10 +55,10 @@ export function validateCommentForm(data) {
|
||||
const errors = {};
|
||||
|
||||
// 验证昵称
|
||||
if (!data.author || data.author.trim().length === 0) {
|
||||
errors.author = '请输入昵称';
|
||||
} else if (data.author.length > 50) {
|
||||
errors.author = '昵称不能超过 50 字';
|
||||
if (!data.name || data.name.trim().length === 0) {
|
||||
errors.name = '请输入昵称';
|
||||
} else if (data.name.length > 50) {
|
||||
errors.name = '昵称不能超过 50 字';
|
||||
}
|
||||
|
||||
// 验证邮箱
|
||||
@@ -88,7 +88,7 @@ export function validateCommentForm(data) {
|
||||
/**
|
||||
* 验证回复所需的用户信息
|
||||
* @param {Object} data - 用户信息
|
||||
* @param {string} data.author - 昵称
|
||||
* @param {string} data.name - 昵称
|
||||
* @param {string} data.email - 邮箱
|
||||
* @param {string} data.url - 网址
|
||||
* @returns {{valid: boolean, errors: Object<string, string>}}
|
||||
@@ -97,10 +97,10 @@ export function validateReplyUserInfo(data) {
|
||||
const errors = {};
|
||||
|
||||
// 验证昵称
|
||||
if (!data.author || data.author.trim().length === 0) {
|
||||
errors.author = '请输入昵称';
|
||||
} else if (data.author.length > 50) {
|
||||
errors.author = '昵称不能超过 50 字';
|
||||
if (!data.name || data.name.trim().length === 0) {
|
||||
errors.name = '请输入昵称';
|
||||
} else if (data.name.length > 50) {
|
||||
errors.name = '昵称不能超过 50 字';
|
||||
}
|
||||
|
||||
// 验证邮箱
|
||||
|
||||
Reference in New Issue
Block a user