Compare commits
2 Commits
8b78ad2b6d
...
b171f47545
Author | SHA1 | Date |
---|---|---|
|
b171f47545 | |
|
98b10455d1 |
|
@ -5,7 +5,7 @@
|
|||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="preload" as="image" href="/src/assets/images/hero-bg.jpg" fetchpriority="high">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Vue + TS</title>
|
||||
<title>优阅工作室</title>
|
||||
|
||||
|
||||
</head>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"name": "company_website",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@tdesign-vue-next/chat": "^0.4.5",
|
||||
"@types/node": "^24.2.1",
|
||||
"@vue/language-core": "^3.0.5",
|
||||
"axios": "^1.11.0",
|
||||
|
@ -20,6 +21,8 @@
|
|||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"less": "^4.4.1",
|
||||
"less-loader": "^12.3.0",
|
||||
"typescript": "~5.8.3",
|
||||
"vite": "^7.1.2",
|
||||
"vue-tsc": "^3.0.5"
|
||||
|
@ -815,6 +818,25 @@
|
|||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@tdesign-vue-next/chat": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmmirror.com/@tdesign-vue-next/chat/-/chat-0.4.5.tgz",
|
||||
"integrity": "sha512-oM+NaVS2+QAC3tvlKCIm92dYvJVTzjPZip48WicCoWK42XyjKDau+hJiEb8TRXTMOw3kAkK7zrO79N0tWmBQnQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.22.6",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"clipboard": "^2.0.11",
|
||||
"highlight.js": "^11.9.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"marked": "^12.0.1",
|
||||
"marked-highlight": "^2.1.1",
|
||||
"tdesign-icons-vue-next": "^0.3.6",
|
||||
"tdesign-vue-next": "^1.15.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">=3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
|
||||
|
@ -1108,6 +1130,16 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/clipboard": {
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
|
||||
"integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
|
||||
"dependencies": {
|
||||
"good-listener": "^1.2.2",
|
||||
"select": "^1.1.2",
|
||||
"tiny-emitter": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
|
@ -1156,6 +1188,11 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delegate": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
|
||||
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
|
@ -1180,6 +1217,19 @@
|
|||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/errno": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz",
|
||||
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"prr": "~1.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"errno": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
|
@ -1375,6 +1425,14 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/good-listener": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
|
||||
"integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
|
||||
"dependencies": {
|
||||
"delegate": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
|
||||
|
@ -1386,6 +1444,13 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
|
@ -1430,11 +1495,45 @@
|
|||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/highlight.js": {
|
||||
"version": "11.11.1",
|
||||
"resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.11.1.tgz",
|
||||
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/hookable": {
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
|
||||
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/image-size": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz",
|
||||
"integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"image-size": "bin/image-size.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-what": {
|
||||
"version": "4.1.16",
|
||||
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
|
||||
|
@ -1446,6 +1545,76 @@
|
|||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/less": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/less/-/less-4.4.1.tgz",
|
||||
"integrity": "sha512-X9HKyiXPi0f/ed0XhgUlBeFfxrlDP3xR4M7768Zl+WXLUViuL9AOPPJP4nCV0tgRWvTYvpNmN0SFhZOQzy16PA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"copy-anything": "^2.0.1",
|
||||
"parse-node-version": "^1.0.1",
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"bin": {
|
||||
"lessc": "bin/lessc"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"errno": "^0.1.1",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"image-size": "~0.5.0",
|
||||
"make-dir": "^2.1.0",
|
||||
"mime": "^1.4.1",
|
||||
"needle": "^3.1.0",
|
||||
"source-map": "~0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/less-loader": {
|
||||
"version": "12.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/less-loader/-/less-loader-12.3.0.tgz",
|
||||
"integrity": "sha512-0M6+uYulvYIWs52y0LqN4+QM9TqWAohYSNTo4htE8Z7Cn3G/qQMEmktfHmyJT23k+20kU9zHH2wrfFXkxNLtVw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 18.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@rspack/core": "0.x || 1.x",
|
||||
"less": "^3.5.0 || ^4.0.0",
|
||||
"webpack": "^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@rspack/core": {
|
||||
"optional": true
|
||||
},
|
||||
"webpack": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/less/node_modules/copy-anything": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz",
|
||||
"integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-what": "^3.14.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/less/node_modules/is-what": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz",
|
||||
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
|
@ -1459,6 +1628,39 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz",
|
||||
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"pify": "^4.0.1",
|
||||
"semver": "^5.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "12.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/marked/-/marked-12.0.2.tgz",
|
||||
"integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/marked-highlight": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/marked-highlight/-/marked-highlight-2.2.2.tgz",
|
||||
"integrity": "sha512-KlHOP31DatbtPPXPaI8nx1KTrG3EW0Z5zewCwpUj65swbtKOTStteK3sNAjBqV75Pgo3fNEVNHeptg18mDuWgw==",
|
||||
"peerDependencies": {
|
||||
"marked": ">=4 <17"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
|
@ -1467,6 +1669,19 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
|
||||
|
@ -1513,6 +1728,32 @@
|
|||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/needle": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/needle/-/needle-3.3.1.tgz",
|
||||
"integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"iconv-lite": "^0.6.3",
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"bin": {
|
||||
"needle": "bin/needle"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.4.x"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-node-version": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz",
|
||||
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/path-browserify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||
|
@ -1539,6 +1780,16 @@
|
|||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pify": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz",
|
||||
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/pinia": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.3.tgz",
|
||||
|
@ -1591,6 +1842,13 @@
|
|||
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz",
|
||||
"integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
|
||||
|
@ -1635,11 +1893,50 @@
|
|||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.1.tgz",
|
||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/select": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
|
||||
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/sortablejs": {
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.6.tgz",
|
||||
"integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A=="
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
|
@ -1704,6 +2001,11 @@
|
|||
"vue": ">=3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||
},
|
||||
"node_modules/tinycolor2": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz",
|
||||
|
@ -1725,6 +2027,12 @@
|
|||
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tdesign-vue-next/chat": "^0.4.5",
|
||||
"@types/node": "^24.2.1",
|
||||
"@vue/language-core": "^3.0.5",
|
||||
"axios": "^1.11.0",
|
||||
|
@ -21,6 +22,8 @@
|
|||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"less": "^4.4.1",
|
||||
"less-loader": "^12.3.0",
|
||||
"typescript": "~5.8.3",
|
||||
"vite": "^7.1.2",
|
||||
"vue-tsc": "^3.0.5"
|
||||
|
|
|
@ -34,6 +34,8 @@ import { useLanguageStore } from './store/language'
|
|||
import { provide } from 'vue'
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
|
||||
|
||||
// 初始化语言store并提供翻译函数
|
||||
const languageStore = useLanguageStore()
|
||||
provide('t', (key: string) => languageStore.t(key))
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
|
@ -0,0 +1,221 @@
|
|||
const Api = {
|
||||
// CHAT_AI_URL: 'http://localhost:8180/chat/generateStreamFlex'
|
||||
CHAT_AI_URL: 'http://localhost:8180/rag/query_rag'
|
||||
};
|
||||
import axios from 'axios'
|
||||
const getAi=(msg: any):any => {
|
||||
return axios.get(Api.CHAT_AI_URL, {
|
||||
params: { message: msg },
|
||||
headers: { Accept: 'text/event-stream' },
|
||||
responseType: 'stream'
|
||||
});
|
||||
}
|
||||
export class MockSSEResponse {
|
||||
private controller!: ReadableStreamDefaultController<Uint8Array>;
|
||||
|
||||
private encoder = new TextEncoder();
|
||||
|
||||
private stream: ReadableStream<Uint8Array>;
|
||||
|
||||
private error: boolean;
|
||||
|
||||
private currentPhase: 'reasoning' | 'content' = 'reasoning';
|
||||
|
||||
constructor(
|
||||
private data: {
|
||||
reasoning: string; // 推理内容
|
||||
content: string; // 正式内容
|
||||
},
|
||||
private delay: number = 100,
|
||||
error = false,
|
||||
) {
|
||||
this.error = error;
|
||||
|
||||
this.stream = new ReadableStream({
|
||||
start: (controller) => {
|
||||
this.controller = controller;
|
||||
if (!this.error) {
|
||||
// 如果不是错误情况,则开始推送数据
|
||||
setTimeout(() => this.pushData(), this.delay); // 延迟开始推送数据
|
||||
}
|
||||
},
|
||||
cancel() {},
|
||||
});
|
||||
}
|
||||
|
||||
private pushData() {
|
||||
try {
|
||||
if (this.currentPhase === 'reasoning') {
|
||||
// 推送推理内容
|
||||
if (this.data.reasoning.length > 0) {
|
||||
const chunk = JSON.stringify({
|
||||
delta: {
|
||||
reasoning_content: this.data.reasoning.slice(0, 1),
|
||||
content: '',
|
||||
},
|
||||
finished: false,
|
||||
});
|
||||
this.controller.enqueue(this.encoder.encode(chunk));
|
||||
this.data.reasoning = this.data.reasoning.slice(1);
|
||||
// 设置下次推送
|
||||
setTimeout(() => this.pushData(), this.delay);
|
||||
} else {
|
||||
// 推理内容推送完成,切换到正式内容
|
||||
this.currentPhase = 'content';
|
||||
setTimeout(() => this.pushData(), this.delay); // 立即开始推送正式内容
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentPhase === 'content') {
|
||||
// 推送正式内容
|
||||
if (this.data.content.length > 0) {
|
||||
const chunk = JSON.stringify({
|
||||
delta: {
|
||||
reasoning_content: '',
|
||||
content: this.data.content.slice(0, 1),
|
||||
},
|
||||
finished: this.data.content.length === 1, // 最后一个字符时标记完成
|
||||
});
|
||||
this.controller.enqueue(this.encoder.encode(chunk));
|
||||
this.data.content = this.data.content.slice(1);
|
||||
|
||||
// 设置下次推送
|
||||
setTimeout(() => this.pushData(), this.delay);
|
||||
} else {
|
||||
// const finalPayload = JSON.stringify({
|
||||
// delta: {
|
||||
// reasoning_content: '',
|
||||
// content: '',
|
||||
// },
|
||||
// finished: true,
|
||||
// });
|
||||
// this.controller.enqueue(this.encoder.encode(`${finalPayload}`));
|
||||
// 全部内容推送完成
|
||||
setTimeout(() => this.controller.close(), this.delay);
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
getResponse(_msg: String): Promise<Response> {
|
||||
return new Promise((resolve) => {
|
||||
resolve(getAi(_msg));
|
||||
});
|
||||
}
|
||||
|
||||
// 封装SSE连接
|
||||
connectSSE = (url, params, onMessage, onError) => {
|
||||
// 构建带参数的URL
|
||||
const queryString = Object.keys(params)
|
||||
.map((key, value) => `${encodeURIComponent(key)}=${params[key].message}`)
|
||||
.join('&');
|
||||
|
||||
const API_BASE_URL = 'http://localhost:8180';
|
||||
const fullUrl = `${API_BASE_URL}${url}?${queryString}`;
|
||||
|
||||
// 创建EventSource
|
||||
const eventSource = new EventSource(fullUrl);
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
const { data } = event;
|
||||
|
||||
// 检查是否是特殊标记
|
||||
if (data === '[DONE]') {
|
||||
if (onMessage) onMessage('[DONE]');
|
||||
} else {
|
||||
// 处理普通消息
|
||||
if (onMessage) onMessage(data);
|
||||
}
|
||||
};
|
||||
|
||||
eventSource.onerror = (error) => {
|
||||
if (onError) onError(error);
|
||||
eventSource.close();
|
||||
};
|
||||
|
||||
// 返回eventSource实例,以便后续可以关闭连接
|
||||
return eventSource;
|
||||
};
|
||||
|
||||
// AI超级智能体聊天
|
||||
chatWithManus = (message) => {
|
||||
return this.connectSSE('/rag/query_rag', { message });
|
||||
};
|
||||
}
|
||||
|
||||
export const fetchSSE = async (options: FetchSSEOptions = {}) => {
|
||||
const { success, fail, complete, url } = options;
|
||||
// fetch请求流式接口url,需传入接口url和参数
|
||||
const responsePromise = fetch(url).catch((e) => {
|
||||
const msg = e.toString() || '流式接口异常';
|
||||
complete?.(false, msg);
|
||||
return Promise.reject(e); // 确保错误能够被后续的.catch()捕获
|
||||
});
|
||||
|
||||
responsePromise
|
||||
.then((response) => {
|
||||
if (!response?.ok) {
|
||||
complete?.(false, response.statusText);
|
||||
fail?.();
|
||||
throw new Error('Request failed'); // 抛出错误以便链式调用中的下一个.catch()处理
|
||||
}
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
if (!reader) throw new Error('No reader available');
|
||||
|
||||
const bufferArr: string[] = [];
|
||||
let dataText = ''; // 记录数据
|
||||
const event: SSEEvent = { type: null, data: null };
|
||||
|
||||
async function processText({ done, value }: ReadableStreamReadResult<Uint8Array>): Promise<void> {
|
||||
if (done) {
|
||||
complete?.(true);
|
||||
return Promise.resolve();
|
||||
}
|
||||
const chunk = decoder.decode(value);
|
||||
const buffers = chunk.toString().replaceAll(' ', ' ').split(/\r?\n/);
|
||||
bufferArr.push(...buffers);
|
||||
const i = 0;
|
||||
while (i < bufferArr.length) {
|
||||
const line = bufferArr[i];
|
||||
if (line) {
|
||||
dataText += line;
|
||||
const response = line.slice(5);
|
||||
if (response === '[DONE]') {
|
||||
event.type = 'finish';
|
||||
dataText = '';
|
||||
} else {
|
||||
event.type = 'delta';
|
||||
event.data = response;
|
||||
|
||||
// const choices = JSON.parse(response.trim())?.choices?.[0];
|
||||
// if (choices.finish_reason === 'stop') {
|
||||
// event.type = 'finish';
|
||||
// dataText = '';
|
||||
// } else {
|
||||
// event.type = 'delta';
|
||||
// event.data = choices;
|
||||
// }
|
||||
}
|
||||
}
|
||||
if (event.type && event.data) {
|
||||
const jsonData = JSON.parse(JSON.stringify(event));
|
||||
console.log('流式数据解析结果:', jsonData);
|
||||
// 回调更新数据
|
||||
success(jsonData);
|
||||
event.type = null;
|
||||
event.data = null;
|
||||
}
|
||||
bufferArr.splice(i, 1);
|
||||
}
|
||||
return reader.read().then(processText);
|
||||
}
|
||||
|
||||
return reader.read().then(processText);
|
||||
})
|
||||
.catch(() => {
|
||||
// 处理整个链式调用过程中发生的任何错误
|
||||
fail?.();
|
||||
});
|
||||
};
|
|
@ -0,0 +1,469 @@
|
|||
<template>
|
||||
<t-space v-if="isVisible1" align="center" @click="visibleModelessDrag = true" class="ai_style" >
|
||||
<img :src="aiImg" alt="勤怠登录页面" width="36px" height="36px">
|
||||
</t-space>
|
||||
<t-dialog
|
||||
v-model:visible="visibleModelessDrag"
|
||||
:footer="false"
|
||||
id ="abc"
|
||||
header="AI助手"
|
||||
mode="modeless"
|
||||
showOverlay="true"
|
||||
draggable
|
||||
:on-confirm="() => (visibleModelessDrag = false)"
|
||||
>
|
||||
<template #body>
|
||||
<t-chat
|
||||
layout="both"
|
||||
style="height: 600px;"
|
||||
:z-index="3000"
|
||||
:data="chatList"
|
||||
:clear-history="chatList.length > 0 && !isStreamLoad"
|
||||
:text-loading="loading"
|
||||
:is-stream-load="isStreamLoad"
|
||||
@on-action="operation"
|
||||
@clear="clearConfirm"
|
||||
>
|
||||
<!-- eslint-disable-next-line vue/no-unused-vars -->
|
||||
<template #actions="{ item, index }">
|
||||
<t-chat-action
|
||||
:content="item.content"
|
||||
:operation-btn="['good', 'bad', 'replay', 'copy']"
|
||||
@operation="handleOperation"
|
||||
/>
|
||||
</template>
|
||||
<template #footer>
|
||||
<t-chat-input v-model="inputValue" :stop-disabled="isStreamLoad" @send="inputEnter" @stop="onStop"> </t-chat-input>
|
||||
</template>
|
||||
</t-chat>
|
||||
</template>
|
||||
</t-dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import aiImg from '@/assets/ai_img.png'
|
||||
const visibleModelessDrag = ref(false);
|
||||
import { MockSSEResponse } from './ChatAi';
|
||||
const fetchCancel = ref(null);
|
||||
const loading = ref(false);
|
||||
const isStreamLoad = ref(false);
|
||||
const chatRef = ref(null);
|
||||
const isShowToBottom = ref(false);
|
||||
const inputValue = ref('');
|
||||
|
||||
|
||||
// 控制按钮显示/隐藏的状态
|
||||
const isVisible1 = ref(false)
|
||||
|
||||
const handleScroll1 = () => {
|
||||
// console.log(window.scrollY)
|
||||
// 当滚动超过300px时显示按钮
|
||||
isVisible1.value = window.scrollY > 300
|
||||
// console.log("sss:" + isVisible1.value)
|
||||
|
||||
|
||||
};
|
||||
// 挂载时添加滚动监听
|
||||
onMounted(() => {
|
||||
window.addEventListener('scroll', handleScroll1)
|
||||
})
|
||||
|
||||
// 卸载时移除滚动监听
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 倒序渲染
|
||||
const chatList = ref([
|
||||
{
|
||||
avatar: 'https://tdesign.gtimg.com/site/chat-avatar.png',
|
||||
name: 'youyueAI',
|
||||
datetime: '今天16:38',
|
||||
content: '我是你的ai助手,有什么可以帮你的。',
|
||||
role: 'assistant',
|
||||
}
|
||||
]);
|
||||
// const chatList = ref([
|
||||
// {
|
||||
// content: `模型由 <span>hunyuan</span> 变为 <span>GPT4</span>`,
|
||||
// role: 'model-change',
|
||||
// },
|
||||
// {
|
||||
// avatar: 'https://tdesign.gtimg.com/site/chat-avatar.png',
|
||||
// name: 'youyueAI',
|
||||
// datetime: '今天16:38',
|
||||
// content: '它叫 McMurdo Station ATM,是美国富国银行安装在南极洲最大科学中心麦克默多站的一台自动提款机。',
|
||||
// role: 'assistant',
|
||||
// },
|
||||
// {
|
||||
// avatar: 'https://tdesign.gtimg.com/site/avatar.jpg',
|
||||
// name: '自己',
|
||||
// datetime: '今天16:38',
|
||||
// content: '南极的自动提款机叫什么名字?',
|
||||
// role: 'user',
|
||||
// },
|
||||
// ]);
|
||||
const handleOperation = function (type, options) {
|
||||
console.log('handleOperation', type, options);
|
||||
};
|
||||
const operation = function (type, options) {
|
||||
console.log(type, options);
|
||||
};
|
||||
const clearConfirm = function () {
|
||||
chatList.value = [];
|
||||
};
|
||||
const onStop = function () {
|
||||
if (fetchCancel.value) {
|
||||
fetchCancel.value.controller.close();
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
const inputEnter = function (inputValue) {
|
||||
if (isStreamLoad.value) {
|
||||
return;
|
||||
}
|
||||
if (!inputValue) return;
|
||||
const params = {
|
||||
avatar: 'https://tdesign.gtimg.com/site/avatar.jpg',
|
||||
name: '自己',
|
||||
datetime: new Date().toDateString(),
|
||||
content: inputValue,
|
||||
role: 'user',
|
||||
};
|
||||
chatList.value.unshift(params);
|
||||
// 空消息占位
|
||||
const params2 = {
|
||||
avatar: 'https://tdesign.gtimg.com/site/chat-avatar.png',
|
||||
name: 'youyueAI',
|
||||
datetime: new Date().toDateString(),
|
||||
content: '',
|
||||
role: 'assistant',
|
||||
};
|
||||
chatList.value.unshift(params2);
|
||||
handleData(inputValue);
|
||||
};
|
||||
|
||||
const fetchSSE = async (fetchFn, options) => {
|
||||
const response = await fetchFn();
|
||||
const { success, fail, complete } = options;
|
||||
// 如果不 ok 说明有请求错误
|
||||
if (response.status !== 200) {
|
||||
complete?.(false, response.statusText);
|
||||
fail?.();
|
||||
return;
|
||||
}
|
||||
// const reader = response?.body?.getReader();
|
||||
// const decoder = new TextDecoder();
|
||||
// if (!reader) return;
|
||||
|
||||
// reader.read().then(function processText({ done, value }) {
|
||||
// if (done) {
|
||||
// // 正常的返回
|
||||
// complete?.(true);
|
||||
// return;
|
||||
// }
|
||||
// const chunk = decoder.decode(value, { stream: true });
|
||||
const buffers = response.data.split(/\r?\n/);
|
||||
// const jsonData = JSON.parse(buffers);
|
||||
success(buffers);
|
||||
// reader.read().then(processText);
|
||||
|
||||
|
||||
};
|
||||
|
||||
const displayText = ref('');
|
||||
const fullText = ref('');
|
||||
const isLoading = ref(true);
|
||||
const eventSource = null;
|
||||
let isProcessing = false;
|
||||
const messageBuffer = [];
|
||||
let animationFrameId = null;
|
||||
|
||||
// 配置参数
|
||||
const config = {
|
||||
bufferSize: 5, // 缓冲的消息数量
|
||||
flushInterval: 10, // 刷新间隔(ms)
|
||||
typingSpeed: 50, // 打字速度(ms/字符)
|
||||
};
|
||||
|
||||
// 处理消息缓冲区
|
||||
const processBuffer = async () => {
|
||||
isProcessing = true;
|
||||
|
||||
// 使用requestAnimationFrame优化渲染性能
|
||||
const processNextMessage = () => {
|
||||
if (messageBuffer.length === 0) {
|
||||
isProcessing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 从缓冲区取出消息
|
||||
const message = messageBuffer.shift();
|
||||
|
||||
try {
|
||||
// 解析消息内容
|
||||
// const parsedData = JSON.parse(message);
|
||||
// const content = parsedData.choices[0]?.delta?.content || '';
|
||||
|
||||
if (message) {
|
||||
// 模拟打字效果,逐个字符添加
|
||||
typeCharacter(message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析SSE消息失败:', error);
|
||||
}
|
||||
|
||||
// 继续处理下一个消息
|
||||
animationFrameId = requestAnimationFrame(processNextMessage);
|
||||
};
|
||||
|
||||
// 开始处理消息
|
||||
animationFrameId = requestAnimationFrame(processNextMessage);
|
||||
};
|
||||
|
||||
// 模拟打字效果
|
||||
const typeCharacter = (content) => {
|
||||
const index = 0;
|
||||
setTimeout(() => {
|
||||
chatList.value[0].content += content.replaceAll(' ', ' ');
|
||||
}, config.typingSpeed);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleData = async () => {
|
||||
loading.value = true;
|
||||
isStreamLoad.value = true;
|
||||
const lastItem = chatList.value[0];
|
||||
|
||||
const mockedData = {
|
||||
reasoning: '1',
|
||||
content: '2',
|
||||
};
|
||||
|
||||
const mockResponse = new MockSSEResponse(mockedData);
|
||||
|
||||
// 临时存储
|
||||
// const messageBuffer = []; // 用于存储SSE消息的缓冲区
|
||||
|
||||
const message = {
|
||||
message: inputValue.value,
|
||||
};
|
||||
const eventSource = mockResponse.chatWithManus(message);
|
||||
eventSource.onmessage = (event) => {
|
||||
const { data } = event;
|
||||
|
||||
if (data && data !== '[DONE]') {
|
||||
// messageBuffer.push(data);
|
||||
|
||||
loading.value = false;
|
||||
// 控制终止按钮
|
||||
isStreamLoad.value = false;
|
||||
// lastItem.reasoning += data.replaceAll(' ', ' ');
|
||||
// lastItem.content += data.replaceAll(' ', ' ');
|
||||
|
||||
// 将消息添加到缓冲区
|
||||
messageBuffer.push(data.replaceAll(' ', ' '));
|
||||
|
||||
// 如果不在处理中,则开始处理缓冲区
|
||||
if (!isProcessing) {
|
||||
processBuffer();
|
||||
}
|
||||
|
||||
// // 检查是否应该创建新气泡
|
||||
// const combinedText = messageBuffer.join('');
|
||||
|
||||
// // 句子结束或消息长度达到阈值
|
||||
// const lastChar = data.charAt(data.length - 1);
|
||||
// const hasCompleteSentence = chineseEndPunctuation.includes(lastChar) || data.includes('\n\n');
|
||||
// const isLongEnough = combinedText.length > 40;
|
||||
|
||||
// if (hasCompleteSentence || isLongEnough) {
|
||||
// createBubble(combinedText);
|
||||
// }
|
||||
}
|
||||
|
||||
if (data === '[DONE]') {
|
||||
// 如果还有未显示的内容,创建最后一个气泡
|
||||
// if (messageBuffer.length > 0) {
|
||||
// const remainingContent = messageBuffer.join('');
|
||||
// createBubble(remainingContent, 'ai-final');
|
||||
// }
|
||||
// 控制终止按钮
|
||||
isStreamLoad.value = false;
|
||||
loading.value = false;
|
||||
|
||||
// 完成后关闭连接
|
||||
// connectionStatus.value = 'disconnected';
|
||||
eventSource.close();
|
||||
}
|
||||
};
|
||||
|
||||
// 监听SSE错误
|
||||
eventSource.onerror = (error) => {
|
||||
// console.error('SSE Error:', error);
|
||||
// connectionStatus.value = 'error';
|
||||
// eventSource.close();
|
||||
// // 如果出错时有未显示的内容,也创建气泡
|
||||
// if (messageBuffer.length > 0) {
|
||||
// const remainingContent = messageBuffer.join('');
|
||||
// createBubble(remainingContent, 'ai-error');
|
||||
// }
|
||||
};
|
||||
|
||||
// 流结束时触发
|
||||
eventSource.onclose = () => {
|
||||
console.log('流式响应已结束');
|
||||
// 可在此处做清理工作,如关闭 EventSource
|
||||
eventSource.close();
|
||||
};
|
||||
|
||||
// await fetchSSE(
|
||||
// () => {
|
||||
// return mockResponse.getResponse(inputValue.value);
|
||||
// },
|
||||
// {
|
||||
// success(result) {
|
||||
// console.log('success', result);
|
||||
|
||||
// for (let i = 0; i < result.length; i++) {
|
||||
// if (result[i] !== '') {
|
||||
// lastItem.reasoning += result[i].replace('data:', '');
|
||||
// lastItem.content += result[i].replace('data:', '');
|
||||
// }
|
||||
// }
|
||||
|
||||
// loading.value = false;
|
||||
// // 控制终止按钮
|
||||
// isStreamLoad.value = false;
|
||||
// // lastItem.reasoning += result.delta.reasoning_content;
|
||||
// // lastItem.content += result.delta.content;
|
||||
// },
|
||||
// complete(isOk, msg) {
|
||||
// if (!isOk) {
|
||||
// lastItem.role = 'error';
|
||||
// lastItem.content = msg;
|
||||
// lastItem.reasoning = msg;
|
||||
// }
|
||||
// // 显示用时xx秒,业务侧需要自行处理
|
||||
// lastItem.duration = 20;
|
||||
// // 控制终止按钮
|
||||
// isStreamLoad.value = false;
|
||||
// loading.value = false;
|
||||
// },
|
||||
// },
|
||||
// );
|
||||
};
|
||||
|
||||
// const handleData = async () => {
|
||||
// loading.value = true;
|
||||
// isStreamLoad.value = true;
|
||||
// const lastItem = chatList.value[0];
|
||||
// const mockedData = `这是一段模拟的流式字符串数据。`;
|
||||
// const mockResponse = new MockSSEResponse(mockedData);
|
||||
// fetchCancel.value = mockResponse;
|
||||
// await fetchSSE(
|
||||
// () => {
|
||||
// return mockResponse.getResponse();
|
||||
// },
|
||||
// {
|
||||
// success(result) {
|
||||
// loading.value = false;
|
||||
// const { data } = result;
|
||||
// lastItem.content += data;
|
||||
// },
|
||||
// complete(isOk, msg) {
|
||||
// if (!isOk || !lastItem.content) {
|
||||
// lastItem.role = 'error';
|
||||
// lastItem.content = msg;
|
||||
// }
|
||||
// // 控制终止按钮
|
||||
// isStreamLoad.value = false;
|
||||
// loading.value = false;
|
||||
// },
|
||||
// },
|
||||
// );
|
||||
// };
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
/* 应用滚动条样式 */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--td-scrollbar-color);
|
||||
}
|
||||
::-webkit-scrollbar-thumb:horizontal:hover {
|
||||
background-color: var(--td-scrollbar-hover-color);
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: var(--td-scroll-track-color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 第一种写法重写 组件样式
|
||||
:global(.t-dialog__ctx.t-dialog__ctx--modeless .t-dialog) {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
|
||||
:deep(.t-chat__text) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
// 第二种重写样式 定义一个啥也不带的 style
|
||||
<style>
|
||||
|
||||
.t-chat__actions-margin {
|
||||
display: none;
|
||||
}
|
||||
.t-dialog__ctx .t-dialog__wrap {
|
||||
z-index: 3001;
|
||||
right: 10;
|
||||
}
|
||||
|
||||
.t-dialog__ctx .t-dialog__position {
|
||||
justify-content: right;
|
||||
/* left: 86px; */
|
||||
position: fixed;
|
||||
right: 100px;
|
||||
bottom: 52px;
|
||||
}
|
||||
|
||||
.ai_style{
|
||||
gap: 16px;
|
||||
position: fixed;
|
||||
bottom: 100px;
|
||||
right: 2rem;
|
||||
background-color: #d7e6ed;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
.ai_style:hover {
|
||||
background-color: var(--primary-dark);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.t-dialog__ctx .t-dialog__position {
|
||||
justify-content: center;
|
||||
/* left: 86px; */
|
||||
position: unset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -8,6 +8,7 @@ const isVisible = ref(false)
|
|||
const handleScroll = () => {
|
||||
// 当滚动超过300px时显示按钮
|
||||
isVisible.value = window.scrollY > 300
|
||||
|
||||
}
|
||||
|
||||
// 回到顶部函数
|
||||
|
|
|
@ -9,8 +9,10 @@ import router from './router/index.ts' // 确保路径正确
|
|||
import { createPinia } from 'pinia'
|
||||
// 引入TDesign UI组件库
|
||||
import TDesign from 'tdesign-vue-next'
|
||||
import TDesignChat from '@tdesign-vue-next/chat'; // 引入chat组件
|
||||
import 'tdesign-vue-next/es/style/index.css'
|
||||
|
||||
|
||||
const app = createApp(App)
|
||||
// 必须先 use(router),再挂载
|
||||
app.use(router)
|
||||
|
@ -20,6 +22,7 @@ app.use(createPinia())
|
|||
|
||||
// 使用TDesign
|
||||
app.use(TDesign)
|
||||
app.use(TDesignChat)
|
||||
|
||||
app.mount('#app')
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
<!-- 联系我们 -->
|
||||
<ContactForm />
|
||||
|
||||
<ChatAi />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -37,6 +39,8 @@ import TeamMembers from '@/components/team/TeamMembers.vue'
|
|||
import ProjectShowcase from '@/components/projects/ProjectShowcase.vue'
|
||||
import ContactForm from '@/components/contact/ContactForm.vue'
|
||||
import CompanyTimeline from '@/components/timeline/CompanyTimeline.vue'
|
||||
|
||||
import ChatAi from '@/components/chat/ChatAi.vue'
|
||||
import { inject } from 'vue'
|
||||
|
||||
// 注入翻译函数(与原App.vue保持一致)
|
||||
|
|
|
@ -10,4 +10,9 @@ export default defineConfig({
|
|||
'@': path.resolve(__dirname, 'src'), // 将 @ 指向 src 目录
|
||||
},
|
||||
},
|
||||
server: {
|
||||
host: '0.0.0.0', // 监听所有网络接口
|
||||
port: 5173, // 可自定义端口(默认5173)
|
||||
open: false // 可选:是否自动打开浏览器
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue