聊天室更新markdown
This commit is contained in:
@@ -345,3 +345,86 @@ $brand-color-hover: #004488;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Markdown样式 ====================
|
||||
.message-bubble {
|
||||
// 粗体
|
||||
strong {
|
||||
font-weight: 600;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
// 斜体
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
// 行内代码
|
||||
.inline-code {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
color: #e53e3e;
|
||||
}
|
||||
|
||||
// 代码块
|
||||
.code-block {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
margin: 8px 0;
|
||||
|
||||
code {
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #334155;
|
||||
}
|
||||
}
|
||||
|
||||
// 链接
|
||||
.md-link {
|
||||
color: $brand-color;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: $brand-color-hover;
|
||||
}
|
||||
}
|
||||
|
||||
// 标题
|
||||
.md-h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
margin: 12px 0 8px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.md-h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin: 10px 0 6px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.md-h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 8px 0 4px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
// 列表
|
||||
.md-ul, .md-ol {
|
||||
margin: 8px 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.md-li {
|
||||
margin: 4px 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@
|
||||
<!-- 消息内容 -->
|
||||
<div class="message-content-wrapper">
|
||||
<div class="message-bubble">
|
||||
<p class="message-text">{{ message.content }}</p>
|
||||
<div
|
||||
class="message-text"
|
||||
v-html="renderMarkdown(message.content || '')"
|
||||
></div>
|
||||
|
||||
<!-- 文件列表 -->
|
||||
<div v-if="message.files && message.files.length > 0" class="message-files">
|
||||
@@ -235,14 +238,59 @@ const formatTime = (time?: string) => {
|
||||
const date = new Date(time)
|
||||
const now = new Date()
|
||||
const diff = now.getTime() - date.getTime()
|
||||
|
||||
|
||||
if (diff < 60000) return '刚刚'
|
||||
if (diff < 3600000) return Math.floor(diff / 60000) + '分钟前'
|
||||
if (diff < 86400000) return Math.floor(diff / 3600000) + '小时前'
|
||||
|
||||
|
||||
return date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' })
|
||||
}
|
||||
|
||||
// Markdown渲染函数
|
||||
const renderMarkdown = (text: string): string => {
|
||||
if (!text) return ''
|
||||
|
||||
// 转义HTML标签
|
||||
let html = text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
|
||||
// 处理代码块(```语法)
|
||||
html = html.replace(/```(\w+)?\n([\s\S]*?)```/g, (match, lang, code) => {
|
||||
return `<pre class="code-block"><code class="language-${lang || 'text'}">${code.trim()}</code></pre>`
|
||||
})
|
||||
|
||||
// 处理行内代码(`语法)
|
||||
html = html.replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>')
|
||||
|
||||
// 处理粗体(**语法)
|
||||
html = html.replace(/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>')
|
||||
|
||||
// 处理斜体(*语法)
|
||||
html = html.replace(/\*([^\*]+)\*/g, '<em>$1</em>')
|
||||
|
||||
// 处理链接([text](url)语法)
|
||||
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" class="md-link">$1</a>')
|
||||
|
||||
// 处理标题(# ## ###等)
|
||||
html = html.replace(/^### (.+)$/gm, '<h3 class="md-h3">$1</h3>')
|
||||
html = html.replace(/^## (.+)$/gm, '<h2 class="md-h2">$1</h2>')
|
||||
html = html.replace(/^# (.+)$/gm, '<h1 class="md-h1">$1</h1>')
|
||||
|
||||
// 处理无序列表(- 或 * 开头)
|
||||
html = html.replace(/^[*-] (.+)$/gm, '<li class="md-li">$1</li>')
|
||||
html = html.replace(/(<li class="md-li">.*<\/li>)/s, '<ul class="md-ul">$1</ul>')
|
||||
|
||||
// 处理有序列表(数字. 开头)
|
||||
html = html.replace(/^\d+\. (.+)$/gm, '<li class="md-li">$1</li>')
|
||||
|
||||
// 处理换行
|
||||
html = html.replace(/\n/g, '<br>')
|
||||
|
||||
return html
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
scrollToBottom
|
||||
|
||||
@@ -361,7 +361,6 @@ $brand-color-hover: #004488;
|
||||
|
||||
// ==================== 消息列表 ====================
|
||||
.messages-list {
|
||||
max-width: 768px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
|
||||
@@ -485,7 +484,6 @@ $brand-color-hover: #004488;
|
||||
background: #fff;
|
||||
|
||||
.quick-bar-inner {
|
||||
max-width: 768px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
@@ -528,7 +526,6 @@ $brand-color-hover: #004488;
|
||||
background: #f8fafc;
|
||||
|
||||
.input-wrapper {
|
||||
max-width: 768px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@@ -616,3 +613,107 @@ $brand-color-hover: #004488;
|
||||
margin: 12px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Markdown样式 ====================
|
||||
.message-bubble {
|
||||
// 粗体
|
||||
strong {
|
||||
font-weight: 600;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
// 斜体
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
// 行内代码
|
||||
.inline-code {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
color: #e53e3e;
|
||||
}
|
||||
|
||||
// 代码块
|
||||
.code-block {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
margin: 8px 0;
|
||||
|
||||
code {
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #334155;
|
||||
}
|
||||
}
|
||||
|
||||
// 链接
|
||||
.md-link {
|
||||
color: $brand-color;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: $brand-color-hover;
|
||||
}
|
||||
}
|
||||
|
||||
// 标题
|
||||
.md-h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
margin: 12px 0 8px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.md-h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin: 10px 0 6px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.md-h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 8px 0 4px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
// 列表
|
||||
.md-ul, .md-ol {
|
||||
margin: 8px 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.md-li {
|
||||
margin: 4px 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
// 用户消息中的markdown样式(白色背景)
|
||||
.message-bubble.user {
|
||||
.inline-code {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
|
||||
code {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.md-link {
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
>
|
||||
<MessageCircle :size="16" class="conv-icon" />
|
||||
<div class="conv-info">
|
||||
<div class="conv-title">{{ conv.title || '新对话' }}</div>
|
||||
<div class="conv-title">{{ getPlainTextPreview(conv.title || '新对话') }}</div>
|
||||
<div class="conv-time">{{ formatTime(conv.createTime) }}</div>
|
||||
</div>
|
||||
<button
|
||||
@@ -124,10 +124,13 @@
|
||||
|
||||
<!-- 消息内容 -->
|
||||
<div class="message-bubble" :class="msg.role">
|
||||
<p class="message-text">
|
||||
{{ msg.text }}
|
||||
<span v-if="isStreaming && msg.role === 'assistant' && messages.indexOf(msg) === messages.length - 1" class="typing-cursor">|</span>
|
||||
</p>
|
||||
<div
|
||||
v-if="msg.text"
|
||||
class="message-text"
|
||||
v-html="msg.role === 'assistant' ? renderMarkdown(msg.text) : msg.text"
|
||||
>
|
||||
</div>
|
||||
<span v-if="isStreaming && msg.role === 'assistant' && messages.indexOf(msg) === messages.length - 1" class="typing-cursor">|</span>
|
||||
<div v-if="!msg.text && isStreaming && msg.role === 'assistant'" class="loading-dots">
|
||||
<span></span><span></span><span></span>
|
||||
</div>
|
||||
@@ -521,13 +524,90 @@ const formatTime = (time?: string | number): string => {
|
||||
const date = new Date(time)
|
||||
const now = new Date()
|
||||
const isToday = date.toDateString() === now.toDateString()
|
||||
|
||||
|
||||
if (isToday) {
|
||||
return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
return date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' })
|
||||
}
|
||||
|
||||
// 去除markdown语法并截取前10个字符(用于历史对话列表预览)
|
||||
const getPlainTextPreview = (text: string): string => {
|
||||
if (!text) return ''
|
||||
|
||||
// 去除markdown语法
|
||||
let plainText = text
|
||||
// 去除代码块
|
||||
.replace(/```[\s\S]*?```/g, '[代码]')
|
||||
// 去除行内代码
|
||||
.replace(/`([^`]+)`/g, '$1')
|
||||
// 去除粗体
|
||||
.replace(/\*\*([^\*]+)\*\*/g, '$1')
|
||||
// 去除斜体
|
||||
.replace(/\*([^\*]+)\*/g, '$1')
|
||||
// 去除链接
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||
// 去除标题标记
|
||||
.replace(/^#{1,6}\s+/gm, '')
|
||||
// 去除列表标记
|
||||
.replace(/^[*-]\s+/gm, '')
|
||||
// 去除多余的空白字符
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
|
||||
// 截取前10个字符
|
||||
if (plainText.length > 10) {
|
||||
return plainText.substring(0, 10) + '...'
|
||||
}
|
||||
|
||||
return plainText
|
||||
}
|
||||
|
||||
// Markdown渲染函数
|
||||
const renderMarkdown = (text: string): string => {
|
||||
if (!text) return ''
|
||||
|
||||
// 转义HTML标签
|
||||
let html = text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
|
||||
// 处理代码块(```语法)
|
||||
html = html.replace(/```(\w+)?\n([\s\S]*?)```/g, (match, lang, code) => {
|
||||
return `<pre class="code-block"><code class="language-${lang || 'text'}">${code.trim()}</code></pre>`
|
||||
})
|
||||
|
||||
// 处理行内代码(`语法)
|
||||
html = html.replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>')
|
||||
|
||||
// 处理粗体(**语法)
|
||||
html = html.replace(/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>')
|
||||
|
||||
// 处理斜体(*语法)
|
||||
html = html.replace(/\*([^\*]+)\*/g, '<em>$1</em>')
|
||||
|
||||
// 处理链接([text](url)语法)
|
||||
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" class="md-link">$1</a>')
|
||||
|
||||
// 处理标题(# ## ###等)
|
||||
html = html.replace(/^### (.+)$/gm, '<h3 class="md-h3">$1</h3>')
|
||||
html = html.replace(/^## (.+)$/gm, '<h2 class="md-h2">$1</h2>')
|
||||
html = html.replace(/^# (.+)$/gm, '<h1 class="md-h1">$1</h1>')
|
||||
|
||||
// 处理无序列表(- 或 * 开头)
|
||||
html = html.replace(/^[*-] (.+)$/gm, '<li class="md-li">$1</li>')
|
||||
html = html.replace(/(<li class="md-li">.*<\/li>)/s, '<ul class="md-ul">$1</ul>')
|
||||
|
||||
// 处理有序列表(数字. 开头)
|
||||
html = html.replace(/^\d+\. (.+)$/gm, '<li class="md-li">$1</li>')
|
||||
|
||||
// 处理换行
|
||||
html = html.replace(/\n/g, '<br>')
|
||||
|
||||
return html
|
||||
}
|
||||
|
||||
// 处理快捷命令
|
||||
const handleQuickCommand = (query: string) => {
|
||||
inputText.value = query
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
</view>
|
||||
<view class="message-content">
|
||||
<view class="bubble other-bubble">
|
||||
<text class="message-text">{{ msg.content }}</text>
|
||||
<rich-text :nodes="renderMarkdown(msg.content || '')" class="message-rich-text"></rich-text>
|
||||
</view>
|
||||
<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
|
||||
</view>
|
||||
@@ -396,6 +396,42 @@ function formatTime(time?: string): string {
|
||||
return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
// Markdown渲染函数(返回富文本HTML)
|
||||
function renderMarkdown(text: string): string {
|
||||
if (!text) return ''
|
||||
|
||||
// 转义HTML特殊字符
|
||||
let html = text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
|
||||
// 处理粗体(**语法)
|
||||
html = html.replace(/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>')
|
||||
|
||||
// 处理斜体(*语法,但要避免和粗体冲突)
|
||||
html = html.replace(/(?<!\*)\*([^\*]+)\*(?!\*)/g, '<em>$1</em>')
|
||||
|
||||
// 处理行内代码(`语法)
|
||||
html = html.replace(/`([^`]+)`/g, '<code style="background-color:#f5f5f5;padding:2px 6px;border-radius:3px;font-family:monospace;color:#e53e3e;">$1</code>')
|
||||
|
||||
// 处理链接([text](url)语法)
|
||||
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color:#0055AA;text-decoration:underline;">$1</a>')
|
||||
|
||||
// 处理标题(# ## ###等)
|
||||
html = html.replace(/^### (.+)$/gm, '<div style="font-size:16px;font-weight:600;margin:8px 0 4px;">$1</div>')
|
||||
html = html.replace(/^## (.+)$/gm, '<div style="font-size:18px;font-weight:600;margin:10px 0 6px;">$1</div>')
|
||||
html = html.replace(/^# (.+)$/gm, '<div style="font-size:20px;font-weight:700;margin:12px 0 8px;">$1</div>')
|
||||
|
||||
// 处理无序列表(- 或 * 开头)
|
||||
html = html.replace(/^[*-] (.+)$/gm, '<div style="margin-left:16px;">• $1</div>')
|
||||
|
||||
// 处理换行
|
||||
html = html.replace(/\n/g, '<br/>')
|
||||
|
||||
return html
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
async function sendMessage() {
|
||||
const text = inputText.value.trim()
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<text class="room-time">{{ formatTime(room.lastMessageTime) }}</text>
|
||||
</view>
|
||||
<view class="room-footer">
|
||||
<text class="last-message">{{ room.lastMessage || '暂无消息' }}</text>
|
||||
<text class="last-message">{{ getPlainTextPreview(room.lastMessage) }}</text>
|
||||
<view class="unread-badge" v-if="room.unreadCount && room.unreadCount > 0">
|
||||
<text class="badge-text">{{ room.unreadCount > 99 ? '99+' : room.unreadCount }}</text>
|
||||
</view>
|
||||
@@ -136,18 +136,50 @@ function formatTime(time?: string): string {
|
||||
const iosCompatibleTime = time.replace(' ', 'T')
|
||||
const date = new Date(iosCompatibleTime)
|
||||
if (isNaN(date.getTime())) return ''
|
||||
|
||||
|
||||
const now = new Date()
|
||||
const diff = now.getTime() - date.getTime()
|
||||
|
||||
|
||||
if (diff < 60000) return '刚刚'
|
||||
if (diff < 3600000) return Math.floor(diff / 60000) + '分钟前'
|
||||
if (diff < 86400000) return Math.floor(diff / 3600000) + '小时前'
|
||||
if (diff < 172800000) return '昨天'
|
||||
|
||||
|
||||
return `${date.getMonth() + 1}/${date.getDate()}`
|
||||
}
|
||||
|
||||
// 去除markdown语法并截取前10个字符
|
||||
function getPlainTextPreview(text?: string): string {
|
||||
if (!text) return '暂无消息'
|
||||
|
||||
// 去除markdown语法
|
||||
let plainText = text
|
||||
// 去除代码块
|
||||
.replace(/```[\s\S]*?```/g, '[代码]')
|
||||
// 去除行内代码
|
||||
.replace(/`([^`]+)`/g, '$1')
|
||||
// 去除粗体
|
||||
.replace(/\*\*([^\*]+)\*\*/g, '$1')
|
||||
// 去除斜体
|
||||
.replace(/\*([^\*]+)\*/g, '$1')
|
||||
// 去除链接
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||
// 去除标题标记
|
||||
.replace(/^#{1,6}\s+/gm, '')
|
||||
// 去除列表标记
|
||||
.replace(/^[*-]\s+/gm, '')
|
||||
// 去除多余的空白字符
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
|
||||
// 截取前10个字符
|
||||
if (plainText.length > 10) {
|
||||
return plainText.substring(0, 10) + '...'
|
||||
}
|
||||
|
||||
return plainText
|
||||
}
|
||||
|
||||
// 获取状态样式类
|
||||
function getStatusClass(status?: string): string {
|
||||
switch (status) {
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<view class="typing-dot"></view>
|
||||
<view class="typing-dot"></view>
|
||||
</view>
|
||||
<text class="message-text" v-else>{{item.content}}</text>
|
||||
<rich-text v-else :nodes="renderMarkdown(item.content)" class="message-rich-text"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="message-time">{{item.time}}</text>
|
||||
@@ -503,6 +503,42 @@
|
||||
await callAIChat(question)
|
||||
}
|
||||
|
||||
// Markdown渲染函数(返回富文本节点)
|
||||
function renderMarkdown(text : string) : string {
|
||||
if (!text) return ''
|
||||
|
||||
// 转义HTML特殊字符
|
||||
let html = text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
|
||||
// 处理粗体(**语法)
|
||||
html = html.replace(/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>')
|
||||
|
||||
// 处理斜体(*语法,但要避免和粗体冲突)
|
||||
html = html.replace(/(?<!\*)\*([^\*]+)\*(?!\*)/g, '<em>$1</em>')
|
||||
|
||||
// 处理行内代码(`语法)
|
||||
html = html.replace(/`([^`]+)`/g, '<code style="background-color:#f5f5f5;padding:2px 6px;border-radius:3px;font-family:monospace;color:#e53e3e;">$1</code>')
|
||||
|
||||
// 处理链接([text](url)语法)
|
||||
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color:#0055AA;text-decoration:underline;">$1</a>')
|
||||
|
||||
// 处理标题(# ## ###等)
|
||||
html = html.replace(/^### (.+)$/gm, '<div style="font-size:16px;font-weight:600;margin:8px 0 4px;">$1</div>')
|
||||
html = html.replace(/^## (.+)$/gm, '<div style="font-size:18px;font-weight:600;margin:10px 0 6px;">$1</div>')
|
||||
html = html.replace(/^# (.+)$/gm, '<div style="font-size:20px;font-weight:700;margin:12px 0 8px;">$1</div>')
|
||||
|
||||
// 处理无序列表(- 或 * 开头)
|
||||
html = html.replace(/^[*-] (.+)$/gm, '<div style="margin-left:16px;">• $1</div>')
|
||||
|
||||
// 处理换行
|
||||
html = html.replace(/\n/g, '<br/>')
|
||||
|
||||
return html
|
||||
}
|
||||
|
||||
// 显示上传选项
|
||||
function showUploadOptions() {
|
||||
uni.showActionSheet({
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"libVersion": "3.12.1",
|
||||
"projectname": "workcase_wechat",
|
||||
"setting": {
|
||||
"urlCheck": true,
|
||||
"urlCheck": false,
|
||||
"coverView": true,
|
||||
"lazyloadPlaceholderEnable": false,
|
||||
"skylineRenderEnable": false,
|
||||
|
||||
Reference in New Issue
Block a user