Compare commits

...

15 Commits

Author SHA1 Message Date
Tim
ac81bccd20 feat: add mermaid support to markdown 2025-08-28 16:52:07 +08:00
Tim
351447e3d1 Merge pull request #773 from sivdead/main
解决文章和草稿长度不够的问题
2025-08-28 15:59:45 +08:00
sivdead
453d8fa68b refactor(model): 将 Post和Draft 实体的内容字段类型从 TEXT 改为 LONGTEXT 2025-08-28 15:11:14 +08:00
tim
2c5b38ee9e fix: 修复 http://localhost:3000/posts/310 内容超出的问题 2025-08-28 14:40:19 +08:00
Tim
b5fd5a3edc Update README.md 2025-08-28 10:16:12 +08:00
tim
ee717aced2 fix: 处理两处图片加载异常问题 2025-08-28 09:19:06 +08:00
Tim
9a9152593e Merge pull request #764 from nagisa77/feature/daily_bugfix_0827
fix: 简化time规则
2025-08-27 20:58:47 +08:00
Tim
856d3dd513 fix: 简化time规则 2025-08-27 20:57:20 +08:00
Tim
0e42a3335a Merge pull request #763 from nagisa77/feature/daily_bugfix_0827
fix: 新增相对时间
2025-08-27 20:48:57 +08:00
Tim
d96aae59d2 fix: 新增相对时间 2025-08-27 20:47:50 +08:00
Tim
122722d0e9 Merge pull request #762 from nagisa77/codex/fix-overlap-of-mobile-post-button
Adjust mobile post icon position and add close button to message box
2025-08-27 20:40:41 +08:00
Tim
1e503e26f2 Merge pull request #761 from nagisa77/feature/daily_bugfix_0827
fix: 帖子可被刷积分,应新增取消赞消除积分😂 #685
2025-08-27 20:28:49 +08:00
Tim
e979350d40 Merge pull request #759 from nagisa77/feature/daily_bugfix_0827
Feature/daily bugfix 0827
2025-08-27 20:21:58 +08:00
Tim
906998a07f Merge pull request #757 from nagisa77/feature/daily_bugfix_0827
fix: 站内信 scroll问题 #749
2025-08-27 20:19:29 +08:00
Tim
56aed4603e Merge pull request #756 from nagisa77/feature/daily_bugfix_0827
fix: 站内信 scroll问题 #749
2025-08-27 20:01:34 +08:00
10 changed files with 1331 additions and 10 deletions

View File

@@ -1,9 +1,9 @@
<p align="center"> <p align="center">
<BaseImage alt="OpenIsle" src="https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/image.png" width="200"> <img alt="OpenIsle" src="https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/image.png" width="200">
<br> <br>
高效的开源社区前后端平台 高效的开源社区前后端平台
<br><br><br> <br><br><br>
<BaseImage alt="Image" src="https://openisle-1307107697.cos.accelerate.myqcloud.com/dynamic_assert/22752cfac5a04a9c90c41995b9f55fed.png" width="1200"> <img alt="Image" src="https://openisle-1307107697.cos.accelerate.myqcloud.com/dynamic_assert/22752cfac5a04a9c90c41995b9f55fed.png" width="1200">
</p> </p>
## 💡 简介 ## 💡 简介

View File

