mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-06 17:36:42 +08:00
feat(portal): 实现消息组件支持 Mermaid 图表渲染
- 添加 markdown-it-mermaid 插件支持 Mermaid 语法 - 集成 mermaid 库并初始化配置 - 实现打字机效果与 Mermaid 渲染结合 -优化案例引用展示逻辑与样式- 添加推荐问题展示功能 - 改进消息组件的响应式与样式细节 - 修复组件销毁时定时器未清除的问题 - 更新依赖包引入 Mermaid 相关库
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mermaid-js/parser": "^0.6.3",
|
||||||
"axios": "^0.21.4",
|
"axios": "^0.21.4",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"driver.js": "^0.9.8",
|
"driver.js": "^0.9.8",
|
||||||
@@ -30,6 +31,8 @@
|
|||||||
"katex": "^0.16.25",
|
"katex": "^0.16.25",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"markdown-it-highlightjs": "^4.2.0",
|
"markdown-it-highlightjs": "^4.2.0",
|
||||||
|
"markdown-it-mermaid": "^0.2.5",
|
||||||
|
"mermaid": "^8.13.10",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
|||||||
@@ -1,118 +1,20 @@
|
|||||||
<!--消息渲染-->
|
|
||||||
<script>
|
|
||||||
import MarkdownIt from 'markdown-it';
|
|
||||||
import highlight from 'markdown-it-highlightjs'
|
|
||||||
import "highlight.js/styles/a11y-dark.css"
|
|
||||||
import katex from "katex"
|
|
||||||
|
|
||||||
const md = new MarkdownIt({
|
|
||||||
}).use(highlight);
|
|
||||||
export default {
|
|
||||||
name: "message",
|
|
||||||
props: {
|
|
||||||
messageData: {
|
|
||||||
type: Object,
|
|
||||||
default: function () {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
suggestions: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
md,
|
|
||||||
displayText: '',
|
|
||||||
typingTimer: null,
|
|
||||||
typingSpeed: 30, // 打字机速度(毫秒/字符)
|
|
||||||
showAllCaseRefers: false // 控制是否显示所有案例引用
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
// 计算需要显示的案例引用
|
|
||||||
displayedCaseRefers() {
|
|
||||||
if (this.showAllCaseRefers || !this.messageData.caseRefers) {
|
|
||||||
return this.messageData.caseRefers || [];
|
|
||||||
}
|
|
||||||
return this.messageData.caseRefers.slice(0, 3);
|
|
||||||
},
|
|
||||||
// 判断是否需要显示"查看更多"按钮
|
|
||||||
shouldShowMoreButton() {
|
|
||||||
return this.messageData.caseRefers && this.messageData.caseRefers.length > 3;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'messageData.text': {
|
|
||||||
handler(newVal) {
|
|
||||||
if (newVal && this.messageData.isBot && !this.messageData.typing) {
|
|
||||||
// this.startTyping(newVal)
|
|
||||||
this.displayText = newVal || ''
|
|
||||||
} else {
|
|
||||||
this.displayText = newVal || ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toUrl(item) {
|
|
||||||
console.log(item);
|
|
||||||
this.$router.push({
|
|
||||||
path: '/case/detail',
|
|
||||||
query: {
|
|
||||||
id: item.caseId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
startTyping(text) {
|
|
||||||
// 清除之前的定时器
|
|
||||||
if (this.typingTimer) {
|
|
||||||
clearInterval(this.typingTimer)
|
|
||||||
this.typingTimer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
// this.displayText = ''
|
|
||||||
let index = 0
|
|
||||||
|
|
||||||
// 开始打字机效果
|
|
||||||
this.typingTimer = setInterval(() => {
|
|
||||||
if (index < text.length) {
|
|
||||||
this.displayText += md.render(text.charAt(index))
|
|
||||||
index++
|
|
||||||
} else {
|
|
||||||
// 打字完成,清除定时器
|
|
||||||
clearInterval(this.typingTimer)
|
|
||||||
this.typingTimer = null
|
|
||||||
}
|
|
||||||
}, this.typingSpeed)
|
|
||||||
},
|
|
||||||
// 切换显示所有案例引用
|
|
||||||
toggleShowAllCaseRefers() {
|
|
||||||
this.showAllCaseRefers = !this.showAllCaseRefers;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
// 组件销毁前清除定时器
|
|
||||||
if (this.typingTimer) {
|
|
||||||
clearInterval(this.typingTimer)
|
|
||||||
this.typingTimer = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="messages">
|
<div class="messages">
|
||||||
<!-- 机器人消息 -->
|
<!-- 机器人消息 -->
|
||||||
<div v-if="messageData.isBot" class="bot-message">
|
<div v-if="messageData.isBot" class="bot-message">
|
||||||
<div class="bot-think" v-if="messageData.thinkText" v-katex:auto v-html="md.render(messageData.thinkText)"></div>
|
<!-- 思考中提示 -->
|
||||||
<div v-katex:auto v-html="md.render(displayText)" ></div>
|
<div v-if="messageData.thinkText" class="bot-think" v-katex:auto v-html="md.render(messageData.thinkText)"></div>
|
||||||
<div v-if="messageData.caseRefers && messageData.caseRefers.length > 0 && messageData.textCompleted">
|
|
||||||
<div class="case-refers">
|
<!-- 主要回复内容 -->
|
||||||
|
<div
|
||||||
|
ref="contentContainer"
|
||||||
|
class="message-content"
|
||||||
|
v-katex:auto
|
||||||
|
v-html="displayText"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<!-- 引用案例 -->
|
||||||
|
<div v-if="messageData.caseRefers && messageData.caseRefers.length > 0 && messageData.textCompleted" class="case-refers">
|
||||||
<div class="case-refers-title">
|
<div class="case-refers-title">
|
||||||
<span><i class="iconfont icon-think"></i> 引用案例</span>
|
<span><i class="iconfont icon-think"></i> 引用案例</span>
|
||||||
<span v-if="shouldShowMoreButton" class="more" @click="toggleShowAllCaseRefers">
|
<span v-if="shouldShowMoreButton" class="more" @click="toggleShowAllCaseRefers">
|
||||||
@@ -120,7 +22,11 @@ export default {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="case-refers-list">
|
<div class="case-refers-list">
|
||||||
<div class="case-refers-item" v-for="item in displayedCaseRefers" :key="item.caseId">
|
<div
|
||||||
|
v-for="item in displayedCaseRefers"
|
||||||
|
:key="item.caseId"
|
||||||
|
class="case-refers-item"
|
||||||
|
>
|
||||||
<div class="case-refers-item-title">
|
<div class="case-refers-item-title">
|
||||||
<a @click="toUrl(item)" class="title">{{ item.title }}</a>
|
<a @click="toUrl(item)" class="title">{{ item.title }}</a>
|
||||||
<span class="case-refers-item-timer">{{ item.uploadTime }}</span>
|
<span class="case-refers-item-timer">{{ item.uploadTime }}</span>
|
||||||
@@ -133,44 +39,180 @@ export default {
|
|||||||
<div class="case-refers-item-keywords">
|
<div class="case-refers-item-keywords">
|
||||||
<span v-for="keyword in item.keywords" :key="keyword">{{ keyword }}</span>
|
<span v-for="keyword in item.keywords" :key="keyword">{{ keyword }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="message-content case-content" v-html="md.render(item.content)"></div>
|
||||||
<div class="message-content">{{item.content}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 非机器人消息-->
|
<!-- 用户消息 -->
|
||||||
<div v-else class="user-message">
|
<div v-else class="user-message">
|
||||||
<div class="message-text">
|
<div class="message-text" v-html="messageData.text"></div>
|
||||||
<div v-html="messageData.text"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 推荐问题 -->
|
<!-- 推荐问题 -->
|
||||||
|
<div v-if="suggestions && suggestions.length > 0" class="suggestions">
|
||||||
<!-- <div v-if="suggestions && suggestions.length > 0">-->
|
<div class="suggestions-title">💡 推荐问题</div>
|
||||||
<!-- <div class="suggestions">-->
|
<div class="suggestions-list">
|
||||||
<!-- <div class="suggestions-title">-->
|
<button
|
||||||
<!-- <span>推荐问题</span>-->
|
v-for="(item, index) in suggestions"
|
||||||
<!-- </div>-->
|
:key="index"
|
||||||
<!-- <div class="suggestions-list">-->
|
class="suggestions-item"
|
||||||
<!-- <div class="suggestions-item" v-for="item in suggestions">-->
|
@click="$emit('suggestion-click', item)"
|
||||||
<!-- <div class="suggestions-item-title">-->
|
>
|
||||||
<!-- {{item}}-->
|
{{ item }}
|
||||||
<!-- </div>-->
|
</button>
|
||||||
<!-- </div>-->
|
</div>
|
||||||
<!-- </div>-->
|
</div>
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MarkdownIt from 'markdown-it';
|
||||||
|
import highlight from 'markdown-it-highlightjs';
|
||||||
|
import 'highlight.js/styles/a11y-dark.css';
|
||||||
|
import markdownItMermaid from 'markdown-it-mermaid';
|
||||||
|
import mermaid from 'mermaid';
|
||||||
|
|
||||||
|
// 初始化 Mermaid
|
||||||
|
mermaid.initialize({ startOnLoad: false });
|
||||||
|
|
||||||
|
const md = new MarkdownIt({
|
||||||
|
html: true,
|
||||||
|
linkify: true,
|
||||||
|
typographer: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
md.use(highlight).use(markdownItMermaid);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Message',
|
||||||
|
props: {
|
||||||
|
messageData: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
suggestions: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
md,
|
||||||
|
displayText: '',
|
||||||
|
typingTimer: null,
|
||||||
|
typingSpeed: 30, // 毫秒/字符
|
||||||
|
showAllCaseRefers: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
displayedCaseRefers() {
|
||||||
|
if (this.showAllCaseRefers || !this.messageData.caseRefers) {
|
||||||
|
return this.messageData.caseRefers || [];
|
||||||
|
}
|
||||||
|
return this.messageData.caseRefers.slice(0, 3);
|
||||||
|
},
|
||||||
|
shouldShowMoreButton() {
|
||||||
|
return this.messageData.caseRefers && this.messageData.caseRefers.length > 3;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'messageData.text': {
|
||||||
|
handler(newVal) {
|
||||||
|
if (!newVal) {
|
||||||
|
this.displayText = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.messageData.isBot && !this.messageData.typing) {
|
||||||
|
this.startTyping(newVal); // 启动打字机效果
|
||||||
|
} else {
|
||||||
|
this.displayText = this.md.render(newVal);
|
||||||
|
this.$nextTick(this.renderMermaid); // 直接渲染 Mermaid
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toUrl(item) {
|
||||||
|
this.$router.push({
|
||||||
|
path: '/case/detail',
|
||||||
|
query: { id: item.caseId },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 正确的打字机效果:先整体渲染 Markdown,再逐字显示 HTML
|
||||||
|
startTyping(fullText) {
|
||||||
|
const renderedText = this.md.render(fullText);
|
||||||
|
this.displayText = '';
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
if (this.typingTimer) {
|
||||||
|
clearInterval(this.typingTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.typingTimer = setInterval(() => {
|
||||||
|
if (index < renderedText.length) {
|
||||||
|
this.displayText += renderedText[index];
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
clearInterval(this.typingTimer);
|
||||||
|
this.typingTimer = null;
|
||||||
|
this.$nextTick(this.renderMermaid); // 渲染 Mermaid 图表
|
||||||
|
}
|
||||||
|
}, this.typingSpeed);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 触发 Mermaid 渲染
|
||||||
|
renderMermaid() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const mermaidEls = this.$el.querySelectorAll('.mermaid');
|
||||||
|
if (mermaidEls.length > 0) {
|
||||||
|
try {
|
||||||
|
// mermaid 8.x 版本使用 init 方法而不是 run
|
||||||
|
if (typeof mermaid.init === 'function') {
|
||||||
|
mermaid.init(undefined, '.mermaid');
|
||||||
|
} else if (mermaid.default && typeof mermaid.default.init === 'function') {
|
||||||
|
mermaid.default.init(undefined, '.mermaid');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Mermaid 渲染失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 切换案例引用显示数量
|
||||||
|
toggleShowAllCaseRefers() {
|
||||||
|
this.showAllCaseRefers = !this.showAllCaseRefers;
|
||||||
|
// 切换后重新渲染 Mermaid(如果内容中有图表)
|
||||||
|
this.$nextTick(this.renderMermaid);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.typingTimer) {
|
||||||
|
clearInterval(this.typingTimer);
|
||||||
|
this.typingTimer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
::v-deep .mermaid{
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
::v-deep svg[id^="mermaid-"]{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
.messages {
|
.messages {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
|
||||||
.bot-message {
|
.bot-message {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
@@ -192,33 +234,64 @@ export default {
|
|||||||
left: 0;
|
left: 0;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
transform: scaleX(0.5);
|
transform: scaleX(0.5);
|
||||||
margin-right: 5px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-content {
|
||||||
|
font-size: 12px !important;
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-message {
|
||||||
|
float: right;
|
||||||
|
padding: 8px 15px;
|
||||||
|
max-width: 80%;
|
||||||
|
background-color: #e4e7ed;
|
||||||
|
border-radius: 18px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== 案例引用样式 ========== */
|
||||||
.case-refers {
|
.case-refers {
|
||||||
margin-top: 10px;
|
margin-top: 12px;
|
||||||
|
|
||||||
.case-refers-title {
|
.case-refers-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
.icon-think {
|
.icon-think {
|
||||||
background-image: url("./map.svg") ;
|
background-image: url('./map.svg');
|
||||||
width: 15px;
|
width: 15px;
|
||||||
height: 13px;
|
height: 13px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.more {
|
.more {
|
||||||
font-size: 10px;
|
font-size: 12px;
|
||||||
padding: 2px 6px;
|
padding: 2px 8px;
|
||||||
background-color: #F4F7FD;
|
background-color: #f4f7fd;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
color:#577EE1;font-weight: unset;
|
color: #577ee1;
|
||||||
|
font-weight: normal;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,91 +299,120 @@ export default {
|
|||||||
.case-refers-list {
|
.case-refers-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
.case-refers-item {
|
.case-refers-item {
|
||||||
//margin-right: 10px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
border: 1px solid rgba(144, 147, 153, 0.44);
|
border: 1px solid rgba(144, 147, 153, 0.44);
|
||||||
padding: 5px;
|
padding: 8px;
|
||||||
border-radius: 5px;
|
border-radius: 6px;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
|
||||||
.case-refers-item-title {
|
.case-refers-item-title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 6px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #000;
|
color: #000;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
color: #1a73e8;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.case-refers-item-timer {
|
.case-refers-item-timer {
|
||||||
font-size: 10px;
|
font-size: 11px;
|
||||||
margin-right: 20px;
|
color: #aaa;
|
||||||
color:#cecece;
|
font-weight: normal;
|
||||||
font-weight: unset!important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.case-refers-item-author {
|
.case-refers-item-author {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #555;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
.user {
|
.user {
|
||||||
background-image: url("./user.svg");
|
background-image: url('./user.svg');
|
||||||
width: 15px;
|
width: 15px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
margin-right: 5px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.case-inter-orginInfo {
|
.case-inter-orginInfo {
|
||||||
font-size: 10px;
|
font-size: 11px;
|
||||||
color: rgba(144, 147, 153, 0.44);margin-left: 5px;
|
color: #999;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.case-refers-item-author,
|
|
||||||
.case-refers-item-keywords {
|
.case-refers-item-keywords {
|
||||||
|
margin-top: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
|
||||||
color: #000;
|
span {
|
||||||
}
|
padding: 2px 6px;
|
||||||
}
|
background-color: #f4f7fd;
|
||||||
}
|
border-radius: 5px;
|
||||||
}
|
font-size: 11px !important;
|
||||||
|
color: #577ee1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-message {
|
|
||||||
float: right;
|
|
||||||
padding: 5px 15px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: rgba(228, 231, 237, 1);
|
|
||||||
border-radius: 5px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.case-refers-item-keywords{
|
|
||||||
margin-top: 5px;
|
|
||||||
span{
|
|
||||||
padding: 1px 4px;
|
|
||||||
background-color: #F4F7FD;
|
|
||||||
border-radius: 5px;
|
|
||||||
font-size: 10px!important;
|
|
||||||
color:#577EE1
|
|
||||||
}
|
|
||||||
span + span {
|
span + span {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.message-content{
|
}
|
||||||
font-size: 12px!important;
|
}
|
||||||
margin-top: 5px;
|
}
|
||||||
|
|
||||||
|
/* ========== 推荐问题 ========== */
|
||||||
|
.suggestions {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.suggestions-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestions-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.suggestions-item {
|
||||||
|
padding: 6px 10px;
|
||||||
|
background-color: #f0f4fc;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: left;
|
||||||
|
color: #1a73e8;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #e1e8f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -57,6 +57,13 @@ module.exports = {
|
|||||||
// set svg-sprite-loader
|
// set svg-sprite-loader
|
||||||
config.plugins.delete('preload')
|
config.plugins.delete('preload')
|
||||||
config.plugins.delete('prefetch')
|
config.plugins.delete('prefetch')
|
||||||
|
// 添加对 mathxyjax3 的处理规则
|
||||||
|
config.module
|
||||||
|
.rule('mathxyjax3')
|
||||||
|
.test(/node_modules[\/\\]mathxyjax3[\/\\].*\.js$/)
|
||||||
|
.use('null-loader')
|
||||||
|
.loader('null-loader')
|
||||||
|
.end()
|
||||||
config.module
|
config.module
|
||||||
.rule('svg')
|
.rule('svg')
|
||||||
.exclude.add(resolve('src/icons'))
|
.exclude.add(resolve('src/icons'))
|
||||||
|
|||||||
Reference in New Issue
Block a user