- {{ iconMap[r.type] }}
+ {{ reactionEmojiMap[r.type] }}
{{ totalCount }}
@@ -24,7 +24,7 @@
- {{ iconMap[t] }}{{ counts[t] }}
+ {{ reactionEmojiMap[t] }}{{ counts[t] }}
@@ -34,6 +34,7 @@
import { ref, computed, watch, onMounted } from 'vue'
import { API_BASE_URL, toast } from '../main'
import { getToken, authState } from '../utils/auth'
+import { reactionEmojiMap } from '../utils/reactions'
let cachedTypes = null
const fetchTypes = async () => {
@@ -54,32 +55,6 @@ const fetchTypes = async () => {
return cachedTypes
}
-const iconMap = {
- LIKE: '❤️',
- DISLIKE: '👎',
- RECOMMEND: '👏',
- ANGRY: '😡',
- FLUSHED: '😳',
- STAR_STRUCK: '🤩',
- ROFL: '🤣',
- HOLDING_BACK_TEARS: '🥹',
- MIND_BLOWN: '🤯',
- POOP: '💩',
- CLOWN: '🤡',
- SKULL: '☠️',
- FIRE: '🔥',
- EYES: '👀',
- FROWN: '☹️',
- HOT: '🥵',
- EAGLE: '🦅',
- SPIDER: '🕷️',
- BAT: '🦇',
- CHINA: '🇨🇳',
- USA: '🇺🇸',
- JAPAN: '🇯🇵',
- KOREA: '🇰🇷'
-}
-
export default {
name: 'ReactionsGroup',
props: {
@@ -202,7 +177,7 @@ export default {
}
return {
- iconMap,
+ reactionEmojiMap,
counts,
totalCount,
likeCount,
diff --git a/frontend/src/utils/reactions.js b/frontend/src/utils/reactions.js
new file mode 100644
index 000000000..7fa967de7
--- /dev/null
+++ b/frontend/src/utils/reactions.js
@@ -0,0 +1,25 @@
+export const reactionEmojiMap = {
+ LIKE: '❤️',
+ DISLIKE: '👎',
+ RECOMMEND: '👏',
+ ANGRY: '😡',
+ FLUSHED: '😳',
+ STAR_STRUCK: '🤩',
+ ROFL: '🤣',
+ HOLDING_BACK_TEARS: '🥹',
+ MIND_BLOWN: '🤯',
+ POOP: '💩',
+ CLOWN: '🤡',
+ SKULL: '☠️',
+ FIRE: '🔥',
+ EYES: '👀',
+ FROWN: '☹️',
+ HOT: '🥵',
+ EAGLE: '🦅',
+ SPIDER: '🕷️',
+ BAT: '🦇',
+ CHINA: '🇨🇳',
+ USA: '🇺🇸',
+ JAPAN: '🇯🇵',
+ KOREA: '🇰🇷'
+}
diff --git a/frontend/src/views/MessagePageView.vue b/frontend/src/views/MessagePageView.vue
index ca15bfb14..4d4672a00 100644
--- a/frontend/src/views/MessagePageView.vue
+++ b/frontend/src/views/MessagePageView.vue
@@ -304,6 +304,7 @@ import { toast } from '../main'
import { stripMarkdownLength } from '../utils/markdown'
import TimeManager from '../utils/time'
import { hatch } from 'ldrs'
+import { reactionEmojiMap } from '../utils/reactions'
hatch.register()
export default {
@@ -364,32 +365,6 @@ export default {
MENTION: 'fas fa-at'
}
- const reactionEmojiMap = {
- LIKE: '❤️',
- DISLIKE: '👎',
- RECOMMEND: '👏',
- ANGRY: '😡',
- FLUSHED: '😳',
- STAR_STRUCK: '🤩',
- ROFL: '🤣',
- HOLDING_BACK_TEARS: '🥹',
- MIND_BLOWN: '🤯',
- POOP: '💩',
- CLOWN: '🤡',
- SKULL: '☠️',
- FIRE: '🔥',
- EYES: '👀',
- FROWN: '☹️',
- HOT: '🥵',
- EAGLE: '🦅',
- SPIDER: '🕷️',
- BAT: '🦇',
- CHINA: '🇨🇳',
- USA: '🇺🇸',
- JAPAN: '🇯🇵',
- KOREA: '🇰🇷'
- }
-
const fetchNotifications = async () => {
try {
const token = getToken()
From 6a1b71de0fdd0b52b84457425e979f831086dbaf Mon Sep 17 00:00:00 2001
From: Tim <135014430+nagisa77@users.noreply.github.com>
Date: Wed, 6 Aug 2025 18:59:08 +0800
Subject: [PATCH 09/17] feat: add tieba emoji support
---
frontend/src/utils/markdown.js | 24 ++++++++++++++++++++++++
frontend/src/utils/tiebaEmoji.js | 10 ++++++++++
frontend/src/utils/vditor.js | 9 ++++++++-
3 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 frontend/src/utils/tiebaEmoji.js
diff --git a/frontend/src/utils/markdown.js b/frontend/src/utils/markdown.js
index a3ed32ec7..579a6749c 100644
--- a/frontend/src/utils/markdown.js
+++ b/frontend/src/utils/markdown.js
@@ -2,6 +2,7 @@ import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css'
import { toast } from '../main'
+import { tiebaEmoji, TIEBA_EMOJI_CDN } from './tiebaEmoji'
function mentionPlugin(md) {
const mentionReg = /^@\[([^\]]+)\]/
@@ -27,6 +28,28 @@ function mentionPlugin(md) {
md.inline.ruler.before('emphasis', 'mention', mention)
}
+function tiebaEmojiPlugin(md) {
+ md.renderer.rules['tieba-emoji'] = (tokens, idx) => {
+ const name = tokens[idx].content
+ const file = tiebaEmoji[name]
+ return `

`
+ }
+ md.inline.ruler.before('emphasis', 'tieba-emoji', (state, silent) => {
+ const pos = state.pos
+ if (state.src.charCodeAt(pos) !== 0x3a) return false
+ const match = state.src.slice(pos).match(/^:tieba(\d+):/)
+ if (!match) return false
+ const key = `tieba${match[1]}`
+ if (!tiebaEmoji[key]) return false
+ if (!silent) {
+ const token = state.push('tieba-emoji', '', 0)
+ token.content = key
+ }
+ state.pos += match[0].length
+ return true
+ })
+}
+
const md = new MarkdownIt({
html: false,
linkify: true,
@@ -43,6 +66,7 @@ const md = new MarkdownIt({
})
md.use(mentionPlugin)
+md.use(tiebaEmojiPlugin)
export function renderMarkdown(text) {
return md.render(text || '')
diff --git a/frontend/src/utils/tiebaEmoji.js b/frontend/src/utils/tiebaEmoji.js
new file mode 100644
index 000000000..da413d0e9
--- /dev/null
+++ b/frontend/src/utils/tiebaEmoji.js
@@ -0,0 +1,10 @@
+export const TIEBA_EMOJI_CDN = 'https://cdn.jsdelivr.net/gh/microlong666/tieba_mobile_emotions@master/'
+
+export const tiebaEmoji = (() => {
+ const map = { tieba1: 'image_emoticon.png' }
+ for (let i = 2; i <= 124; i++) {
+ if (i > 50 && i < 62) continue
+ map[`tieba${i}`] = `image_emoticon${i}.png`
+ }
+ return map
+})()
diff --git a/frontend/src/utils/vditor.js b/frontend/src/utils/vditor.js
index 2e9a2628c..a7fabe346 100644
--- a/frontend/src/utils/vditor.js
+++ b/frontend/src/utils/vditor.js
@@ -3,6 +3,7 @@ import 'vditor/dist/index.css'
import { API_BASE_URL } from '../main'
import { getToken, authState } from './auth'
import { searchUsers, fetchFollowings, fetchAdmins } from './user'
+import { tiebaEmoji, TIEBA_EMOJI_CDN } from './tiebaEmoji'
export function getEditorTheme() {
return document.documentElement.dataset.theme === 'dark' ? 'dark' : 'classic'
@@ -42,8 +43,14 @@ export function createVditor(editorId, options = {}) {
placeholder,
height: 'auto',
theme: getEditorTheme(),
- preview: Object.assign({ theme: { current: getPreviewTheme() } }, preview),
+ preview: Object.assign({
+ theme: { current: getPreviewTheme() },
+ customEmoji: tiebaEmoji,
+ emojiPath: TIEBA_EMOJI_CDN
+ }, preview),
hint: {
+ emoji: tiebaEmoji,
+ emojiPath: TIEBA_EMOJI_CDN,
extend: [
{
key: '@',
From 2235612070ef3c00a9c3c920a2dc3c02268d1f22 Mon Sep 17 00:00:00 2001
From: WangHe <51102@163.com>
Date: Wed, 6 Aug 2025 19:14:19 +0800
Subject: [PATCH 10/17] fix: Click outside the drop-down box to not hide
---
frontend/src/components/Dropdown.vue | 162 ++++++++++++++++--------
frontend/src/directives/clickOutside.js | 159 +++++++++++++++++++++++
frontend/src/main.js | 10 +-
3 files changed, 274 insertions(+), 57 deletions(-)
create mode 100644 frontend/src/directives/clickOutside.js
diff --git a/frontend/src/components/Dropdown.vue b/frontend/src/components/Dropdown.vue
index 27f5a641c..062521262 100644
--- a/frontend/src/components/Dropdown.vue
+++ b/frontend/src/components/Dropdown.vue
@@ -1,13 +1,24 @@
-
+
-
+
{{ label.name }}
@@ -21,7 +32,12 @@
-
+
{{ selectedLabels[0].name }}
@@ -32,20 +48,46 @@
-
+
-
+
-
+
-
+
-
+
-
+
{{ o.name }}
@@ -86,47 +146,49 @@
diff --git a/frontend/src/directives/clickOutside.js b/frontend/src/directives/clickOutside.js
new file mode 100644
index 000000000..22dae7e97
--- /dev/null
+++ b/frontend/src/directives/clickOutside.js
@@ -0,0 +1,159 @@
+/**
+ * @file clickOutsideDirective.js
+ * @description 一个用于检测元素外部点击的Vue 3自定义指令。
+ *
+ * @example
+ * // 在 main.js 中全局注册
+ * import { createApp } from 'vue'
+ * import App from './App.vue'
+ * import ClickOutside from './clickOutsideDirective.js'
+ *
+ * const app = createApp(App)
+ * app.directive('click-outside', ClickOutside)
+ * app.mount('#app')
+ *
+ * // 在组件中使用
+ * ...
+ *
+ * // 排除特定元素
+ * ...
+ * ...
+ */
+
+// 使用一个Map来存储所有指令绑定的元素及其对应的处理器
+// 键是HTMLElement,值是一个包含处理器和回调函数的对象数组
+const nodeList = new Map();
+
+// 检查是否在客户端环境,以避免在SSR(服务器端渲染)时执行
+const isClient = typeof window !== 'undefined';
+
+// 在客户端环境中,只设置一次全局的 mousedown 和 mouseup 监听器
+if (isClient) {
+ let startClick;
+
+ document.addEventListener('mousedown', (e) => (startClick = e));
+
+ document.addEventListener('mouseup', (e) => {
+ // 遍历所有注册的元素和它们的处理器
+ for (const handlers of nodeList.values()) {
+ for (const { documentHandler } of handlers) {
+ // 调用每个处理器,传入 mouseup 和 mousedown 事件
+ documentHandler(e, startClick);
+ }
+ }
+ // 完成后重置 startClick
+ startClick = undefined;
+ });
+}
+
+/**
+ * 创建一个文档事件处理器。
+ * @param {HTMLElement} el - 指令绑定的元素。
+ * @param {import('vue').DirectiveBinding} binding - 指令的绑定对象。
+ * @returns {Function} 返回一个处理函数。
+ */
+function createDocumentHandler(el, binding) {
+ let excludes = [];
+ // binding.arg 可以是一个元素或一个元素数组,用于排除不需要触发回调的点击
+ if (Array.isArray(binding.arg)) {
+ excludes = binding.arg;
+ } else if (binding.arg instanceof HTMLElement) {
+ excludes.push(binding.arg);
+ }
+
+ return function (mouseup, mousedown) {
+ // 从组件实例中获取 popper 引用(如果存在),这对于处理下拉菜单、弹窗等很有用
+ const popperRef = binding.instance?.popperRef;
+ const mouseUpTarget = mouseup.target;
+ const mouseDownTarget = mousedown?.target;
+
+ // 检查各种条件,如果满足任一条件,则不执行回调
+ const isBound = !binding || !binding.instance;
+ const isTargetExists = !mouseUpTarget || !mouseDownTarget;
+ const isContainedByEl = el.contains(mouseUpTarget) || el.contains(mouseDownTarget);
+ const isSelf = el === mouseUpTarget;
+
+ // 检查点击是否发生在任何被排除的元素内部
+ const isTargetExcluded =
+ (excludes.length && excludes.some((item) => item?.contains(mouseUpTarget))) ||
+ (excludes.length && excludes.includes(mouseDownTarget));
+
+ // 检查点击是否发生在关联的 popper 元素内部
+ const isContainedByPopper =
+ popperRef &&
+ (popperRef.contains(mouseUpTarget) || popperRef.contains(mouseDownTarget));
+
+ if (
+ isBound ||
+ isTargetExists ||
+ isContainedByEl ||
+ isSelf ||
+ isTargetExcluded ||
+ isContainedByPopper
+ ) {
+ return;
+ }
+
+ // 如果所有检查都通过,说明点击发生在外部,执行指令传入的回调函数
+ binding.value(mouseup, mousedown);
+ };
+}
+
+const ClickOutside = {
+ /**
+ * 在绑定元素的 attribute 或事件监听器被应用之前调用。
+ * @param {HTMLElement} el
+ * @param {import('vue').DirectiveBinding} binding
+ */
+ beforeMount(el, binding) {
+ if (!nodeList.has(el)) {
+ nodeList.set(el, []);
+ }
+
+ nodeList.get(el).push({
+ documentHandler: createDocumentHandler(el, binding),
+ bindingFn: binding.value,
+ });
+ },
+
+ /**
+ * 在包含组件的 VNode 及其子组件的 VNode 更新后调用。
+ * @param {HTMLElement} el
+ * @param {import('vue').DirectiveBinding} binding
+ */
+ updated(el, binding) {
+ if (!nodeList.has(el)) {
+ nodeList.set(el, []);
+ }
+
+ const handlers = nodeList.get(el);
+ // 查找旧的回调函数对应的处理器
+ const oldHandlerIndex = handlers.findIndex(
+ (item) => item.bindingFn === binding.oldValue
+ );
+
+ const newHandler = {
+ documentHandler: createDocumentHandler(el, binding),
+ bindingFn: binding.value,
+ };
+
+ if (oldHandlerIndex >= 0) {
+ // 如果找到了,就替换成新的处理器
+ handlers.splice(oldHandlerIndex, 1, newHandler);
+ } else {
+ // 否则,直接添加新的处理器
+ handlers.push(newHandler);
+ }
+ },
+
+ /**
+ * 在绑定元素的父组件卸载后调用。
+ * @param {HTMLElement} el
+ */
+ unmounted(el) {
+ // 当元素卸载时,从Map中移除它,以进行垃圾回收并防止内存泄漏
+ nodeList.delete(el);
+ },
+};
+
+export default ClickOutside;
diff --git a/frontend/src/main.js b/frontend/src/main.js
index 6fe6cf3a4..cb0db8df5 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -12,6 +12,8 @@ import { checkToken, clearToken, isLogin } from './utils/auth'
import { loginWithGoogle } from './utils/google'
import { initTheme } from './utils/theme'
import { clearVditorStorage } from './utils/clearVditorStorage'
+import ClickOutside from './directives/clickOutside' // 确保路径正确
+
// 采用本地开发环境
// export const API_DOMAIN = 'http://127.0.0.1'
@@ -38,16 +40,18 @@ clearVditorStorage()
const app = createApp(App)
app.use(router)
app.use(
- Toast,
- {
+ Toast,
+ {
position: POSITION.TOP_RIGHT,
containerClassName: "open-isle-toast-style-v1",
transition: "Vue-Toastification__fade",
// closeButton: false,
timeout: 2000,
- },
+ },
)
+app.directive('click-outside', ClickOutside)
+
app.mount('#app')
checkToken().then(valid => {
From 05dbeccdd716e146cba96e25344090161919cda5 Mon Sep 17 00:00:00 2001
From: tim
Date: Wed, 6 Aug 2025 19:26:35 +0800
Subject: [PATCH 11/17] fix: emoji fix
---
frontend/src/assets/global.css | 10 ++++++++++
frontend/src/utils/markdown.js | 4 ++--
frontend/src/utils/tiebaEmoji.js | 5 +++--
frontend/src/utils/vditor.js | 5 +----
4 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/frontend/src/assets/global.css b/frontend/src/assets/global.css
index 77be29063..1997730f4 100644
--- a/frontend/src/assets/global.css
+++ b/frontend/src/assets/global.css
@@ -71,6 +71,16 @@ body {
top: var(--header-height) !important;
}
+.vditor-panel {
+ min-width: 400px;
+}
+
+.emoji {
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+}
+
/* .vditor {
--textarea-background-color: transparent;
border: none !important;
diff --git a/frontend/src/utils/markdown.js b/frontend/src/utils/markdown.js
index 579a6749c..dbcd352b7 100644
--- a/frontend/src/utils/markdown.js
+++ b/frontend/src/utils/markdown.js
@@ -2,7 +2,7 @@ import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css'
import { toast } from '../main'
-import { tiebaEmoji, TIEBA_EMOJI_CDN } from './tiebaEmoji'
+import { tiebaEmoji } from './tiebaEmoji'
function mentionPlugin(md) {
const mentionReg = /^@\[([^\]]+)\]/
@@ -32,7 +32,7 @@ function tiebaEmojiPlugin(md) {
md.renderer.rules['tieba-emoji'] = (tokens, idx) => {
const name = tokens[idx].content
const file = tiebaEmoji[name]
- return `
`
+ return `
`
}
md.inline.ruler.before('emphasis', 'tieba-emoji', (state, silent) => {
const pos = state.pos
diff --git a/frontend/src/utils/tiebaEmoji.js b/frontend/src/utils/tiebaEmoji.js
index da413d0e9..ce91ea0ff 100644
--- a/frontend/src/utils/tiebaEmoji.js
+++ b/frontend/src/utils/tiebaEmoji.js
@@ -1,10 +1,11 @@
export const TIEBA_EMOJI_CDN = 'https://cdn.jsdelivr.net/gh/microlong666/tieba_mobile_emotions@master/'
+// export const TIEBA_EMOJI_CDN = 'https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/vditor/dist/images/emoji/'
export const tiebaEmoji = (() => {
- const map = { tieba1: 'image_emoticon.png' }
+ const map = { tieba1: TIEBA_EMOJI_CDN + 'image_emoticon.png' }
for (let i = 2; i <= 124; i++) {
if (i > 50 && i < 62) continue
- map[`tieba${i}`] = `image_emoticon${i}.png`
+ map[`tieba${i}`] = TIEBA_EMOJI_CDN + `image_emoticon${i}.png`
}
return map
})()
diff --git a/frontend/src/utils/vditor.js b/frontend/src/utils/vditor.js
index a7fabe346..f0a83214a 100644
--- a/frontend/src/utils/vditor.js
+++ b/frontend/src/utils/vditor.js
@@ -3,7 +3,7 @@ import 'vditor/dist/index.css'
import { API_BASE_URL } from '../main'
import { getToken, authState } from './auth'
import { searchUsers, fetchFollowings, fetchAdmins } from './user'
-import { tiebaEmoji, TIEBA_EMOJI_CDN } from './tiebaEmoji'
+import { tiebaEmoji } from './tiebaEmoji'
export function getEditorTheme() {
return document.documentElement.dataset.theme === 'dark' ? 'dark' : 'classic'
@@ -45,12 +45,9 @@ export function createVditor(editorId, options = {}) {
theme: getEditorTheme(),
preview: Object.assign({
theme: { current: getPreviewTheme() },
- customEmoji: tiebaEmoji,
- emojiPath: TIEBA_EMOJI_CDN
}, preview),
hint: {
emoji: tiebaEmoji,
- emojiPath: TIEBA_EMOJI_CDN,
extend: [
{
key: '@',
From fdf51be5f56581fd25c0bb623455a3d23af1d921 Mon Sep 17 00:00:00 2001
From: Tim <135014430+nagisa77@users.noreply.github.com>
Date: Wed, 6 Aug 2025 19:28:57 +0800
Subject: [PATCH 12/17] Preserve comment text on submission errors
---
frontend/src/components/CommentEditor.vue | 8 +++++---
frontend/src/components/CommentItem.vue | 3 ++-
frontend/src/views/PostPageView.vue | 3 ++-
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/frontend/src/components/CommentEditor.vue b/frontend/src/components/CommentEditor.vue
index 15bab89d6..fe3bc7dd8 100644
--- a/frontend/src/components/CommentEditor.vue
+++ b/frontend/src/components/CommentEditor.vue
@@ -67,9 +67,11 @@ export default {
if (!vditorInstance.value || isDisabled.value) return
const value = vditorInstance.value.getValue()
console.debug('CommentEditor submit', value)
- emit('submit', value)
- vditorInstance.value.setValue('')
- text.value = ''
+ emit('submit', value, () => {
+ if (!vditorInstance.value) return
+ vditorInstance.value.setValue('')
+ text.value = ''
+ })
}
onMounted(() => {
diff --git a/frontend/src/components/CommentItem.vue b/frontend/src/components/CommentItem.vue
index bf8201dda..3eab5be1b 100644
--- a/frontend/src/components/CommentItem.vue
+++ b/frontend/src/components/CommentItem.vue
@@ -157,7 +157,7 @@ const CommentItem = {
toast.error('操作失败')
}
}
- const submitReply = async (text) => {
+ const submitReply = async (text, clear) => {
if (!text.trim()) return
isWaitingForReply.value = true
const token = getToken()
@@ -201,6 +201,7 @@ const CommentItem = {
src: data.author.avatar,
iconClick: () => router.push(`/users/${data.author.id}`)
})
+ clear()
showEditor.value = false
toast.success('回复成功')
} else if (res.status === 429) {
diff --git a/frontend/src/views/PostPageView.vue b/frontend/src/views/PostPageView.vue
index 62c5d118d..48ad47bae 100644
--- a/frontend/src/views/PostPageView.vue
+++ b/frontend/src/views/PostPageView.vue
@@ -364,7 +364,7 @@ export default {
}
}
- const postComment = async (text) => {
+ const postComment = async (text, clear) => {
if (!text.trim()) return
console.debug('Posting comment', { postId, text })
isWaitingPostingComment.value = true
@@ -385,6 +385,7 @@ export default {
const data = await res.json()
console.debug('Post comment response data', data)
await fetchComments()
+ clear()
if (data.reward && data.reward > 0) {
toast.success(`评论成功,获得 ${data.reward} 经验值`)
} else {
From fbaa05f146012b637b3c19248574c1008409f7e3 Mon Sep 17 00:00:00 2001
From: Tim <135014430+nagisa77@users.noreply.github.com>
Date: Wed, 6 Aug 2025 19:32:56 +0800
Subject: [PATCH 13/17] feat: show compact vditor toolbar on mobile
---
frontend/src/assets/global.css | 2 +-
frontend/src/utils/vditor.js | 41 +++++++++++++++++++---------------
2 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/frontend/src/assets/global.css b/frontend/src/assets/global.css
index 1997730f4..97e58f834 100644
--- a/frontend/src/assets/global.css
+++ b/frontend/src/assets/global.css
@@ -235,7 +235,7 @@ body {
}
.vditor-toolbar {
- display: none;
+ overflow-x: auto;
}
.about-content h1,
diff --git a/frontend/src/utils/vditor.js b/frontend/src/utils/vditor.js
index f0a83214a..9888c1d2b 100644
--- a/frontend/src/utils/vditor.js
+++ b/frontend/src/utils/vditor.js
@@ -38,6 +38,28 @@ export function createVditor(editorId, options = {}) {
return searchUsers(value)
}
+ const isMobile = window.innerWidth <= 768
+ const toolbar = isMobile
+ ? ['emoji', 'bold', 'italic', 'strike', '|', 'link', 'upload']
+ : [
+ 'emoji',
+ 'bold',
+ 'italic',
+ 'strike',
+ '|',
+ 'list',
+ 'line',
+ 'quote',
+ 'code',
+ 'inline-code',
+ '|',
+ 'undo',
+ 'redo',
+ '|',
+ 'link',
+ 'upload'
+ ]
+
let vditor
vditor = new Vditor(editorId, {
placeholder,
@@ -62,24 +84,7 @@ export function createVditor(editorId, options = {}) {
],
},
cdn: 'https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/vditor',
- toolbar: [
- 'emoji',
- 'bold',
- 'italic',
- 'strike',
- '|',
- 'list',
- 'line',
- 'quote',
- 'code',
- 'inline-code',
- '|',
- 'undo',
- 'redo',
- '|',
- 'link',
- 'upload'
- ],
+ toolbar,
upload: {
accept: 'image/*,video/*',
multiple: false,
From 3de6b89cc4ae40187b50f66e31b74010f44e9346 Mon Sep 17 00:00:00 2001
From: tim
Date: Wed, 6 Aug 2025 19:47:51 +0800
Subject: [PATCH 14/17] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dvditor=E9=AB=98?=
=?UTF-8?q?=E5=BA=A6=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
frontend/src/components/PostEditor.vue | 8 +++++++-
frontend/src/utils/vditor.js | 2 +-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/frontend/src/components/PostEditor.vue b/frontend/src/components/PostEditor.vue
index 85b1ca9c5..63644222d 100644
--- a/frontend/src/components/PostEditor.vue
+++ b/frontend/src/components/PostEditor.vue
@@ -123,7 +123,6 @@ export default {
diff --git a/frontend/src/utils/vditor.js b/frontend/src/utils/vditor.js
index 9888c1d2b..93564b7d0 100644
--- a/frontend/src/utils/vditor.js
+++ b/frontend/src/utils/vditor.js
@@ -40,7 +40,7 @@ export function createVditor(editorId, options = {}) {
const isMobile = window.innerWidth <= 768
const toolbar = isMobile
- ? ['emoji', 'bold', 'italic', 'strike', '|', 'link', 'upload']
+ ? ['emoji', 'upload']
: [
'emoji',
'bold',
From b4f85989d05ee1a20d184b9354603c420528da3c Mon Sep 17 00:00:00 2001
From: tim
Date: Wed, 6 Aug 2025 20:10:25 +0800
Subject: [PATCH 15/17] =?UTF-8?q?feat:=20=E7=A7=BB=E5=8A=A8=E7=AB=AF=20vdi?=
=?UTF-8?q?tor=20=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
frontend/src/assets/global.css | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/frontend/src/assets/global.css b/frontend/src/assets/global.css
index 97e58f834..48188a8e0 100644
--- a/frontend/src/assets/global.css
+++ b/frontend/src/assets/global.css
@@ -255,6 +255,11 @@ body {
margin-bottom: 3px;
}
+
+ .vditor-toolbar--pin {
+ top: 0 !important;
+ }
+
.about-content li,
.info-content-text li {
font-size: 14px;
From 4a88685e81f65b36293780c3acf3bdba65da5364 Mon Sep 17 00:00:00 2001
From: Tim
Date: Wed, 6 Aug 2025 20:26:01 +0800
Subject: [PATCH 16/17] =?UTF-8?q?fix:=20=E7=A7=BB=E5=8A=A8=E7=AB=AF?=
=?UTF-8?q?=E8=A1=A8=E6=83=85=E9=9D=A2=E6=9D=BFfix?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/java/com/openisle/config/SecurityConfig.java | 4 ++--
frontend/src/main.js | 11 +++++++----
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/backend/src/main/java/com/openisle/config/SecurityConfig.java b/backend/src/main/java/com/openisle/config/SecurityConfig.java
index 5c9572837..51aa0d89e 100644
--- a/backend/src/main/java/com/openisle/config/SecurityConfig.java
+++ b/backend/src/main/java/com/openisle/config/SecurityConfig.java
@@ -77,8 +77,8 @@ public class SecurityConfig {
"http://127.0.0.1",
"http://localhost:8080",
"http://localhost",
- "http://30.211.98.193:8080",
- "http://30.211.98.193",
+ "http://30.211.106.178:8080",
+ "http://30.211.106.178",
"http://192.168.7.70",
"http://192.168.7.70:8080",
websiteUrl,
diff --git a/frontend/src/main.js b/frontend/src/main.js
index cb0db8df5..918b9b2ad 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -16,17 +16,20 @@ import ClickOutside from './directives/clickOutside' // 确保路径正确
// 采用本地开发环境
+export const API_DOMAIN = 'http://30.211.106.178'
+export const API_PORT = 8081
+
// export const API_DOMAIN = 'http://127.0.0.1'
// export const API_PORT = 8081
// 采用线上环境
-export const API_DOMAIN = 'https://www.open-isle.com'
-export const API_PORT = ''
+// export const API_DOMAIN = 'https://www.open-isle.com'
+// export const API_PORT = ''
// For 开发
-// export const API_BASE_URL = API_PORT ? `${API_DOMAIN}:${API_PORT}` : API_DOMAIN
+export const API_BASE_URL = API_PORT ? `${API_DOMAIN}:${API_PORT}` : API_DOMAIN
// 线上部署
-export const API_BASE_URL = ""
+// export const API_BASE_URL = ""
export const GOOGLE_CLIENT_ID = '777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com'
export const GITHUB_CLIENT_ID = 'Ov23liVkO1NPAX5JyWxJ'
From 925973b13439a66f48d8e0cca445d4da294f57a3 Mon Sep 17 00:00:00 2001
From: Tim
Date: Wed, 6 Aug 2025 20:31:58 +0800
Subject: [PATCH 17/17] fix
---
frontend/src/assets/global.css | 5 +++++
frontend/src/main.js | 11 ++++-------
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/frontend/src/assets/global.css b/frontend/src/assets/global.css
index 48188a8e0..af5513209 100644
--- a/frontend/src/assets/global.css
+++ b/frontend/src/assets/global.css
@@ -268,4 +268,9 @@ body {
.info-content-text pre {
line-height: 1.1;
}
+
+ .vditor-panel {
+ position: relative;
+ min-width: 0;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/main.js b/frontend/src/main.js
index 918b9b2ad..cb0db8df5 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -16,20 +16,17 @@ import ClickOutside from './directives/clickOutside' // 确保路径正确
// 采用本地开发环境
-export const API_DOMAIN = 'http://30.211.106.178'
-export const API_PORT = 8081
-
// export const API_DOMAIN = 'http://127.0.0.1'
// export const API_PORT = 8081
// 采用线上环境
-// export const API_DOMAIN = 'https://www.open-isle.com'
-// export const API_PORT = ''
+export const API_DOMAIN = 'https://www.open-isle.com'
+export const API_PORT = ''
// For 开发
-export const API_BASE_URL = API_PORT ? `${API_DOMAIN}:${API_PORT}` : API_DOMAIN
+// export const API_BASE_URL = API_PORT ? `${API_DOMAIN}:${API_PORT}` : API_DOMAIN
// 线上部署
-// export const API_BASE_URL = ""
+export const API_BASE_URL = ""
export const GOOGLE_CLIENT_ID = '777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com'
export const GITHUB_CLIENT_ID = 'Ov23liVkO1NPAX5JyWxJ'