@@ -22,7 +22,7 @@ public class Draft {
private String title; private String title;
@Column(columnDefinition = "TEXT") @Column(columnDefinition = "LONGTEXT")
private String content; private String content;
@ManyToOne(fetch = FetchType.LAZY, optional = false) @ManyToOne(fetch = FetchType.LAZY, optional = false)

View File

@@ -31,7 +31,7 @@ public class Post {
@Column(nullable = false) @Column(nullable = false)
private String title; private String title;
@Column(nullable = false, columnDefinition = "TEXT") @Column(nullable = false, columnDefinition = "LONGTEXT")
private String content; private String content;
@CreationTimestamp @CreationTimestamp

View File

@@ -162,6 +162,7 @@ body {
border-radius: 4px; border-radius: 4px;
line-height: 1.5; line-height: 1.5;
position: relative; position: relative;
white-space: break-spaces;
} }
.info-content-text pre .line-numbers { .info-content-text pre .line-numbers {
@@ -188,7 +189,6 @@ body {
font-family: 'Maple Mono', monospace; font-family: 'Maple Mono', monospace;
font-size: 13px; font-size: 13px;
border-radius: 4px; border-radius: 4px;
white-space: break-spaces;
background-color: var(--code-highlight-background-color); background-color: var(--code-highlight-background-color);
color: var(--text-color); color: var(--text-color);
} }

View File

@@ -2,7 +2,7 @@
<div v-if="show" class="cropper-modal"> <div v-if="show" class="cropper-modal">
<div class="cropper-body"> <div class="cropper-body">
<div class="cropper-wrapper"> <div class="cropper-wrapper">
<BaseImage ref="image" :src="src" alt="to crop" /> <img ref="image" :src="src" alt="to crop" />
</div> </div>
<div class="cropper-actions"> <div class="cropper-actions">
<button class="cropper-btn" @click="$emit('close')">取消</button> <button class="cropper-btn" @click="$emit('close')">取消</button>

View File

@@ -63,7 +63,7 @@
<DropdownMenu v-if="isLogin" ref="userMenu" :items="headerMenuItems"> <DropdownMenu v-if="isLogin" ref="userMenu" :items="headerMenuItems">
<template #trigger> <template #trigger>
<div class="avatar-container"> <div class="avatar-container">
<BaseImage class="avatar-img" :src="avatar" alt="avatar" /> <img class="avatar-img" :src="avatar" alt="avatar" />
<i class="fas fa-caret-down dropdown-icon"></i> <i class="fas fa-caret-down dropdown-icon"></i>
</div> </div>
</template> </template>

View File

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,7 @@
"highlight.js": "^11.11.1", "highlight.js": "^11.11.1",
"ldrs": "^1.0.0", "ldrs": "^1.0.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"mermaid": "^10.9.4",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"nuxt": "latest", "nuxt": "latest",
"sanitize-html": "^2.17.0", "sanitize-html": "^2.17.0",

View File

@@ -96,6 +96,9 @@ const md = new MarkdownIt({
linkify: true, linkify: true,
breaks: true, breaks: true,
highlight: (str, lang) => { highlight: (str, lang) => {
if (lang === 'mermaid') {
return `<pre class="mermaid">${str}</pre>`
}
let code = '' let code = ''
if (lang && hljs.getLanguage(lang)) { if (lang && hljs.getLanguage(lang)) {
code = hljs.highlight(str, { language: lang, ignoreIllegals: true }).value code = hljs.highlight(str, { language: lang, ignoreIllegals: true }).value
@@ -182,7 +185,7 @@ const SANITIZE_CFG = {
allowedClasses: { allowedClasses: {
a: ['mention-link'], a: ['mention-link'],
img: ['emoji'], img: ['emoji'],
pre: ['code-block'], pre: ['code-block', 'mermaid'],
div: ['line-numbers', 'line-number'], div: ['line-numbers', 'line-number'],
code: ['hljs', /^language-/], code: ['hljs', /^language-/],
button: ['copy-code-btn'], button: ['copy-code-btn'],
@@ -208,8 +211,15 @@ const SANITIZE_CFG = {
/** @section 渲染 & 事件 */ /** @section 渲染 & 事件 */
export function renderMarkdown(text) { export function renderMarkdown(text) {
const raw = md.render(text || '') const raw = md.render(text || '')
// ⭐ 核心:对最终 HTML 进行一次净化 const html = sanitizeHtml(raw, SANITIZE_CFG)
return sanitizeHtml(raw, SANITIZE_CFG) if (typeof window !== 'undefined') {
setTimeout(async () => {
const mermaid = await import('mermaid')
mermaid.default.initialize({ startOnLoad: false })
mermaid.default.run({ nodes: document.querySelectorAll('.mermaid') })
})
}
return html
} }
export function handleMarkdownClick(e) { export function handleMarkdownClick(e) {

View File

@@ -4,6 +4,17 @@ export default class TimeManager {
if (Number.isNaN(date.getTime())) return '' if (Number.isNaN(date.getTime())) return ''
const now = new Date() const now = new Date()
const diffMs = now.getTime() - date.getTime()
if (diffMs >= 0 && diffMs < 60 * 1000) {
return '刚刚'
}
if (diffMs >= 0 && diffMs < 60 * 60 * 1000) {
const mins = Math.floor(diffMs / 60_000)
return `${mins || 1}分钟前`
}
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()) const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate())
const startOfDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()) const startOfDate = new Date(date.getFullYear(), date.getMonth(), date.getDate())
const diffDays = Math.floor((startOfToday - startOfDate) / 86400000) const diffDays = Math.floor((startOfToday - startOfDate) / 86400000)