From 90d32a5121afebed066adf893d5c3e386eca4fed Mon Sep 17 00:00:00 2001 From: Alex-larget <33240357+Alex-larget@users.noreply.github.com> Date: Sun, 8 Mar 2026 11:56:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E5=88=87=E6=8D=A2API=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E5=9C=B0=E5=9D=80=E8=87=B3=E7=9C=9F=E5=AE=9E=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E3=80=82=E5=AE=9E=E7=8E=B0@=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=8F=90=E5=8F=8A=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E5=9C=A8=E5=86=85=E5=AE=B9=E4=B8=AD=E6=8F=92=E5=85=A5=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E4=BF=A1=E6=81=AF=E5=B9=B6=E9=AB=98=E4=BA=AE=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=EF=BC=8C=E4=BC=98=E5=8C=96=E7=94=A8=E6=88=B7=E4=BD=93?= =?UTF-8?q?=E9=AA=8C=E3=80=82=E8=B0=83=E6=95=B4=E5=90=8E=E7=AB=AF=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E4=BB=A5=E6=94=AF=E6=8C=81=E5=85=8D=E8=B4=B9=E7=AB=A0?= =?UTF-8?q?=E8=8A=82=E7=9A=84=E5=88=A4=E6=96=AD=EF=BC=8C=E7=A1=AE=E4=BF=9D?= =?UTF-8?q?=E7=AB=A0=E8=8A=82=E4=BF=A1=E6=81=AF=E7=9A=84=E5=87=86=E7=A1=AE?= =?UTF-8?q?=E6=80=A7=E4=B8=8E=E4=B8=80=E8=87=B4=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- miniprogram/app.js | 4 +- soul-admin/src/pages/content/ContentPage.tsx | 119 ++++++++++++++++++- soul-api/internal/handler/book.go | 72 +++++++++-- 3 files changed, 181 insertions(+), 14 deletions(-) diff --git a/miniprogram/app.js b/miniprogram/app.js index a641870e..1abc1ba6 100644 --- a/miniprogram/app.js +++ b/miniprogram/app.js @@ -8,9 +8,9 @@ const { parseScene } = require('./utils/scene.js') App({ globalData: { // API基础地址 - 连接真实后端 - // baseUrl: 'https://soulapi.quwanzhi.com', + baseUrl: 'https://soulapi.quwanzhi.com', // baseUrl: 'https://souldev.quwanzhi.com', - baseUrl: 'http://localhost:8080', + // baseUrl: 'http://localhost:8080', // 小程序配置 - 真实AppID diff --git a/soul-admin/src/pages/content/ContentPage.tsx b/soul-admin/src/pages/content/ContentPage.tsx index 62ef491d..a32ba9b4 100644 --- a/soul-admin/src/pages/content/ContentPage.tsx +++ b/soul-admin/src/pages/content/ContentPage.tsx @@ -36,6 +36,7 @@ import { Plus, Image as ImageIcon, Search, + AtSign, } from 'lucide-react' import { get, put, del } from '@/api/client' import { ChapterTree } from './ChapterTree' @@ -156,6 +157,12 @@ export function ContentPage() { const [editingPart, setEditingPart] = useState<{ id: string; title: string } | null>(null) const [isSavingPartTitle, setIsSavingPartTitle] = useState(false) + const [showMentionUserDialog, setShowMentionUserDialog] = useState(false) + const [mentionTarget, setMentionTarget] = useState<'new' | 'edit'>('new') + const [mentionUserList, setMentionUserList] = useState<{ id: string; nickname: string }[]>([]) + const [mentionUserSearch, setMentionUserSearch] = useState('') + const [mentionUserLoading, setMentionUserLoading] = useState(false) + const tree = buildTree(sectionsList) const totalSections = sectionsList.length @@ -178,6 +185,43 @@ export function ContentPage() { loadList() }, []) + const loadMentionUsers = useCallback(async () => { + setMentionUserLoading(true) + try { + const params = new URLSearchParams({ pageSize: '200' }) + if (mentionUserSearch.trim()) params.set('search', mentionUserSearch.trim()) + const data = await get<{ success?: boolean; users?: { id: string; nickname?: string }[] }>( + `/api/db/users?${params}`, + ) + const users = Array.isArray(data?.users) ? data.users : [] + setMentionUserList(users.map((u) => ({ id: String(u.id), nickname: u.nickname || '用户' }))) + } catch (e) { + console.error(e) + setMentionUserList([]) + } finally { + setMentionUserLoading(false) + } + }, [mentionUserSearch]) + + useEffect(() => { + if (showMentionUserDialog) loadMentionUsers() + }, [showMentionUserDialog, loadMentionUsers]) + + const openMentionUserDialog = (target: 'new' | 'edit') => { + setMentionTarget(target) + setMentionUserSearch('') + setShowMentionUserDialog(true) + } + + const insertMentionUser = (user: { id: string; nickname: string }) => { + const snippet = `{{@${user.id}:${user.nickname}}}` + if (mentionTarget === 'new') { + setNewSection((prev) => ({ ...prev, content: (prev.content || '') + snippet })) + } else if (editingSection) { + setEditingSection({ ...editingSection, content: (editingSection.content || '') + snippet }) + } + setShowMentionUserDialog(false) + } const togglePart = (partId: string) => { setExpandedParts((prev) => @@ -563,10 +607,22 @@ export function ContentPage() {
- +
+ + +