- /admin/* 全部由 React SPA 渲染,替代旧版 HTML 后台页面 - 新增仪表盘、帖子/评论/用户管理、系统设置与 JSON API - 帖子详情页支持管理员置顶;评论换行显示修复 Co-authored-by: Cursor <cursoragent@cursor.com>
27 lines
995 B
TypeScript
27 lines
995 B
TypeScript
/** 转义 HTML 并保留换行 */
|
||
function escapeWithBreaks(text: string): string {
|
||
return text
|
||
.replace(/\r\n/g, '\n')
|
||
.replace(/\r/g, '\n')
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/\n/g, '<br>');
|
||
}
|
||
|
||
/** @用户名 高亮(仅用于评论正文中用户主动输入的 @) */
|
||
export function highlightMentions(text: string, _onClick?: (name: string) => void): string {
|
||
return escapeWithBreaks(text)
|
||
.replace(/@([\w\u4e00-\u9fa5_-]+)/g, '<span class="mention">@$1</span>');
|
||
}
|
||
|
||
export function formatTime(iso: string) {
|
||
const d = new Date(iso);
|
||
const now = new Date();
|
||
const diff = (now.getTime() - d.getTime()) / 1000;
|
||
if (diff < 60) return '刚刚';
|
||
if (diff < 3600) return `${Math.floor(diff / 60)}分钟前`;
|
||
if (diff < 86400) return `${Math.floor(diff / 3600)}小时前`;
|
||
return `${d.getMonth() + 1}-${d.getDate()} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||
}
|