页面右侧聊天助手的ai输出结果加上md文档格式显示
This commit is contained in:
@@ -13,12 +13,14 @@
|
||||
"axios": "^1.13.6",
|
||||
"element-plus": "^2.13.3",
|
||||
"html2pdf.js": "^0.14.0",
|
||||
"markdown-it": "^14.2.0",
|
||||
"sass": "^1.97.3",
|
||||
"vue": "^3.5.25",
|
||||
"vue-router": "^4.6.4",
|
||||
"vuex": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/node": "^24.10.1",
|
||||
"@vitejs/plugin-vue": "^6.0.2",
|
||||
"@vue/tsconfig": "^0.8.1",
|
||||
|
||||
Generated
+71
@@ -20,6 +20,9 @@ importers:
|
||||
html2pdf.js:
|
||||
specifier: ^0.14.0
|
||||
version: 0.14.0
|
||||
markdown-it:
|
||||
specifier: ^14.2.0
|
||||
version: 14.2.0
|
||||
sass:
|
||||
specifier: ^1.97.3
|
||||
version: 1.97.3
|
||||
@@ -33,6 +36,9 @@ importers:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0(vue@3.5.29(typescript@5.9.3))
|
||||
devDependencies:
|
||||
'@types/markdown-it':
|
||||
specifier: ^14.1.2
|
||||
version: 14.1.2
|
||||
'@types/node':
|
||||
specifier: ^24.10.1
|
||||
version: 24.11.0
|
||||
@@ -487,12 +493,21 @@ packages:
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/linkify-it@5.0.0':
|
||||
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
|
||||
|
||||
'@types/lodash-es@4.17.12':
|
||||
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
|
||||
|
||||
'@types/lodash@4.17.24':
|
||||
resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==}
|
||||
|
||||
'@types/markdown-it@14.1.2':
|
||||
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
|
||||
|
||||
'@types/mdurl@2.0.0':
|
||||
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
|
||||
|
||||
'@types/node@24.11.0':
|
||||
resolution: {integrity: sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==}
|
||||
|
||||
@@ -587,6 +602,9 @@ packages:
|
||||
alien-signals@3.1.2:
|
||||
resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==}
|
||||
|
||||
argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
async-validator@4.2.5:
|
||||
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
|
||||
|
||||
@@ -658,6 +676,10 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.3.0
|
||||
|
||||
entities@4.5.0:
|
||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
entities@7.0.1:
|
||||
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
|
||||
engines: {node: '>=0.12'}
|
||||
@@ -783,6 +805,9 @@ packages:
|
||||
jspdf@4.2.1:
|
||||
resolution: {integrity: sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==}
|
||||
|
||||
linkify-it@5.0.1:
|
||||
resolution: {integrity: sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==}
|
||||
|
||||
local-pkg@1.1.2:
|
||||
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -803,10 +828,17 @@ packages:
|
||||
magic-string@0.30.21:
|
||||
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||
|
||||
markdown-it@14.2.0:
|
||||
resolution: {integrity: sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==}
|
||||
hasBin: true
|
||||
|
||||
math-intrinsics@1.1.0:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
mdurl@2.0.0:
|
||||
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
|
||||
|
||||
memoize-one@6.0.0:
|
||||
resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
|
||||
|
||||
@@ -870,6 +902,10 @@ packages:
|
||||
proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
|
||||
punycode.js@2.3.1:
|
||||
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
quansync@0.2.11:
|
||||
resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
|
||||
|
||||
@@ -931,6 +967,9 @@ packages:
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
uc.micro@2.1.0:
|
||||
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
|
||||
|
||||
ufo@1.6.3:
|
||||
resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==}
|
||||
|
||||
@@ -1328,12 +1367,21 @@ snapshots:
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/linkify-it@5.0.0': {}
|
||||
|
||||
'@types/lodash-es@4.17.12':
|
||||
dependencies:
|
||||
'@types/lodash': 4.17.24
|
||||
|
||||
'@types/lodash@4.17.24': {}
|
||||
|
||||
'@types/markdown-it@14.1.2':
|
||||
dependencies:
|
||||
'@types/linkify-it': 5.0.0
|
||||
'@types/mdurl': 2.0.0
|
||||
|
||||
'@types/mdurl@2.0.0': {}
|
||||
|
||||
'@types/node@24.11.0':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
@@ -1460,6 +1508,8 @@ snapshots:
|
||||
|
||||
alien-signals@3.1.2: {}
|
||||
|
||||
argparse@2.0.1: {}
|
||||
|
||||
async-validator@4.2.5: {}
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
@@ -1553,6 +1603,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- '@vue/composition-api'
|
||||
|
||||
entities@4.5.0: {}
|
||||
|
||||
entities@7.0.1: {}
|
||||
|
||||
es-define-property@1.0.1: {}
|
||||
@@ -1702,6 +1754,10 @@ snapshots:
|
||||
dompurify: 3.3.3
|
||||
html2canvas: 1.4.1
|
||||
|
||||
linkify-it@5.0.1:
|
||||
dependencies:
|
||||
uc.micro: 2.1.0
|
||||
|
||||
local-pkg@1.1.2:
|
||||
dependencies:
|
||||
mlly: 1.8.0
|
||||
@@ -1722,8 +1778,19 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
markdown-it@14.2.0:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
entities: 4.5.0
|
||||
linkify-it: 5.0.1
|
||||
mdurl: 2.0.0
|
||||
punycode.js: 2.3.1
|
||||
uc.micro: 2.1.0
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
mdurl@2.0.0: {}
|
||||
|
||||
memoize-one@6.0.0: {}
|
||||
|
||||
mime-db@1.52.0: {}
|
||||
@@ -1783,6 +1850,8 @@ snapshots:
|
||||
|
||||
proxy-from-env@1.1.0: {}
|
||||
|
||||
punycode.js@2.3.1: {}
|
||||
|
||||
quansync@0.2.11: {}
|
||||
|
||||
raf@3.4.1:
|
||||
@@ -1864,6 +1933,8 @@ snapshots:
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
uc.micro@2.1.0: {}
|
||||
|
||||
ufo@1.6.3: {}
|
||||
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
@@ -94,6 +94,90 @@
|
||||
font-size: 0.13rem;
|
||||
line-height: 1.6;
|
||||
max-width: 85%;
|
||||
|
||||
// ===== Markdown 渲染样式 =====
|
||||
p {
|
||||
margin: 0 0 0.08rem;
|
||||
&:last-child { margin-bottom: 0; }
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 0.12rem 0 0.06rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
h1 { font-size: 0.18rem; }
|
||||
h2 { font-size: 0.16rem; }
|
||||
h3 { font-size: 0.14rem; }
|
||||
|
||||
ul, ol {
|
||||
padding-left: 0.2rem;
|
||||
margin: 0.06rem 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.04rem;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #f1f5f9;
|
||||
padding: 0.01rem 0.04rem;
|
||||
border-radius: 0.03rem;
|
||||
font-size: 0.12rem;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #1e293b;
|
||||
color: #e2e8f0;
|
||||
padding: 0.1rem 0.12rem;
|
||||
border-radius: 0.06rem;
|
||||
overflow-x: auto;
|
||||
margin: 0.08rem 0;
|
||||
|
||||
code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
font-size: 0.11rem;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 3px solid #cbd5e1;
|
||||
padding-left: 0.1rem;
|
||||
margin: 0.08rem 0;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #2563eb;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin: 0.08rem 0;
|
||||
width: 100%;
|
||||
font-size: 0.12rem;
|
||||
|
||||
th, td {
|
||||
border: 1px solid #e5e7eb;
|
||||
padding: 0.04rem 0.08rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #f8fafc;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
margin: 0.1rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__msg--ai &__msg-bubble {
|
||||
|
||||
@@ -74,12 +74,22 @@
|
||||
import { ref, computed, watch, nextTick, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import markdownit from 'markdown-it'
|
||||
import MemberDialog from '@/components/MemberDialog.vue'
|
||||
import AiThinkingIndicator from '@/components/tools/AiThinkingIndicator.vue'
|
||||
import { sendNovaChat } from '@/utils/aiRequest'
|
||||
import type { NovaChatHistoryItem } from '@/utils/aiRequest'
|
||||
import { fetchResumeList } from '@/api/resume'
|
||||
|
||||
// ==================== Markdown 渲染实例 ====================
|
||||
|
||||
/** markdown-it 实例,用于将 AI 回复的 Markdown 文本渲染为 HTML */
|
||||
const md = markdownit({
|
||||
html: false, // 禁止原始 HTML(防 XSS)
|
||||
breaks: true, // 将换行符转为 <br>
|
||||
linkify: true, // 自动识别链接
|
||||
})
|
||||
|
||||
// ==================== Props ====================
|
||||
|
||||
/** 组件属性 */
|
||||
@@ -180,9 +190,9 @@ const userQuestions = computed(() => quickQuestions.value)
|
||||
|
||||
// ==================== 内容格式化 ====================
|
||||
|
||||
/** 将消息中的换行符转为 HTML 换行标签 */
|
||||
/** 将消息内容通过 markdown-it 渲染为 HTML */
|
||||
function formatContent(content: string): string {
|
||||
return content.replace(/\n/g, '<br>')
|
||||
return md.render(content)
|
||||
}
|
||||
|
||||
// ==================== 滚动控制 ====================
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
"strict": true,
|
||||
|
||||
Reference in New Issue
Block a user