支持消息 Markdown 与欢迎语富文本
聊天/离线提示使用 Markdown 安全渲染;欢迎语改为 TipTap 富文本(颜色字号),DOMPurify 白名单清洗后展示。
This commit is contained in:
@@ -16,6 +16,8 @@ import {
|
||||
type Channel, type CustomerTag, type StaffUser, type TenantSettings, type WorkHours, type WelcomeSegment,
|
||||
} from '@/services/api'
|
||||
import { useAuth } from '@/stores/auth'
|
||||
import MarkdownEditor from '@/components/common/MarkdownEditor'
|
||||
import RichTextEditor from '@/components/common/RichTextEditor'
|
||||
|
||||
const tagColorPresets: { value: string; label: string; bg: string; color: string }[] = [
|
||||
{ value: 'amber', label: '琥珀', bg: '#fef3c7', color: '#92400e' },
|
||||
@@ -834,9 +836,12 @@ const Settings = () => {
|
||||
}
|
||||
for (let i = 0; i < welcomeSegments.length; i++) {
|
||||
const seg = welcomeSegments[i]
|
||||
if (seg.type === 'text' && !seg.content.trim()) {
|
||||
message.error(`第 ${i + 1} 段文本不能为空`)
|
||||
return
|
||||
if (seg.type === 'text') {
|
||||
const plain = seg.content.replace(/<[^>]+>/g, '').replace(/ /g, ' ').trim()
|
||||
if (!plain) {
|
||||
message.error(`第 ${i + 1} 段文本不能为空`)
|
||||
return
|
||||
}
|
||||
}
|
||||
if (seg.type === 'image' && !seg.content.trim()) {
|
||||
message.error(`第 ${i + 1} 段请上传图片`)
|
||||
@@ -857,7 +862,8 @@ const Settings = () => {
|
||||
<div>
|
||||
<div className="text-sm font-medium text-neutral-800">欢迎语(多段)</div>
|
||||
<p className="text-xs text-neutral-500 m-0 mt-0.5">
|
||||
访客打开窗口且尚无消息时按顺序展示;可混排文本与图片,最多 {MAX_WELCOME_SEGMENTS} 段。
|
||||
访客打开窗口且尚无消息时按顺序展示;可混排富文本与图片,最多 {MAX_WELCOME_SEGMENTS} 段。
|
||||
选中文字可设置<strong className="font-medium text-neutral-600">颜色、字号、加粗</strong>等(仅欢迎语;正常聊天仍为 Markdown)。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -913,14 +919,10 @@ const Settings = () => {
|
||||
</div>
|
||||
</div>
|
||||
{seg.type === 'text' ? (
|
||||
<Input.TextArea
|
||||
rows={2}
|
||||
maxLength={500}
|
||||
showCount
|
||||
<RichTextEditor
|
||||
value={seg.content}
|
||||
placeholder="访客打开窗口时展示的文案"
|
||||
onChange={e => {
|
||||
const v = e.target.value
|
||||
placeholder="输入欢迎语,选中文字后设置颜色、字号…"
|
||||
onChange={v => {
|
||||
setWelcomeSegments(prev =>
|
||||
prev.map((s, i) => (i === idx ? { ...s, content: v } : s)),
|
||||
)
|
||||
@@ -1006,8 +1008,18 @@ const Settings = () => {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Form.Item name="offline_prompt" label="离线留言提示" rules={[{ max: 500 }]}>
|
||||
<Input.TextArea rows={3} maxLength={500} showCount placeholder="无客服在线时展示" />
|
||||
<Form.Item
|
||||
name="offline_prompt"
|
||||
label="离线留言提示"
|
||||
rules={[{ max: 500 }]}
|
||||
extra="点工具栏设置加粗、列表、链接、表情;可点「预览」查看效果"
|
||||
>
|
||||
<MarkdownEditor
|
||||
rows={3}
|
||||
maxLength={500}
|
||||
showCount
|
||||
placeholder="无客服在线时展示…"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item className="!mb-0">
|
||||
<Button type="primary" htmlType="submit" loading={saving}>保存</Button>
|
||||
|
||||
Reference in New Issue
Block a user