正在显示
15 个修改的文件
包含
952 行增加
和
10 行删除
1 | -<!DOCTYPE html> | 1 | +<!doctype html> |
2 | <html lang=""> | 2 | <html lang=""> |
3 | <head> | 3 | <head> |
4 | - <meta charset="UTF-8"> | ||
5 | - <link rel="icon" href="/favicon.ico"> | 4 | + <meta charset="UTF-8" /> |
5 | + <link rel="icon" href="/favicon.ico" /> | ||
6 | <script src="https://cdn.tailwindcss.com"></script> | 6 | <script src="https://cdn.tailwindcss.com"></script> |
7 | - <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet"> | ||
8 | - <meta name="viewport" content="width=device-width, initial-scale=1.0"> | 7 | + <link |
8 | + href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" | ||
9 | + rel="stylesheet" | ||
10 | + /> | ||
11 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
9 | <title>Vite App</title> | 12 | <title>Vite App</title> |
10 | </head> | 13 | </head> |
11 | <body> | 14 | <body> |
12 | <div id="app"></div> | 15 | <div id="app"></div> |
13 | <script type="module" src="/src/main.js"></script> | 16 | <script type="module" src="/src/main.js"></script> |
17 | + <script type="text/javascript" src="/config.js"></script> | ||
14 | </body> | 18 | </body> |
15 | </html> | 19 | </html> |
@@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
8 | "name": "aigeo", | 8 | "name": "aigeo", |
9 | "version": "0.0.0", | 9 | "version": "0.0.0", |
10 | "dependencies": { | 10 | "dependencies": { |
11 | + "axios": "^1.11.0", | ||
11 | "chart.js": "^4.5.0", | 12 | "chart.js": "^4.5.0", |
12 | "pinia": "^3.0.3", | 13 | "pinia": "^3.0.3", |
13 | "sass": "^1.90.0", | 14 | "sass": "^1.90.0", |
@@ -2009,6 +2010,12 @@ | @@ -2009,6 +2010,12 @@ | ||
2009 | "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", | 2010 | "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", |
2010 | "license": "MIT" | 2011 | "license": "MIT" |
2011 | }, | 2012 | }, |
2013 | + "node_modules/asynckit": { | ||
2014 | + "version": "0.4.0", | ||
2015 | + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", | ||
2016 | + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", | ||
2017 | + "license": "MIT" | ||
2018 | + }, | ||
2012 | "node_modules/autoprefixer": { | 2019 | "node_modules/autoprefixer": { |
2013 | "version": "10.4.21", | 2020 | "version": "10.4.21", |
2014 | "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.21.tgz", | 2021 | "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.21.tgz", |
@@ -2047,6 +2054,17 @@ | @@ -2047,6 +2054,17 @@ | ||
2047 | "postcss": "^8.1.0" | 2054 | "postcss": "^8.1.0" |
2048 | } | 2055 | } |
2049 | }, | 2056 | }, |
2057 | + "node_modules/axios": { | ||
2058 | + "version": "1.11.0", | ||
2059 | + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz", | ||
2060 | + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", | ||
2061 | + "license": "MIT", | ||
2062 | + "dependencies": { | ||
2063 | + "follow-redirects": "^1.15.6", | ||
2064 | + "form-data": "^4.0.4", | ||
2065 | + "proxy-from-env": "^1.1.0" | ||
2066 | + } | ||
2067 | + }, | ||
2050 | "node_modules/balanced-match": { | 2068 | "node_modules/balanced-match": { |
2051 | "version": "1.0.2", | 2069 | "version": "1.0.2", |
2052 | "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", | 2070 | "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", |
@@ -2144,6 +2162,19 @@ | @@ -2144,6 +2162,19 @@ | ||
2144 | "url": "https://github.com/sponsors/sindresorhus" | 2162 | "url": "https://github.com/sponsors/sindresorhus" |
2145 | } | 2163 | } |
2146 | }, | 2164 | }, |
2165 | + "node_modules/call-bind-apply-helpers": { | ||
2166 | + "version": "1.0.2", | ||
2167 | + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", | ||
2168 | + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", | ||
2169 | + "license": "MIT", | ||
2170 | + "dependencies": { | ||
2171 | + "es-errors": "^1.3.0", | ||
2172 | + "function-bind": "^1.1.2" | ||
2173 | + }, | ||
2174 | + "engines": { | ||
2175 | + "node": ">= 0.4" | ||
2176 | + } | ||
2177 | + }, | ||
2147 | "node_modules/camelcase-css": { | 2178 | "node_modules/camelcase-css": { |
2148 | "version": "2.0.1", | 2179 | "version": "2.0.1", |
2149 | "resolved": "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz", | 2180 | "resolved": "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz", |
@@ -2240,6 +2271,18 @@ | @@ -2240,6 +2271,18 @@ | ||
2240 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", | 2271 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", |
2241 | "license": "MIT" | 2272 | "license": "MIT" |
2242 | }, | 2273 | }, |
2274 | + "node_modules/combined-stream": { | ||
2275 | + "version": "1.0.8", | ||
2276 | + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", | ||
2277 | + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", | ||
2278 | + "license": "MIT", | ||
2279 | + "dependencies": { | ||
2280 | + "delayed-stream": "~1.0.0" | ||
2281 | + }, | ||
2282 | + "engines": { | ||
2283 | + "node": ">= 0.8" | ||
2284 | + } | ||
2285 | + }, | ||
2243 | "node_modules/commander": { | 2286 | "node_modules/commander": { |
2244 | "version": "4.1.1", | 2287 | "version": "4.1.1", |
2245 | "resolved": "https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz", | 2288 | "resolved": "https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz", |
@@ -2364,6 +2407,15 @@ | @@ -2364,6 +2407,15 @@ | ||
2364 | "url": "https://github.com/sponsors/sindresorhus" | 2407 | "url": "https://github.com/sponsors/sindresorhus" |
2365 | } | 2408 | } |
2366 | }, | 2409 | }, |
2410 | + "node_modules/delayed-stream": { | ||
2411 | + "version": "1.0.0", | ||
2412 | + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", | ||
2413 | + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", | ||
2414 | + "license": "MIT", | ||
2415 | + "engines": { | ||
2416 | + "node": ">=0.4.0" | ||
2417 | + } | ||
2418 | + }, | ||
2367 | "node_modules/detect-libc": { | 2419 | "node_modules/detect-libc": { |
2368 | "version": "1.0.3", | 2420 | "version": "1.0.3", |
2369 | "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz", | 2421 | "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz", |
@@ -2389,6 +2441,20 @@ | @@ -2389,6 +2441,20 @@ | ||
2389 | "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", | 2441 | "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", |
2390 | "license": "MIT" | 2442 | "license": "MIT" |
2391 | }, | 2443 | }, |
2444 | + "node_modules/dunder-proto": { | ||
2445 | + "version": "1.0.1", | ||
2446 | + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", | ||
2447 | + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", | ||
2448 | + "license": "MIT", | ||
2449 | + "dependencies": { | ||
2450 | + "call-bind-apply-helpers": "^1.0.1", | ||
2451 | + "es-errors": "^1.3.0", | ||
2452 | + "gopd": "^1.2.0" | ||
2453 | + }, | ||
2454 | + "engines": { | ||
2455 | + "node": ">= 0.4" | ||
2456 | + } | ||
2457 | + }, | ||
2392 | "node_modules/eastasianwidth": { | 2458 | "node_modules/eastasianwidth": { |
2393 | "version": "0.2.0", | 2459 | "version": "0.2.0", |
2394 | "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", | 2460 | "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", |
@@ -2430,6 +2496,51 @@ | @@ -2430,6 +2496,51 @@ | ||
2430 | "url": "https://github.com/sponsors/antfu" | 2496 | "url": "https://github.com/sponsors/antfu" |
2431 | } | 2497 | } |
2432 | }, | 2498 | }, |
2499 | + "node_modules/es-define-property": { | ||
2500 | + "version": "1.0.1", | ||
2501 | + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", | ||
2502 | + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", | ||
2503 | + "license": "MIT", | ||
2504 | + "engines": { | ||
2505 | + "node": ">= 0.4" | ||
2506 | + } | ||
2507 | + }, | ||
2508 | + "node_modules/es-errors": { | ||
2509 | + "version": "1.3.0", | ||
2510 | + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", | ||
2511 | + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", | ||
2512 | + "license": "MIT", | ||
2513 | + "engines": { | ||
2514 | + "node": ">= 0.4" | ||
2515 | + } | ||
2516 | + }, | ||
2517 | + "node_modules/es-object-atoms": { | ||
2518 | + "version": "1.1.1", | ||
2519 | + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", | ||
2520 | + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", | ||
2521 | + "license": "MIT", | ||
2522 | + "dependencies": { | ||
2523 | + "es-errors": "^1.3.0" | ||
2524 | + }, | ||
2525 | + "engines": { | ||
2526 | + "node": ">= 0.4" | ||
2527 | + } | ||
2528 | + }, | ||
2529 | + "node_modules/es-set-tostringtag": { | ||
2530 | + "version": "2.1.0", | ||
2531 | + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", | ||
2532 | + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", | ||
2533 | + "license": "MIT", | ||
2534 | + "dependencies": { | ||
2535 | + "es-errors": "^1.3.0", | ||
2536 | + "get-intrinsic": "^1.2.6", | ||
2537 | + "has-tostringtag": "^1.0.2", | ||
2538 | + "hasown": "^2.0.2" | ||
2539 | + }, | ||
2540 | + "engines": { | ||
2541 | + "node": ">= 0.4" | ||
2542 | + } | ||
2543 | + }, | ||
2433 | "node_modules/esbuild": { | 2544 | "node_modules/esbuild": { |
2434 | "version": "0.25.8", | 2545 | "version": "0.25.8", |
2435 | "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.8.tgz", | 2546 | "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.8.tgz", |
@@ -2595,6 +2706,26 @@ | @@ -2595,6 +2706,26 @@ | ||
2595 | "node": ">=8" | 2706 | "node": ">=8" |
2596 | } | 2707 | } |
2597 | }, | 2708 | }, |
2709 | + "node_modules/follow-redirects": { | ||
2710 | + "version": "1.15.11", | ||
2711 | + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", | ||
2712 | + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", | ||
2713 | + "funding": [ | ||
2714 | + { | ||
2715 | + "type": "individual", | ||
2716 | + "url": "https://github.com/sponsors/RubenVerborgh" | ||
2717 | + } | ||
2718 | + ], | ||
2719 | + "license": "MIT", | ||
2720 | + "engines": { | ||
2721 | + "node": ">=4.0" | ||
2722 | + }, | ||
2723 | + "peerDependenciesMeta": { | ||
2724 | + "debug": { | ||
2725 | + "optional": true | ||
2726 | + } | ||
2727 | + } | ||
2728 | + }, | ||
2598 | "node_modules/foreground-child": { | 2729 | "node_modules/foreground-child": { |
2599 | "version": "3.3.1", | 2730 | "version": "3.3.1", |
2600 | "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.1.tgz", | 2731 | "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.1.tgz", |
@@ -2611,6 +2742,22 @@ | @@ -2611,6 +2742,22 @@ | ||
2611 | "url": "https://github.com/sponsors/isaacs" | 2742 | "url": "https://github.com/sponsors/isaacs" |
2612 | } | 2743 | } |
2613 | }, | 2744 | }, |
2745 | + "node_modules/form-data": { | ||
2746 | + "version": "4.0.4", | ||
2747 | + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", | ||
2748 | + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", | ||
2749 | + "license": "MIT", | ||
2750 | + "dependencies": { | ||
2751 | + "asynckit": "^0.4.0", | ||
2752 | + "combined-stream": "^1.0.8", | ||
2753 | + "es-set-tostringtag": "^2.1.0", | ||
2754 | + "hasown": "^2.0.2", | ||
2755 | + "mime-types": "^2.1.12" | ||
2756 | + }, | ||
2757 | + "engines": { | ||
2758 | + "node": ">= 6" | ||
2759 | + } | ||
2760 | + }, | ||
2614 | "node_modules/fraction.js": { | 2761 | "node_modules/fraction.js": { |
2615 | "version": "4.3.7", | 2762 | "version": "4.3.7", |
2616 | "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", | 2763 | "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", |
@@ -2658,6 +2805,43 @@ | @@ -2658,6 +2805,43 @@ | ||
2658 | "node": ">=6.9.0" | 2805 | "node": ">=6.9.0" |
2659 | } | 2806 | } |
2660 | }, | 2807 | }, |
2808 | + "node_modules/get-intrinsic": { | ||
2809 | + "version": "1.3.0", | ||
2810 | + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", | ||
2811 | + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", | ||
2812 | + "license": "MIT", | ||
2813 | + "dependencies": { | ||
2814 | + "call-bind-apply-helpers": "^1.0.2", | ||
2815 | + "es-define-property": "^1.0.1", | ||
2816 | + "es-errors": "^1.3.0", | ||
2817 | + "es-object-atoms": "^1.1.1", | ||
2818 | + "function-bind": "^1.1.2", | ||
2819 | + "get-proto": "^1.0.1", | ||
2820 | + "gopd": "^1.2.0", | ||
2821 | + "has-symbols": "^1.1.0", | ||
2822 | + "hasown": "^2.0.2", | ||
2823 | + "math-intrinsics": "^1.1.0" | ||
2824 | + }, | ||
2825 | + "engines": { | ||
2826 | + "node": ">= 0.4" | ||
2827 | + }, | ||
2828 | + "funding": { | ||
2829 | + "url": "https://github.com/sponsors/ljharb" | ||
2830 | + } | ||
2831 | + }, | ||
2832 | + "node_modules/get-proto": { | ||
2833 | + "version": "1.0.1", | ||
2834 | + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", | ||
2835 | + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", | ||
2836 | + "license": "MIT", | ||
2837 | + "dependencies": { | ||
2838 | + "dunder-proto": "^1.0.1", | ||
2839 | + "es-object-atoms": "^1.0.0" | ||
2840 | + }, | ||
2841 | + "engines": { | ||
2842 | + "node": ">= 0.4" | ||
2843 | + } | ||
2844 | + }, | ||
2661 | "node_modules/get-stream": { | 2845 | "node_modules/get-stream": { |
2662 | "version": "9.0.1", | 2846 | "version": "9.0.1", |
2663 | "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-9.0.1.tgz", | 2847 | "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-9.0.1.tgz", |
@@ -2707,6 +2891,45 @@ | @@ -2707,6 +2891,45 @@ | ||
2707 | "node": ">=10.13.0" | 2891 | "node": ">=10.13.0" |
2708 | } | 2892 | } |
2709 | }, | 2893 | }, |
2894 | + "node_modules/gopd": { | ||
2895 | + "version": "1.2.0", | ||
2896 | + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", | ||
2897 | + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", | ||
2898 | + "license": "MIT", | ||
2899 | + "engines": { | ||
2900 | + "node": ">= 0.4" | ||
2901 | + }, | ||
2902 | + "funding": { | ||
2903 | + "url": "https://github.com/sponsors/ljharb" | ||
2904 | + } | ||
2905 | + }, | ||
2906 | + "node_modules/has-symbols": { | ||
2907 | + "version": "1.1.0", | ||
2908 | + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", | ||
2909 | + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", | ||
2910 | + "license": "MIT", | ||
2911 | + "engines": { | ||
2912 | + "node": ">= 0.4" | ||
2913 | + }, | ||
2914 | + "funding": { | ||
2915 | + "url": "https://github.com/sponsors/ljharb" | ||
2916 | + } | ||
2917 | + }, | ||
2918 | + "node_modules/has-tostringtag": { | ||
2919 | + "version": "1.0.2", | ||
2920 | + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", | ||
2921 | + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", | ||
2922 | + "license": "MIT", | ||
2923 | + "dependencies": { | ||
2924 | + "has-symbols": "^1.0.3" | ||
2925 | + }, | ||
2926 | + "engines": { | ||
2927 | + "node": ">= 0.4" | ||
2928 | + }, | ||
2929 | + "funding": { | ||
2930 | + "url": "https://github.com/sponsors/ljharb" | ||
2931 | + } | ||
2932 | + }, | ||
2710 | "node_modules/hasown": { | 2933 | "node_modules/hasown": { |
2711 | "version": "2.0.2", | 2934 | "version": "2.0.2", |
2712 | "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", | 2935 | "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", |
@@ -3016,6 +3239,15 @@ | @@ -3016,6 +3239,15 @@ | ||
3016 | "@jridgewell/sourcemap-codec": "^1.5.0" | 3239 | "@jridgewell/sourcemap-codec": "^1.5.0" |
3017 | } | 3240 | } |
3018 | }, | 3241 | }, |
3242 | + "node_modules/math-intrinsics": { | ||
3243 | + "version": "1.1.0", | ||
3244 | + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", | ||
3245 | + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", | ||
3246 | + "license": "MIT", | ||
3247 | + "engines": { | ||
3248 | + "node": ">= 0.4" | ||
3249 | + } | ||
3250 | + }, | ||
3019 | "node_modules/merge2": { | 3251 | "node_modules/merge2": { |
3020 | "version": "1.4.1", | 3252 | "version": "1.4.1", |
3021 | "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", | 3253 | "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", |
@@ -3050,6 +3282,27 @@ | @@ -3050,6 +3282,27 @@ | ||
3050 | "url": "https://github.com/sponsors/jonschlinkert" | 3282 | "url": "https://github.com/sponsors/jonschlinkert" |
3051 | } | 3283 | } |
3052 | }, | 3284 | }, |
3285 | + "node_modules/mime-db": { | ||
3286 | + "version": "1.52.0", | ||
3287 | + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", | ||
3288 | + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", | ||
3289 | + "license": "MIT", | ||
3290 | + "engines": { | ||
3291 | + "node": ">= 0.6" | ||
3292 | + } | ||
3293 | + }, | ||
3294 | + "node_modules/mime-types": { | ||
3295 | + "version": "2.1.35", | ||
3296 | + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", | ||
3297 | + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", | ||
3298 | + "license": "MIT", | ||
3299 | + "dependencies": { | ||
3300 | + "mime-db": "1.52.0" | ||
3301 | + }, | ||
3302 | + "engines": { | ||
3303 | + "node": ">= 0.6" | ||
3304 | + } | ||
3305 | + }, | ||
3053 | "node_modules/minimatch": { | 3306 | "node_modules/minimatch": { |
3054 | "version": "9.0.5", | 3307 | "version": "9.0.5", |
3055 | "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", | 3308 | "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", |
@@ -3623,6 +3876,12 @@ | @@ -3623,6 +3876,12 @@ | ||
3623 | "url": "https://github.com/sponsors/sindresorhus" | 3876 | "url": "https://github.com/sponsors/sindresorhus" |
3624 | } | 3877 | } |
3625 | }, | 3878 | }, |
3879 | + "node_modules/proxy-from-env": { | ||
3880 | + "version": "1.1.0", | ||
3881 | + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", | ||
3882 | + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", | ||
3883 | + "license": "MIT" | ||
3884 | + }, | ||
3626 | "node_modules/queue-microtask": { | 3885 | "node_modules/queue-microtask": { |
3627 | "version": "1.2.3", | 3886 | "version": "1.2.3", |
3628 | "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", | 3887 | "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", |
@@ -13,6 +13,7 @@ | @@ -13,6 +13,7 @@ | ||
13 | "format": "prettier --write src/" | 13 | "format": "prettier --write src/" |
14 | }, | 14 | }, |
15 | "dependencies": { | 15 | "dependencies": { |
16 | + "axios": "^1.11.0", | ||
16 | "chart.js": "^4.5.0", | 17 | "chart.js": "^4.5.0", |
17 | "pinia": "^3.0.3", | 18 | "pinia": "^3.0.3", |
18 | "sass": "^1.90.0", | 19 | "sass": "^1.90.0", |
public/config.js
0 → 100644
1 | +window.PLATFROM_CONFIG = { | ||
2 | + DEV_BASE_URL: 'http://erpapitest.yiwaixiao.net:80', // 开发环境 | ||
3 | + PRO_BASE_URL: 'http://erpapi.yiwaixiao.net', // 正式环境 | ||
4 | +} | ||
5 | + | ||
6 | + | ||
7 | +document.cookie = 'token=eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwNzU1ODg4NDM3MDUiLCJzdWIiOiJ5aXdhaXhpYW8ubmV0IiwidXNlcl9pZCI6Mzc4LCJsb2dpbmlkIjoiaW5mbyIsImRvbWFpbiI6IjIxZ21haWwuY29tIiwiY29tcGFueV9pZCI6NywicGFyYW1fbGV2ZWwiOjAsImxvZ3BhdGgiOiJlOlxcbG9nc1xcMjFnbWFpbC5jb21cXGluZm9cXGVycm9yXFwiLCJpYXQiOjE3NTU0ODg1MjIsImV4cCI6MTc1NTQ5NTcyMn0.B7FNn8Zk-t2SvGUwHRUURLn_2QsJNX2lJX-w8pGJhRw'; |
src/api/aiapi.js
0 → 100644
1 | +import request from '@/utils/request' | ||
2 | + | ||
3 | +export const uploadFile = (data) => { | ||
4 | + return request({ | ||
5 | + url: '/ai/upload', | ||
6 | + method: 'post', | ||
7 | + data | ||
8 | + }) | ||
9 | +} | ||
10 | + | ||
11 | +export const saveHtml = (data) => { | ||
12 | + return request({ | ||
13 | + url: '/ai/saveHtml', | ||
14 | + method: 'post', | ||
15 | + data | ||
16 | + }) | ||
17 | +} | ||
18 | + | ||
19 | +export const saveDocx = (data) => { | ||
20 | + return request({ | ||
21 | + url: '/ai/generateFile', | ||
22 | + method: 'post', | ||
23 | + data | ||
24 | + }) | ||
25 | +} | ||
26 | + | ||
27 | +export const uploadFileToDataset = (data) => { | ||
28 | + return request({ | ||
29 | + url: '/ai/uploadFileToDataset', | ||
30 | + method: 'post', | ||
31 | + data | ||
32 | + }) | ||
33 | +} | ||
34 | + | ||
35 | + | ||
36 | +//<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>登录页面</title> <style> body { font-family: Arial, sans-serif; background-color: #f4f4f4; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } .login-container { background: white; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } h2 { margin-bottom: 20px; } input[type="text"], input[type="password"] { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ccc; border-radius: 3px; } input[type="submit"] { background-color: #4CAF50; color: white; border: none; padding: 10px; cursor: pointer; border-radius: 3px; width: 100%; } input[type="submit"]:hover { background-color: #45a049; } </style> </head> <body> <div class="login-container"> <h2>用户登录</h2> <form action="/login" method="POST"> <label for="username">用户名:</label> <input type="text" id="username" name="username" required> <label for="password">密码:</label> <input type="password" id="password" name="password" required> <input type="submit" value="登录"> </form> </div> </body> </html> |
src/assets/robot.png
0 → 100644

1.7 KB
src/assets/user-icon.png
0 → 100644

1.2 KB
@@ -86,4 +86,18 @@ | @@ -86,4 +86,18 @@ | ||
86 | <script setup> | 86 | <script setup> |
87 | 87 | ||
88 | </script> | 88 | </script> |
89 | -<style scoped></style> | 89 | +<style scoped> |
90 | +@import 'tailwindcss/base'; | ||
91 | +@import 'tailwindcss/components'; | ||
92 | +@import 'tailwindcss/utilities'; | ||
93 | + | ||
94 | +@layer utilities { | ||
95 | + .content-auto { | ||
96 | + content-visibility: auto; | ||
97 | + } | ||
98 | + | ||
99 | + .sidebar-item-active { | ||
100 | + @apply bg-primary/10 text-primary border-l-4 border-primary; | ||
101 | + } | ||
102 | +} | ||
103 | +</style> |
@@ -13,6 +13,11 @@ const router = createRouter({ | @@ -13,6 +13,11 @@ const router = createRouter({ | ||
13 | name: 'about', | 13 | name: 'about', |
14 | component: () => import('../views/test.vue'), | 14 | component: () => import('../views/test.vue'), |
15 | }, | 15 | }, |
16 | + { | ||
17 | + path: '/test1', | ||
18 | + name: 'test1', | ||
19 | + component: () => import('../views/test1.vue'), | ||
20 | + }, | ||
16 | ], | 21 | ], |
17 | }) | 22 | }) |
18 | 23 |
src/utils/config.js
0 → 100644
1 | +export const MAX_SIZE = 1024 * 1024 * 5; | ||
2 | +export const INVALID_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; | ||
3 | + | ||
4 | +export const getCookie = (name) => { | ||
5 | + const cookieArr = document.cookie.split('; '); | ||
6 | + for (let item of cookieArr) { | ||
7 | + const [key, value] = item.split('='); | ||
8 | + if (key === name) { | ||
9 | + return decodeURIComponent(value); | ||
10 | + } | ||
11 | + } | ||
12 | + return null; | ||
13 | +} |
src/utils/request.js
0 → 100644
1 | +import axios from 'axios' | ||
2 | + | ||
3 | +// 根据环境获取基础URL | ||
4 | +// 从全局window对象获取配置 | ||
5 | +const config = window.PLATFROM_CONFIG || {} | ||
6 | +// 添加调试信息 | ||
7 | +const BASE_URL = import.meta.env.DEV ? config.DEV_BASE_URL : config.PRO_BASE_URL; | ||
8 | +// const API_BASE_URL="http://webdemo.yiwaixiao.net/" | ||
9 | +// 创建axios实例 | ||
10 | +const request = axios.create({ | ||
11 | + baseURL: BASE_URL, | ||
12 | + timeout: 60000, | ||
13 | + headers: { | ||
14 | + 'Content-Type': 'application/x-www-form-urlencoded', | ||
15 | + 'token': 'eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwNzU1ODg4NDM3MDUiLCJzdWIiOiJ5aXdhaXhpYW8ubmV0IiwidXNlcl9pZCI6Mzc4LCJsb2dpbmlkIjoiaW5mbyIsImRvbWFpbiI6IjIxZ21haWwuY29tIiwiY29tcGFueV9pZCI6NywicGFyYW1fbGV2ZWwiOjAsImxvZ3BhdGgiOiJkOlxcbG9nc1xcMjFnbWFpbC5jb20iLCJpYXQiOjE3NTUwNTQ5NTksImV4cCI6MTc1Njc4Mjk1OX0.WfXb6Ol7ka8n3MHgnndor2la6VzmtBHpjZngsNjwHn0' | ||
16 | + } | ||
17 | +}) | ||
18 | + | ||
19 | +// 请求拦截器 | ||
20 | +request.interceptors.request.use( | ||
21 | + config => { | ||
22 | + console.log("config:", config) | ||
23 | + console.log(BASE_URL) | ||
24 | + return config | ||
25 | + }, | ||
26 | + error => { | ||
27 | + return Promise.reject(error) | ||
28 | + } | ||
29 | +) | ||
30 | + | ||
31 | +// 响应拦截器 | ||
32 | +request.interceptors.response.use( | ||
33 | + response => { | ||
34 | + return response.data | ||
35 | + }, | ||
36 | + error => { | ||
37 | + // if (error.response?.status == '800') { | ||
38 | + // // token过期处理 | ||
39 | + // const userStore = useUserStore() | ||
40 | + // userStore.clearToken() | ||
41 | + // window.location.href = '/login' | ||
42 | + // } | ||
43 | + return Promise.reject(error) | ||
44 | + } | ||
45 | +) | ||
46 | + | ||
47 | +export default request |
@@ -541,6 +541,7 @@ | @@ -541,6 +541,7 @@ | ||
541 | import siderbar from '@/components/siderbar.vue'; | 541 | import siderbar from '@/components/siderbar.vue'; |
542 | import { ref, onMounted } from 'vue'; | 542 | import { ref, onMounted } from 'vue'; |
543 | import { Chart, registerables } from 'chart.js'; | 543 | import { Chart, registerables } from 'chart.js'; |
544 | +import { getCookie } from '@/utils/config'; | ||
544 | Chart.register(...registerables); | 545 | Chart.register(...registerables); |
545 | 546 | ||
546 | // 状态管理 | 547 | // 状态管理 |
@@ -963,6 +964,8 @@ onMounted(() => { | @@ -963,6 +964,8 @@ onMounted(() => { | ||
963 | userDropdownOpen.value = false; | 964 | userDropdownOpen.value = false; |
964 | } | 965 | } |
965 | }); | 966 | }); |
967 | + const token = getCookie('token') | ||
968 | + console.log(token) | ||
966 | }); | 969 | }); |
967 | 970 | ||
968 | tailwind.config = { | 971 | tailwind.config = { |
@@ -1033,8 +1036,4 @@ tailwind.config = { | @@ -1033,8 +1036,4 @@ tailwind.config = { | ||
1033 | @apply opacity-100 translate-y-0; | 1036 | @apply opacity-100 translate-y-0; |
1034 | } | 1037 | } |
1035 | } | 1038 | } |
1036 | - | ||
1037 | -.btn-primary { | ||
1038 | - background-color: rgb(0, 119, 255); | ||
1039 | -} | ||
1040 | </style> | 1039 | </style> |
src/views/test1.vue
0 → 100644
1 | +<script setup> | ||
2 | +import { saveDocx, saveHtml, uploadFile, uploadFileToDataset } from '@/api/aiapi'; | ||
3 | +import { ref, onMounted, computed } from 'vue'; | ||
4 | +import { MAX_SIZE, INVALID_TYPES } from '@/utils/config.js'; | ||
5 | +const messages = ref([]); | ||
6 | +const openaiMessages = ref([]); | ||
7 | +const inputMessage = ref(''); | ||
8 | +const isStreaming = ref(false); | ||
9 | +const ws = ref(null); | ||
10 | +const isConnected = ref(false); | ||
11 | +const currentMode = ref('Dify'); | ||
12 | +const modelOptions = ref(['gpt-4o-mini', 'o3-mini', 'gpt-5-mini', 'dall-e-3', 'gpt-3.5-turbo']); | ||
13 | +const selectedModel = ref('gpt-4o-mini'); | ||
14 | +const fileUrl = ref(''); | ||
15 | +const showFile = ref(false); | ||
16 | + | ||
17 | +const triggerMode = () => { | ||
18 | + if (currentMode.value === 'Dify') { | ||
19 | + currentMode.value = 'OpenAI'; | ||
20 | + } else { | ||
21 | + currentMode.value = 'Dify'; | ||
22 | + } | ||
23 | +}; | ||
24 | + | ||
25 | +const getCurrentMessages = () => { | ||
26 | + return currentMode.value === 'Dify' ? messages.value : openaiMessages.value; | ||
27 | +}; | ||
28 | + | ||
29 | +onMounted(() => { | ||
30 | + // 初始化WebSocket连接 | ||
31 | + ws.value = new WebSocket('ws://192.168.0.24/ws/chat/378'); | ||
32 | + | ||
33 | + ws.value.onopen = () => { | ||
34 | + isConnected.value = true; | ||
35 | + }; | ||
36 | + | ||
37 | + ws.value.onmessage = (event) => { | ||
38 | + const response = JSON.parse(event.data); | ||
39 | + console.log("*-**-*--------*", response) | ||
40 | + if (response.code === 200) { | ||
41 | + // 渲染AI回复 | ||
42 | + let aiMessage; | ||
43 | + if (response.task_id !== null) { | ||
44 | + aiMessage = messages.value.find(m => m.id === response.id && m.role === 'ai'); | ||
45 | + } else { | ||
46 | + openaiMessages.value.map(item => { | ||
47 | + console.log(item.id, response.id, item.id === response.id) | ||
48 | + if (item.id === response.id) { | ||
49 | + aiMessage = item | ||
50 | + } | ||
51 | + }) | ||
52 | + aiMessage = openaiMessages.value.find(m => m.id === response.id); | ||
53 | + } | ||
54 | + if (!aiMessage) { | ||
55 | + aiMessage = { | ||
56 | + role: response.task_id !== null ? 'ai' : 'assistant', | ||
57 | + type: 'text', | ||
58 | + content: '', | ||
59 | + id: response.id, | ||
60 | + }; | ||
61 | + if (currentMode.value === 'OpenAI') { | ||
62 | + openaiMessages.value.push(aiMessage); | ||
63 | + } else { | ||
64 | + aiMessage.conversation_id = response.conversation_id | ||
65 | + messages.value.push(aiMessage); | ||
66 | + } | ||
67 | + } | ||
68 | + // 追加流式内容 | ||
69 | + aiMessage.content += response.answer; | ||
70 | + } else if (response.code === 203) { | ||
71 | + // 回复结束 | ||
72 | + isStreaming.value = false; | ||
73 | + } else if (response.code === 500) { | ||
74 | + // 消息失败处理 | ||
75 | + if (currentMode.value === 'OpenAI') { | ||
76 | + openaiMessages.value.push({ | ||
77 | + role: 'system', | ||
78 | + type: 'text', | ||
79 | + content: '消息发送失败,请重试' | ||
80 | + }); | ||
81 | + } else { | ||
82 | + messages.value.push({ | ||
83 | + role: 'system', | ||
84 | + type: 'text', | ||
85 | + content: '消息发送失败,请重试' | ||
86 | + }); | ||
87 | + } | ||
88 | + isStreaming.value = false; | ||
89 | + } else if (response.code >= 300) { | ||
90 | + messages.value.push({ | ||
91 | + role: 'system', | ||
92 | + type: 'text', | ||
93 | + content: response.message | ||
94 | + }); | ||
95 | + } | ||
96 | + }; | ||
97 | + | ||
98 | + ws.value.onclose = () => { | ||
99 | + isConnected.value = false; | ||
100 | + }; | ||
101 | +}); | ||
102 | + | ||
103 | +const sendMessage = () => { | ||
104 | + if (!inputMessage.value.trim() || !isConnected.value) return; | ||
105 | + let data; | ||
106 | + if (currentMode.value === 'Dify') { | ||
107 | + data = difySendMessage() | ||
108 | + } else { | ||
109 | + openaiSendMessage() | ||
110 | + return | ||
111 | + } | ||
112 | + console.log("data:", data) | ||
113 | + | ||
114 | + ws.value.send(JSON.stringify({ | ||
115 | + method: currentMode.value, | ||
116 | + hasFile: true, | ||
117 | + dto: data | ||
118 | + })); | ||
119 | + fileUrl.value = ''; | ||
120 | + showFile.value = false; | ||
121 | + inputMessage.value = ''; | ||
122 | + isStreaming.value = true; | ||
123 | +}; | ||
124 | + | ||
125 | +const difySendMessage = () => { | ||
126 | + // 添加用户消息 | ||
127 | + messages.value.push({ | ||
128 | + role: 'user', | ||
129 | + type: 'text', | ||
130 | + content: inputMessage.value | ||
131 | + }); | ||
132 | + let data = { | ||
133 | + query: inputMessage.value | ||
134 | + } | ||
135 | + const aiMessage = messages.value.find(m => m.role === 'ai'); | ||
136 | + if (aiMessage && aiMessage.conversation_id) { | ||
137 | + data.conversation_id = aiMessage.conversation_id; | ||
138 | + } | ||
139 | + return data | ||
140 | +} | ||
141 | +const openaiSendMessage = () => { | ||
142 | + let data = { | ||
143 | + model: selectedModel.value, | ||
144 | + messages: [], | ||
145 | + } | ||
146 | + const newMessage = { | ||
147 | + role: 'user', | ||
148 | + type: 'text', | ||
149 | + content: inputMessage.value, | ||
150 | + }; | ||
151 | + // 如果有上传图片,添加到新消息 | ||
152 | + if (fileType.value !== null && fileType.value === 'image') { | ||
153 | + newMessage.image_url = uploadedImageUrl.value; | ||
154 | + } else if (fileType.value !== null && fileType.value === 'file') { | ||
155 | + data.fileContent = fileUrl.value; | ||
156 | + } | ||
157 | + openaiMessages.value.push(newMessage); | ||
158 | + openaiMessages.value.map(item => { | ||
159 | + if (item.hasOwnProperty('image_url')) { | ||
160 | + data.messages.push({ | ||
161 | + role: item.role, | ||
162 | + content: [{ | ||
163 | + type: 'text', | ||
164 | + text: item.content | ||
165 | + }, { | ||
166 | + type: 'image_url', | ||
167 | + image_url: { | ||
168 | + url: item.image_url | ||
169 | + } | ||
170 | + }] | ||
171 | + }) | ||
172 | + } else { | ||
173 | + data.messages.push({ | ||
174 | + role: item.role, | ||
175 | + content: item.content | ||
176 | + }) | ||
177 | + } | ||
178 | + }) | ||
179 | + console.log("11data:", data) | ||
180 | + ws.value.send(JSON.stringify({ | ||
181 | + method: currentMode.value, | ||
182 | + hasFile: true, | ||
183 | + dto: data | ||
184 | + })); | ||
185 | + fileUrl.value = ''; | ||
186 | + showFile.value = false; | ||
187 | + inputMessage.value = ''; | ||
188 | + isStreaming.value = true; | ||
189 | +} | ||
190 | + | ||
191 | +const triggerFileUpload = () => { | ||
192 | + document.getElementById('file-upload').click(); | ||
193 | +}; | ||
194 | + | ||
195 | +const handleFileUpload = async (event) => { | ||
196 | + try { | ||
197 | + const file = event.target.files[0]; | ||
198 | + if (!file) return; | ||
199 | + const formData = new FormData(); | ||
200 | + formData.append('file', file); | ||
201 | + const res = await uploadFileToDataset(formData); | ||
202 | + | ||
203 | + // if (file.size > MAX_SIZE) { | ||
204 | + // alert('文件大小不能超过5MB'); | ||
205 | + // return; | ||
206 | + // } | ||
207 | + // const res = await uploadFile(formData); | ||
208 | + // console.log("res:", res); | ||
209 | + // fileUrl.value = res.data; // 保存返回的URL | ||
210 | + // showFile.value = true; | ||
211 | + event.target.value = ''; | ||
212 | + } catch (err) { | ||
213 | + console.log("err:", err); | ||
214 | + alert('文件上传失败,请重试'); | ||
215 | + } | ||
216 | +}; | ||
217 | + | ||
218 | +const cancel = () => { | ||
219 | + fileUrl.value = ''; | ||
220 | + showFile.value = false; | ||
221 | +} | ||
222 | + | ||
223 | +const fileType = computed(() => { | ||
224 | + if (!fileUrl.value) return null; | ||
225 | + | ||
226 | + const url = fileUrl.value; | ||
227 | + const extension = url.split('.').pop().toLowerCase(); | ||
228 | + | ||
229 | + const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; | ||
230 | + | ||
231 | + return imageExtensions.includes(extension) ? 'image' : 'file'; | ||
232 | +}); | ||
233 | + | ||
234 | +const extractHtmlFromString = (str) => { | ||
235 | + const htmlStart = str.indexOf('```html') + '```html'.length; | ||
236 | + const htmlEnd = str.indexOf('```', htmlStart); | ||
237 | + | ||
238 | + if (htmlStart === -1 || htmlEnd === -1) { | ||
239 | + return null; // 没有找到HTML代码块 | ||
240 | + } | ||
241 | + | ||
242 | + return str.substring(htmlStart, htmlEnd).trim(); | ||
243 | +} | ||
244 | + | ||
245 | +const saveToHtml = async (content) => { | ||
246 | + const html = extractHtmlFromString(content) | ||
247 | + const res = await saveHtml({ | ||
248 | + html: html | ||
249 | + }) | ||
250 | + console.log("res:", res) | ||
251 | + if (res.code == '200' && res.data) { | ||
252 | + alert("保存成功") | ||
253 | + } else { | ||
254 | + alert("保存失败") | ||
255 | + } | ||
256 | +} | ||
257 | +function test1(input) { | ||
258 | + let processed = input; | ||
259 | + const hasSeparator = input.includes('---'); | ||
260 | + if (hasSeparator) { | ||
261 | + // 按分隔符分割并过滤空内容 | ||
262 | + const parts = input.split('---') | ||
263 | + .map(part => part.trim()) | ||
264 | + .filter(part => part.length > 0); | ||
265 | + // 取中间部分或首个有效内容 | ||
266 | + processed = parts.length > 1 ? parts.slice(1, -1).join('\n\n') || parts[1] : parts[0]; | ||
267 | + } | ||
268 | + const lines = processed.split('\n').map(line => line.trim()); | ||
269 | + let startIndex = -1; | ||
270 | + let endIndex = lines.length; | ||
271 | + // 找到第一个#标题的位置 | ||
272 | + for (let i = 0; i < lines.length; i++) { | ||
273 | + if (lines[i].startsWith('#')) { | ||
274 | + startIndex = i; | ||
275 | + break; | ||
276 | + } | ||
277 | + } | ||
278 | + if (startIndex === -1) { | ||
279 | + return lines.filter(line => line).join('\n'); | ||
280 | + } | ||
281 | + // 找到文章结束位置(连续空行或内容结束) | ||
282 | + for (let i = lines.length - 1; i >= startIndex; i--) { | ||
283 | + if (lines[i].length > 0) { | ||
284 | + endIndex = i + 1; | ||
285 | + break; | ||
286 | + } | ||
287 | + } | ||
288 | + return lines.slice(startIndex, endIndex).join('\n'); | ||
289 | +} | ||
290 | + | ||
291 | +const saveFile = async (content, type) => { | ||
292 | + const str = test1(content) | ||
293 | + const res = await saveDocx({ | ||
294 | + content: str, | ||
295 | + type | ||
296 | + }) | ||
297 | + console.log("res", res) | ||
298 | +} | ||
299 | + | ||
300 | +const test = async () => { | ||
301 | + // const file = event.target.files[0]; | ||
302 | + // const formData = new FormData(); | ||
303 | + // formData.append('file', file); | ||
304 | + // if (file.size > MAX_SIZE) { | ||
305 | + // alert('文件大小不能超过5MB'); | ||
306 | + // return; | ||
307 | + // } | ||
308 | + // const res = await uploadFile(formData); | ||
309 | + // console.log("res:", res); | ||
310 | + | ||
311 | +} | ||
312 | + | ||
313 | +</script> | ||
314 | +<template> | ||
315 | + <div class="chat-container"> | ||
316 | + <div class="chat-messages"> | ||
317 | + <div v-for="(message, index) in getCurrentMessages()" :key="index" class="message"> | ||
318 | + <div :class="['message-content', message.role]"> | ||
319 | + <img v-if="message.role === 'user'" src="@/assets/user-icon.png" class="avatar" /> | ||
320 | + <img v-else src="@/assets/robot.png" class="avatar" /> | ||
321 | + <div class="message-body"> | ||
322 | + <div v-if="message.type === 'text'"> | ||
323 | + {{ message.content }} | ||
324 | + <button v-if="message.content.includes('```html') && message.content.includes('```')" | ||
325 | + @click="saveToHtml(message.content)" class="save-btn"> | ||
326 | + 保存HTML | ||
327 | + </button> | ||
328 | + <button @click="saveFile(message.content, 'docx')" class="save-btn"> | ||
329 | + 生成DOCX | ||
330 | + </button> | ||
331 | + <button @click="saveFile(message.content, 'pdf')" class="save-btn"> | ||
332 | + 生成PDF | ||
333 | + </button> | ||
334 | + </div> | ||
335 | + <img v-else-if="message.type === 'image'" :src="message.content" class="uploaded-image" /> | ||
336 | + <div v-else-if="message.type === 'file'"> | ||
337 | + <a :href="message.content" target="_blank">下载文件</a> | ||
338 | + </div> | ||
339 | + </div> | ||
340 | + </div> | ||
341 | + </div> | ||
342 | + <div v-if="isStreaming" class="streaming-indicator"> | ||
343 | + <div class="typing-dots"> | ||
344 | + <span></span><span></span><span></span> | ||
345 | + </div> | ||
346 | + </div> | ||
347 | + </div> | ||
348 | + <div v-if="showFile" class="image-preview"> | ||
349 | + <img v-if="fileType === 'image'" :src="fileUrl" alt="预览图片" /> | ||
350 | + <span v-else>已上传文件:{{ fileUrl.split('/').pop() }}</span> | ||
351 | + | ||
352 | + <button class="cancel-btn" @click="cancel">取消</button> | ||
353 | + </div> | ||
354 | + | ||
355 | + <div class="chat-input"> | ||
356 | + <div class="upload-buttons"> | ||
357 | + <button class="small-button" @click="triggerMode">当前模式:{{ currentMode }}</button> | ||
358 | + <select v-if="currentMode === 'OpenAI'" v-model="selectedModel" class="model-select"> | ||
359 | + <option v-for="(model, index) in modelOptions" :value="model" :key="index">{{ model }}</option> | ||
360 | + </select> | ||
361 | + <div class="vertical-buttons" v-if="currentMode === 'OpenAI'"> | ||
362 | + <input type="file" id="file-upload" @change="handleFileUpload" style="display: none" /> | ||
363 | + <button class="small-button" @click="triggerFileUpload">上传文件</button> | ||
364 | + </div> | ||
365 | + </div> | ||
366 | + <textarea v-model="inputMessage" @keyup.enter="sendMessage" placeholder="输入消息..."></textarea> | ||
367 | + <button @click="sendMessage">发送</button> | ||
368 | + <button @click="saveFile">测试</button> | ||
369 | + <button @click="test">测试1</button> | ||
370 | + </div> | ||
371 | + </div> | ||
372 | +</template> | ||
373 | + | ||
374 | + | ||
375 | + | ||
376 | +<style scoped> | ||
377 | +.chat-container { | ||
378 | + display: flex; | ||
379 | + flex-direction: column; | ||
380 | + height: 100vh; | ||
381 | + max-width: 800px; | ||
382 | + margin: 0 auto; | ||
383 | + border: 1px solid #ddd; | ||
384 | +} | ||
385 | + | ||
386 | +.chat-messages { | ||
387 | + flex: 1; | ||
388 | + overflow-y: auto; | ||
389 | + padding: 20px; | ||
390 | +} | ||
391 | + | ||
392 | +.message { | ||
393 | + margin-bottom: 15px; | ||
394 | +} | ||
395 | + | ||
396 | +.message-content { | ||
397 | + display: flex; | ||
398 | + align-items: flex-start; | ||
399 | + gap: 10px; | ||
400 | +} | ||
401 | + | ||
402 | +.message-content.user { | ||
403 | + flex-direction: row-reverse; | ||
404 | +} | ||
405 | + | ||
406 | +.avatar { | ||
407 | + width: 40px; | ||
408 | + height: 40px; | ||
409 | + border-radius: 50%; | ||
410 | + object-fit: cover; | ||
411 | +} | ||
412 | + | ||
413 | +.message-body { | ||
414 | + max-width: 70%; | ||
415 | + padding: 10px 15px; | ||
416 | + border-radius: 18px; | ||
417 | + background: #f0f0f0; | ||
418 | +} | ||
419 | + | ||
420 | +.message-content.user .message-body { | ||
421 | + background: #007bff; | ||
422 | + color: white; | ||
423 | +} | ||
424 | + | ||
425 | +.uploaded-image { | ||
426 | + max-width: 200px; | ||
427 | + max-height: 200px; | ||
428 | + border-radius: 8px; | ||
429 | +} | ||
430 | + | ||
431 | +.chat-input { | ||
432 | + display: flex; | ||
433 | + padding: 10px; | ||
434 | + border-top: 1px solid #ddd; | ||
435 | + background: white; | ||
436 | + gap: 10px; | ||
437 | +} | ||
438 | + | ||
439 | +.upload-buttons { | ||
440 | + display: flex; | ||
441 | + flex-direction: column; | ||
442 | + gap: 5px; | ||
443 | + min-width: 120px; | ||
444 | +} | ||
445 | + | ||
446 | +.vertical-buttons { | ||
447 | + display: flex; | ||
448 | + flex-direction: column; | ||
449 | + gap: 5px; | ||
450 | +} | ||
451 | + | ||
452 | +/* 图片预览样式 */ | ||
453 | +.image-preview { | ||
454 | + padding: 10px; | ||
455 | + text-align: center; | ||
456 | + background: #f5f5f5; | ||
457 | + border-bottom: 1px solid #ddd; | ||
458 | +} | ||
459 | + | ||
460 | +.image-preview img { | ||
461 | + width: 80px; | ||
462 | + height: 80px; | ||
463 | + object-fit: cover; | ||
464 | + margin-bottom: 5px; | ||
465 | +} | ||
466 | + | ||
467 | +.cancel-btn { | ||
468 | + padding: 3px 8px; | ||
469 | + font-size: 12px; | ||
470 | + background: #ff4d4f; | ||
471 | +} | ||
472 | + | ||
473 | +textarea { | ||
474 | + flex: 1; | ||
475 | + padding: 10px; | ||
476 | + border: 1px solid #ddd; | ||
477 | + border-radius: 4px; | ||
478 | + resize: none; | ||
479 | + height: 60px; | ||
480 | +} | ||
481 | + | ||
482 | +button { | ||
483 | + padding: 10px 15px; | ||
484 | + background: #007bff; | ||
485 | + color: white; | ||
486 | + border: none; | ||
487 | + border-radius: 4px; | ||
488 | + cursor: pointer; | ||
489 | +} | ||
490 | + | ||
491 | +.streaming-indicator { | ||
492 | + padding: 10px; | ||
493 | +} | ||
494 | + | ||
495 | +.typing-dots span { | ||
496 | + display: inline-block; | ||
497 | + width: 8px; | ||
498 | + height: 8px; | ||
499 | + border-radius: 50%; | ||
500 | + background: #ccc; | ||
501 | + margin: 0 2px; | ||
502 | + animation: bounce 1.4s infinite ease-in-out; | ||
503 | +} | ||
504 | + | ||
505 | +.typing-dots span:nth-child(2) { | ||
506 | + animation-delay: 0.2s; | ||
507 | +} | ||
508 | + | ||
509 | +.typing-dots span:nth-child(3) { | ||
510 | + animation-delay: 0.4s; | ||
511 | +} | ||
512 | + | ||
513 | +@keyframes bounce { | ||
514 | + | ||
515 | + 0%, | ||
516 | + 60%, | ||
517 | + 100% { | ||
518 | + transform: translateY(0); | ||
519 | + } | ||
520 | + | ||
521 | + 30% { | ||
522 | + transform: translateY(-5px); | ||
523 | + } | ||
524 | +} | ||
525 | + | ||
526 | +.small-button { | ||
527 | + padding: 5px 10px; | ||
528 | + font-size: 12px; | ||
529 | + height: 30px; | ||
530 | +} | ||
531 | + | ||
532 | +.model-select { | ||
533 | + padding: 5px; | ||
534 | + border: 1px solid #ddd; | ||
535 | + border-radius: 4px; | ||
536 | + margin-right: 10px; | ||
537 | + height: 30px; | ||
538 | +} | ||
539 | + | ||
540 | +.image-preview { | ||
541 | + padding: 10px; | ||
542 | + border-bottom: 1px solid #ddd; | ||
543 | + text-align: center; | ||
544 | +} | ||
545 | + | ||
546 | +.image-preview img { | ||
547 | + max-width: 200px; | ||
548 | + max-height: 200px; | ||
549 | + margin-bottom: 10px; | ||
550 | +} | ||
551 | +</style> |
@@ -15,4 +15,9 @@ export default defineConfig({ | @@ -15,4 +15,9 @@ export default defineConfig({ | ||
15 | '@': fileURLToPath(new URL('./src', import.meta.url)) | 15 | '@': fileURLToPath(new URL('./src', import.meta.url)) |
16 | }, | 16 | }, |
17 | }, | 17 | }, |
18 | + server: { | ||
19 | + host: '0.0.0.0', | ||
20 | + port: 5189, | ||
21 | + allowedHosts: ['erpwebtest.yiwaixiao.net', 'webdemo.yiwaixiao.net'] | ||
22 | + }, | ||
18 | }) | 23 | }) |
-
请 注册 或 登录 后发表评论