添加了通用问答和历史回答的pdf导出功能,能导出对话,并保存为pdf形式
This commit is contained in:
parent
dd1fdd16ec
commit
2d4eeab6a2
|
|
@ -30,6 +30,7 @@
|
|||
"element-plus": "^2.3.8",
|
||||
"file-saver": "^2.0.5",
|
||||
"highlight.js": "^11.11.1",
|
||||
"html2pdf.js": "^0.12.1",
|
||||
"image-conversion": "^2.1.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"js-message": "^2.1.0",
|
||||
|
|
@ -3752,6 +3753,11 @@
|
|||
"integrity": "sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/pako": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
|
||||
"integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw=="
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||
|
|
@ -3769,6 +3775,12 @@
|
|||
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/raf": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
|
||||
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@types/range-parser": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmmirror.com/@types/range-parser/-/range-parser-1.2.7.tgz",
|
||||
|
|
@ -6391,6 +6403,14 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-arraybuffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
||||
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
|
||||
|
|
@ -7450,6 +7470,25 @@
|
|||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/canvg": {
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz",
|
||||
"integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@types/raf": "^3.4.0",
|
||||
"core-js": "^3.8.3",
|
||||
"raf": "^3.4.1",
|
||||
"regenerator-runtime": "^0.13.7",
|
||||
"rgbcolor": "^1.0.1",
|
||||
"stackblur-canvas": "^2.0.0",
|
||||
"svg-pathdata": "^6.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/capital-case": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/capital-case/-/capital-case-1.0.4.tgz",
|
||||
|
|
@ -8419,6 +8458,14 @@
|
|||
"node": ">=12 || >=16"
|
||||
}
|
||||
},
|
||||
"node_modules/css-line-break": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
|
||||
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
|
||||
"dependencies": {
|
||||
"utrie": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/css-loader": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmmirror.com/css-loader/-/css-loader-6.11.0.tgz",
|
||||
|
|
@ -11280,6 +11327,21 @@
|
|||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-png": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz",
|
||||
"integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
|
||||
"dependencies": {
|
||||
"@types/pako": "^2.0.3",
|
||||
"iobuffer": "^5.3.2",
|
||||
"pako": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-png/node_modules/pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
|
||||
},
|
||||
"node_modules/fast-uri": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.0.6.tgz",
|
||||
|
|
@ -11363,6 +11425,11 @@
|
|||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fflate": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
|
||||
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
|
||||
},
|
||||
"node_modules/figures": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/figures/-/figures-3.2.0.tgz",
|
||||
|
|
@ -12965,6 +13032,27 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/html2canvas": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
||||
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
|
||||
"dependencies": {
|
||||
"css-line-break": "^2.1.0",
|
||||
"text-segmentation": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html2pdf.js": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/html2pdf.js/-/html2pdf.js-0.12.1.tgz",
|
||||
"integrity": "sha512-3rBWQ96H5oOU9jtoz3MnE/epGi27ig9h8aonBk4JTpvUERM3lMRxhIRckhJZEi4wE0YfRINoYOIDY0hLY0CHgQ==",
|
||||
"dependencies": {
|
||||
"html2canvas": "^1.0.0",
|
||||
"jspdf": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
|
|
@ -13715,6 +13803,11 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/iobuffer": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
|
||||
"integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA=="
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
||||
|
|
@ -15661,6 +15754,22 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jspdf": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.3.tgz",
|
||||
"integrity": "sha512-eURjAyz5iX1H8BOYAfzvdPfIKK53V7mCpBTe7Kb16PaM8JSXEcUQNBQaiWMI8wY5RvNOPj4GccMjTlfwRBd+oQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.9",
|
||||
"fast-png": "^6.2.0",
|
||||
"fflate": "^0.8.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"canvg": "^3.0.11",
|
||||
"core-js": "^3.6.0",
|
||||
"dompurify": "^3.2.4",
|
||||
"html2canvas": "^1.0.0-rc.5"
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
|
|
@ -18641,6 +18750,12 @@
|
|||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
|
||||
|
|
@ -20408,6 +20523,15 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
|
||||
|
|
@ -20735,6 +20859,12 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/regex-not": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/regex-not/-/regex-not-1.0.2.tgz",
|
||||
|
|
@ -21139,6 +21269,15 @@
|
|||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/rgbcolor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
|
||||
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8.15"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
|
||||
|
|
@ -22461,6 +22600,15 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/stackblur-canvas": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
|
||||
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.1.14"
|
||||
}
|
||||
},
|
||||
"node_modules/stackframe": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz",
|
||||
|
|
@ -23564,6 +23712,15 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svg-pathdata": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
|
||||
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svg-sprite-loader": {
|
||||
"version": "6.0.11",
|
||||
"resolved": "https://registry.npmmirror.com/svg-sprite-loader/-/svg-sprite-loader-6.0.11.tgz",
|
||||
|
|
@ -24023,6 +24180,14 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/text-segmentation": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
|
||||
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
|
||||
"dependencies": {
|
||||
"utrie": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz",
|
||||
|
|
@ -25294,6 +25459,14 @@
|
|||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utrie": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
|
||||
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
|
||||
"dependencies": {
|
||||
"base64-arraybuffer": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz",
|
||||
|
|
@ -29618,6 +29791,11 @@
|
|||
"integrity": "sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/pako": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
|
||||
"integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||
|
|
@ -29635,6 +29813,12 @@
|
|||
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/raf": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
|
||||
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
|
||||
"optional": true
|
||||
},
|
||||
"@types/range-parser": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmmirror.com/@types/range-parser/-/range-parser-1.2.7.tgz",
|
||||
|
|
@ -31566,6 +31750,11 @@
|
|||
"pascalcase": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"base64-arraybuffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
||||
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
|
||||
|
|
@ -32391,6 +32580,22 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"canvg": {
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz",
|
||||
"integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@types/raf": "^3.4.0",
|
||||
"core-js": "^3.8.3",
|
||||
"raf": "^3.4.1",
|
||||
"regenerator-runtime": "^0.13.7",
|
||||
"rgbcolor": "^1.0.1",
|
||||
"stackblur-canvas": "^2.0.0",
|
||||
"svg-pathdata": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"capital-case": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/capital-case/-/capital-case-1.0.4.tgz",
|
||||
|
|
@ -33122,6 +33327,14 @@
|
|||
"integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==",
|
||||
"dev": true
|
||||
},
|
||||
"css-line-break": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
|
||||
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
|
||||
"requires": {
|
||||
"utrie": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"css-loader": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmmirror.com/css-loader/-/css-loader-6.11.0.tgz",
|
||||
|
|
@ -35305,6 +35518,23 @@
|
|||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-png": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz",
|
||||
"integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
|
||||
"requires": {
|
||||
"@types/pako": "^2.0.3",
|
||||
"iobuffer": "^5.3.2",
|
||||
"pako": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"fast-uri": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.0.6.tgz",
|
||||
|
|
@ -35363,6 +35593,11 @@
|
|||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"fflate": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
|
||||
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
|
||||
},
|
||||
"figures": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/figures/-/figures-3.2.0.tgz",
|
||||
|
|
@ -36545,6 +36780,24 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"html2canvas": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
||||
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
|
||||
"requires": {
|
||||
"css-line-break": "^2.1.0",
|
||||
"text-segmentation": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"html2pdf.js": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/html2pdf.js/-/html2pdf.js-0.12.1.tgz",
|
||||
"integrity": "sha512-3rBWQ96H5oOU9jtoz3MnE/epGi27ig9h8aonBk4JTpvUERM3lMRxhIRckhJZEi4wE0YfRINoYOIDY0hLY0CHgQ==",
|
||||
"requires": {
|
||||
"html2canvas": "^1.0.0",
|
||||
"jspdf": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
|
|
@ -37106,6 +37359,11 @@
|
|||
"p-is-promise": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"iobuffer": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
|
||||
"integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA=="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
||||
|
|
@ -38517,6 +38775,20 @@
|
|||
"integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
|
||||
"dev": true
|
||||
},
|
||||
"jspdf": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.3.tgz",
|
||||
"integrity": "sha512-eURjAyz5iX1H8BOYAfzvdPfIKK53V7mCpBTe7Kb16PaM8JSXEcUQNBQaiWMI8wY5RvNOPj4GccMjTlfwRBd+oQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.26.9",
|
||||
"canvg": "^3.0.11",
|
||||
"core-js": "^3.6.0",
|
||||
"dompurify": "^3.2.4",
|
||||
"fast-png": "^6.2.0",
|
||||
"fflate": "^0.8.1",
|
||||
"html2canvas": "^1.0.0-rc.5"
|
||||
}
|
||||
},
|
||||
"jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
|
|
@ -40791,6 +41063,12 @@
|
|||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"optional": true
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
|
||||
|
|
@ -42005,6 +42283,15 @@
|
|||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||
"dev": true
|
||||
},
|
||||
"raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
|
||||
|
|
@ -42253,6 +42540,12 @@
|
|||
"regenerate": "^1.4.2"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
||||
"optional": true
|
||||
},
|
||||
"regex-not": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/regex-not/-/regex-not-1.0.2.tgz",
|
||||
|
|
@ -42554,6 +42847,12 @@
|
|||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
||||
"dev": true
|
||||
},
|
||||
"rgbcolor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
|
||||
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
|
||||
"optional": true
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
|
||||
|
|
@ -43553,6 +43852,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"stackblur-canvas": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
|
||||
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
|
||||
"optional": true
|
||||
},
|
||||
"stackframe": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz",
|
||||
|
|
@ -44373,6 +44678,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"svg-pathdata": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
|
||||
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
|
||||
"optional": true
|
||||
},
|
||||
"svg-sprite-loader": {
|
||||
"version": "6.0.11",
|
||||
"resolved": "https://registry.npmmirror.com/svg-sprite-loader/-/svg-sprite-loader-6.0.11.tgz",
|
||||
|
|
@ -44713,6 +45024,14 @@
|
|||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"text-segmentation": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
|
||||
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
|
||||
"requires": {
|
||||
"utrie": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz",
|
||||
|
|
@ -45672,6 +45991,14 @@
|
|||
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
|
||||
"dev": true
|
||||
},
|
||||
"utrie": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
|
||||
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
|
||||
"requires": {
|
||||
"base64-arraybuffer": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz",
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
"element-plus": "^2.3.8",
|
||||
"file-saver": "^2.0.5",
|
||||
"highlight.js": "^11.11.1",
|
||||
"html2pdf.js": "^0.12.1",
|
||||
"image-conversion": "^2.1.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"js-message": "^2.1.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
// src/utils/exportPdf.ts
|
||||
import html2pdf from 'html2pdf.js'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
/**
|
||||
* html2pdf 配置类型定义
|
||||
*/
|
||||
export type Html2PdfOptions = {
|
||||
margin?: number
|
||||
filename?: string
|
||||
image?: { type?: 'jpeg' | 'png'; quality?: number }
|
||||
html2canvas?: { scale?: number; scrollY?: number; useCORS?: boolean; windowWidth?: number }
|
||||
jsPDF?: {
|
||||
unit?: string
|
||||
format?: 'a3' | 'a4' | 'a5' | 'letter' | 'legal' | [number, number]
|
||||
orientation?: 'portrait' | 'landscape'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出指定 DOM 元素为 PDF(支持完整滚动内容)
|
||||
* @param element 要导出的 DOM 元素
|
||||
* @param fileName 导出文件名(默认:export.pdf)
|
||||
*/
|
||||
export async function exportElementToPdf(
|
||||
element: HTMLElement,
|
||||
fileName = 'export.pdf'
|
||||
): Promise<void> {
|
||||
if (!element) {
|
||||
console.error('❌ exportElementToPdf: 未传入有效的 DOM 元素')
|
||||
return
|
||||
}
|
||||
|
||||
// 等待 DOM 渲染完成
|
||||
await nextTick()
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
|
||||
// 获取元素尺寸
|
||||
const elementWidth = element.scrollWidth
|
||||
const elementHeight = element.scrollHeight
|
||||
|
||||
// html2pdf 配置
|
||||
const opt: Html2PdfOptions = {
|
||||
margin: 10, // 页面边距,单位 px
|
||||
filename: fileName,
|
||||
image: { type: 'jpeg', quality: 0.98 },
|
||||
html2canvas: {
|
||||
scale: 2,
|
||||
scrollY: -window.scrollY,
|
||||
useCORS: true,
|
||||
windowWidth: elementWidth,
|
||||
},
|
||||
jsPDF: {
|
||||
unit: 'pt', // 使用 pt 单位更适合像素换算
|
||||
format: [elementWidth, elementHeight],
|
||||
orientation: 'portrait',
|
||||
},
|
||||
}
|
||||
|
||||
console.log('📄 正在导出 PDF...')
|
||||
try {
|
||||
await html2pdf().set(opt).from(element).save()
|
||||
console.log(`✅ PDF 导出成功:${fileName}`)
|
||||
} catch (err) {
|
||||
console.error('❌ PDF 导出失败:', err)
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
<!-- 聊天消息区域 -->
|
||||
<div class="chat-messages" ref="messagesContainer">
|
||||
<MessageItem
|
||||
v-for="(msg, index) in messages"
|
||||
v-for="(msg, index) in messages"
|
||||
:key="index"
|
||||
:message="msg"
|
||||
:index="index"
|
||||
|
|
@ -304,16 +304,16 @@ const handleCreateNewChat = async () => {
|
|||
if (messages.value.length > 0) {
|
||||
setCurrentMessages(messages.value)
|
||||
}
|
||||
|
||||
|
||||
// 创建新会话初始消息
|
||||
const initialMessages = [...props.initialMessages]
|
||||
|
||||
|
||||
const newChatIndex = await createNewChat(initialMessages)
|
||||
messages.value = initialMessages
|
||||
|
||||
|
||||
// 发射会话创建事件
|
||||
emit('chatCreated', newChatIndex)
|
||||
|
||||
|
||||
// 滚动到底部显示新消息
|
||||
await nextTick()
|
||||
throttledScrollToBottom()
|
||||
|
|
@ -322,21 +322,21 @@ const handleCreateNewChat = async () => {
|
|||
// 切换会话
|
||||
const handleSwitchChat = async (index: number) => {
|
||||
if (index === currentChatIndex.value) return
|
||||
|
||||
|
||||
// 保存当前会话消息
|
||||
if (messages.value.length > 0) {
|
||||
setCurrentMessages(messages.value)
|
||||
}
|
||||
|
||||
|
||||
const newIndex = switchChat(index)
|
||||
|
||||
|
||||
// 短暂延迟以确保动画流畅
|
||||
await nextTick()
|
||||
messages.value = [...getCurrentMessages()]
|
||||
|
||||
|
||||
// 发射会话切换事件
|
||||
emit('chatSwitched', newIndex)
|
||||
|
||||
|
||||
// 滚动到底部
|
||||
await nextTick()
|
||||
throttledScrollToBottom()
|
||||
|
|
@ -345,12 +345,12 @@ const handleSwitchChat = async (index: number) => {
|
|||
// 发送消息
|
||||
const handleSendMessage = async (messageText: string) => {
|
||||
if (!messageText.trim() || isLoading.value) return
|
||||
|
||||
|
||||
inputMessage.value = '' // 清空输入框
|
||||
|
||||
|
||||
const currentSession = getCurrentSession()
|
||||
const conversationId = currentSession?.conversationId
|
||||
|
||||
|
||||
const result = await sendMessageCore(
|
||||
messageText,
|
||||
messages.value,
|
||||
|
|
@ -371,7 +371,7 @@ const handleSendMessage = async (messageText: string) => {
|
|||
streamingScrollToBottom()
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
// 保存消息到当前会话
|
||||
setCurrentMessages(messages.value)
|
||||
scrollToBottomForce()
|
||||
|
|
@ -380,7 +380,7 @@ const handleSendMessage = async (messageText: string) => {
|
|||
// 中止流式回答
|
||||
const handleStopStream = async () => {
|
||||
await stopStream(props.chatType, props.userId)
|
||||
|
||||
|
||||
// 移除当前消息的加载状态
|
||||
if (messages.value.length > 0) {
|
||||
const lastMessage = messages.value[messages.value.length - 1]
|
||||
|
|
@ -396,18 +396,18 @@ const handleStopStream = async () => {
|
|||
// 重新生成回答
|
||||
const handleRegenerateMessage = async (index: number) => {
|
||||
if (index === 0) return
|
||||
|
||||
|
||||
// 获取前一条用户消息
|
||||
const userMessage = messages.value[index - 1]
|
||||
if (!userMessage || !userMessage.isUser) return
|
||||
|
||||
|
||||
// 删除当前助手消息及之后的消息
|
||||
messages.value = messages.value.slice(0, index)
|
||||
|
||||
|
||||
// 重新生成回答
|
||||
const currentSession = getCurrentSession()
|
||||
const conversationId = currentSession?.conversationId
|
||||
|
||||
|
||||
await sendMessageCore(
|
||||
userMessage.text,
|
||||
messages.value,
|
||||
|
|
@ -427,7 +427,7 @@ const handleRegenerateMessage = async (index: number) => {
|
|||
streamingScrollToBottom()
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
setCurrentMessages(messages.value)
|
||||
scrollToBottomForce()
|
||||
}
|
||||
|
|
@ -435,11 +435,11 @@ const handleRegenerateMessage = async (index: number) => {
|
|||
// 保存编辑
|
||||
const handleSaveEdit = async (newText: string) => {
|
||||
if (!newText.trim()) return
|
||||
|
||||
|
||||
// 重置编辑状态
|
||||
editingMessageIndex.value = -1
|
||||
editingMessageText.value = ''
|
||||
|
||||
|
||||
// 将编辑后的文本作为新的用户问题发送
|
||||
await handleSendMessage(newText)
|
||||
}
|
||||
|
|
@ -455,13 +455,13 @@ const handleSourceClick = async (source: TraceFile, conversationId?: string, mes
|
|||
// 构造完整的PDF预览URL
|
||||
const baseUrl = window.location.protocol + '//' + window.location.host
|
||||
const previewFileUrl = baseUrl + source.filePath
|
||||
|
||||
|
||||
console.log('预览文件:', source)
|
||||
console.log('预览URL:', previewFileUrl)
|
||||
|
||||
|
||||
// 调用文件预览模态框
|
||||
filePreviewModals.value?.showPdfPreview(previewFileUrl)
|
||||
|
||||
|
||||
// 发射文件来源点击事件,让父组件处理
|
||||
emit('sourceClick', source)
|
||||
} catch (error) {
|
||||
|
|
@ -475,7 +475,7 @@ const handleContextFileClick = async (fileContext: TraceContext, fileType: 'exce
|
|||
try {
|
||||
// 将 \n 字符串转换为真正的换行符
|
||||
const processedContent = fileContext.context.replace(/\\n/g, '\n')
|
||||
|
||||
|
||||
if (fileType === 'excel') {
|
||||
// 如果marked转换失败,尝试手动解析markdown表格
|
||||
let htmlContent = ''
|
||||
|
|
@ -486,15 +486,15 @@ const handleContextFileClick = async (fileContext: TraceContext, fileType: 'exce
|
|||
console.warn('marked解析失败,尝试手动解析:', error)
|
||||
htmlContent = parseMarkdownTable(processedContent)
|
||||
}
|
||||
|
||||
|
||||
// 如果HTML中没有table标签,尝试手动解析
|
||||
if (!htmlContent.includes('<table')) {
|
||||
console.warn('未检测到表格,手动解析markdown')
|
||||
htmlContent = parseMarkdownTable(processedContent)
|
||||
}
|
||||
|
||||
|
||||
filePreviewModals.value?.showExcelPreview(htmlContent)
|
||||
|
||||
|
||||
} else if (fileType === 'markdown' || fileType === 'word') {
|
||||
// Markdown和Word文件都使用markdown预览
|
||||
let htmlContent = ''
|
||||
|
|
@ -506,10 +506,10 @@ const handleContextFileClick = async (fileContext: TraceContext, fileType: 'exce
|
|||
// 如果解析失败,使用简单的换行处理
|
||||
htmlContent = `<pre style="white-space: pre-wrap; font-family: inherit;">${processedContent}</pre>`
|
||||
}
|
||||
|
||||
|
||||
filePreviewModals.value?.showMarkdownPreview(htmlContent, fileContext.fileName)
|
||||
}
|
||||
|
||||
|
||||
console.log(`预览${fileType}文件:`, fileContext.fileName)
|
||||
console.log('文件内容:', fileContext.context)
|
||||
} catch (error) {
|
||||
|
|
@ -521,7 +521,7 @@ const handleContextFileClick = async (fileContext: TraceContext, fileType: 'exce
|
|||
// 处理推荐问题点击事件
|
||||
const handleRecommendQuestionClick = (question: string) => {
|
||||
if (!question.trim() || isLoading.value) return
|
||||
|
||||
|
||||
// 发送问题
|
||||
handleSendMessage(question)
|
||||
}
|
||||
|
|
@ -530,6 +530,11 @@ const handleRecommendQuestionClick = (question: string) => {
|
|||
const getAssistantAvatar = () => {
|
||||
return props.assistantAvatar || new URL('@/assets/assistant.png', import.meta.url).href
|
||||
}
|
||||
const messagesQuantity = computed(() => messages.value.length)
|
||||
defineExpose({
|
||||
messagesContainer,
|
||||
messagesQuantity
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
@ -571,7 +576,7 @@ const getAssistantAvatar = () => {
|
|||
background: #ffffff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
|
|
@ -601,14 +606,14 @@ const getAssistantAvatar = () => {
|
|||
padding: 40px 20px;
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #e8eef5 100%);
|
||||
overflow-y: auto;
|
||||
|
||||
|
||||
.logo-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.title-section {
|
||||
margin-bottom: 30px;
|
||||
|
||||
|
||||
.main-title {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
|
|
@ -619,7 +624,7 @@ const getAssistantAvatar = () => {
|
|||
max-width: 800px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.quick-questions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
|
|
@ -627,7 +632,7 @@ const getAssistantAvatar = () => {
|
|||
max-width: 900px;
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
|
||||
|
||||
.question-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #e5e7eb;
|
||||
|
|
@ -638,13 +643,13 @@ const getAssistantAvatar = () => {
|
|||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
|
||||
|
||||
&:hover {
|
||||
border-color: #6366f1;
|
||||
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
|
||||
.question-icon {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
|
|
@ -657,7 +662,7 @@ const getAssistantAvatar = () => {
|
|||
color: #6366f1;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
|
||||
.question-text {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
|
|
@ -671,13 +676,13 @@ const getAssistantAvatar = () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.centered-input-wrapper {
|
||||
width: 100%;
|
||||
max-width: 900px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.footer-text {
|
||||
font-size: 13px;
|
||||
color: #9ca3af;
|
||||
|
|
@ -696,7 +701,7 @@ const getAssistantAvatar = () => {
|
|||
flex-direction: column;
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #e8eef5 100%);
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
.chat-messages {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
|
|
@ -705,7 +710,7 @@ const getAssistantAvatar = () => {
|
|||
scroll-behavior: smooth;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.fixed-input-section {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
|
@ -718,11 +723,11 @@ const getAssistantAvatar = () => {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
|
||||
> * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
|
||||
:deep(.centered-input-wrapper) {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
@ -809,58 +814,58 @@ const getAssistantAvatar = () => {
|
|||
.chat-main {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
|
||||
.sidebar-toggle-btn {
|
||||
top: 12px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
|
||||
.empty-state-container {
|
||||
padding: 20px 16px;
|
||||
|
||||
|
||||
.logo-section {
|
||||
margin-bottom: 16px;
|
||||
|
||||
|
||||
:deep(.el-icon) {
|
||||
font-size: 40px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.title-section {
|
||||
margin-bottom: 24px;
|
||||
|
||||
|
||||
.main-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.quick-questions {
|
||||
grid-template-columns: 1fr;
|
||||
margin-bottom: 24px;
|
||||
|
||||
|
||||
.question-card {
|
||||
padding: 14px 16px;
|
||||
|
||||
|
||||
.question-text {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.centered-input-wrapper {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.chat-content {
|
||||
.chat-messages {
|
||||
padding: 1rem 0.5rem;
|
||||
padding-bottom: 200px;
|
||||
}
|
||||
|
||||
|
||||
.fixed-input-section {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,11 +6,12 @@
|
|||
<div class="conversation-meta">
|
||||
<span class="message-count"> {{ $t('vabI18n.HistoryRecords.HistoryDetails.count') }} {{ messages.length }} {{ $t('vabI18n.HistoryRecords.HistoryDetails.messageCount') }}</span>
|
||||
<el-button class="export-btn" type="primary" size="small" icon="Download" @click="handleExportMarkdown">{{ $t('vabI18n.HistoryRecords.HistoryDetails.exportMarkdown') }}</el-button>
|
||||
<el-button class="export-btn" type="primary" size="small" icon="Download" @click="handleExportPdf">导出为pdf</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 时间线对话 -->
|
||||
<div class="timeline-container">
|
||||
<div class="timeline-container" ref="timelineContainer">
|
||||
<div v-for="(message, index) in messages" :key="message.messageId" class="timeline-item">
|
||||
<!-- 时间标签 -->
|
||||
<div class="timeline-time">
|
||||
|
|
@ -67,6 +68,8 @@
|
|||
import { marked } from 'marked'
|
||||
import { convertEchartsMarkdown } from '@/api/echart'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import html2pdf from 'html2pdf.js'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'HistoryDetails',
|
||||
props: {
|
||||
|
|
@ -147,6 +150,67 @@
|
|||
state.showThinking[index] = !state.showThinking[index]
|
||||
}
|
||||
|
||||
// DOM元素引用
|
||||
const timelineContainer = ref<HTMLElement | null>(null)
|
||||
|
||||
// 声明 html2pdf 选项类型
|
||||
type Html2PdfOptions = {
|
||||
margin?: number
|
||||
filename?: string
|
||||
image?: { type?: 'jpeg' | 'png'; quality?: number }
|
||||
html2canvas?: { scale?: number; scrollY?: number; windowWidth?: number }
|
||||
jsPDF?: {
|
||||
unit?: string;
|
||||
format?: 'a3' | 'a4' | 'a5' | 'letter' | 'legal' | [number, number];
|
||||
orientation?: 'portrait' | 'landscape'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const handleExportPdf = async () => {
|
||||
if (!timelineContainer.value) return
|
||||
|
||||
// 保存原始样式
|
||||
const originalMaxHeight = timelineContainer.value.style.maxHeight
|
||||
const originalOverflow = timelineContainer.value.style.overflow
|
||||
|
||||
// 展开所有内容
|
||||
timelineContainer.value.style.maxHeight = 'none'
|
||||
timelineContainer.value.style.overflow = 'visible'
|
||||
Object.keys(state.showThinking).forEach(k => state.showThinking[k] = true)
|
||||
|
||||
await nextTick()
|
||||
await new Promise(resolve => setTimeout(resolve, 50)) // 等待渲染
|
||||
|
||||
const elementHeight = timelineContainer.value.scrollHeight
|
||||
const elementWidth = timelineContainer.value.scrollWidth
|
||||
|
||||
const opt : Html2PdfOptions = {
|
||||
margin: 0.3,
|
||||
filename: `${props.conversationName}.pdf`,
|
||||
image: { type: 'jpeg', quality: 0.98 },
|
||||
html2canvas: { scale: 2, scrollY: -window.scrollY, windowWidth: elementWidth },
|
||||
jsPDF: {
|
||||
unit: 'in',
|
||||
format: [elementWidth / 90, elementHeight / 90] as [number, number],
|
||||
orientation: 'portrait'
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await html2pdf().set(opt).from(timelineContainer.value).save()
|
||||
} catch (err) {
|
||||
console.error('PDF 导出失败:', err)
|
||||
} finally {
|
||||
// 恢复原样式
|
||||
timelineContainer.value.style.maxHeight = originalMaxHeight
|
||||
timelineContainer.value.style.overflow = originalOverflow
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//导出为markdown格式
|
||||
const handleExportMarkdown = async () => {
|
||||
// 原始 markdown 内容
|
||||
|
|
@ -182,6 +246,7 @@
|
|||
|
||||
return {
|
||||
...toRefs(state),
|
||||
timelineContainer,
|
||||
t,
|
||||
locale,
|
||||
conversationName: computed(() => props.conversationName),
|
||||
|
|
@ -191,6 +256,7 @@
|
|||
formatAnswer,
|
||||
toggleThinking,
|
||||
handleExportMarkdown,
|
||||
handleExportPdf,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
@ -218,6 +284,7 @@
|
|||
link.click()
|
||||
setTimeout(() => URL.revokeObjectURL(link.href), 10000)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
Loading…
Reference in New Issue