hookehuyr

feat: 添加axios依赖并初始化数据管理

refactor: 重构页面组件以使用本地数据
style: 调整组件代码结构以提高可读性
docs: 更新组件注释和文档
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
11 }, 11 },
12 "dependencies": { 12 "dependencies": {
13 "@vitejs/plugin-vue-jsx": "4.1.2", 13 "@vitejs/plugin-vue-jsx": "4.1.2",
14 + "axios": "^1.8.4",
14 "pinia": "^2.1.7", 15 "pinia": "^2.1.7",
15 "vue": "^3.4.21", 16 "vue": "^3.4.21",
16 "vue-router": "^4.3.0" 17 "vue-router": "^4.3.0"
......
...@@ -11,6 +11,9 @@ importers: ...@@ -11,6 +11,9 @@ importers:
11 '@vitejs/plugin-vue-jsx': 11 '@vitejs/plugin-vue-jsx':
12 specifier: 4.1.2 12 specifier: 4.1.2
13 version: 4.1.2(vite@5.4.18)(vue@3.5.13) 13 version: 4.1.2(vite@5.4.18)(vue@3.5.13)
14 + axios:
15 + specifier: ^1.8.4
16 + version: 1.8.4
14 pinia: 17 pinia:
15 specifier: ^2.1.7 18 specifier: ^2.1.7
16 version: 2.3.1(vue@3.5.13) 19 version: 2.3.1(vue@3.5.13)
...@@ -617,6 +620,9 @@ packages: ...@@ -617,6 +620,9 @@ packages:
617 argparse@2.0.1: 620 argparse@2.0.1:
618 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 621 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
619 622
623 + asynckit@0.4.0:
624 + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
625 +
620 autoprefixer@10.4.21: 626 autoprefixer@10.4.21:
621 resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} 627 resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==}
622 engines: {node: ^10 || ^12 || >=14} 628 engines: {node: ^10 || ^12 || >=14}
...@@ -624,6 +630,9 @@ packages: ...@@ -624,6 +630,9 @@ packages:
624 peerDependencies: 630 peerDependencies:
625 postcss: ^8.1.0 631 postcss: ^8.1.0
626 632
633 + axios@1.8.4:
634 + resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==}
635 +
627 balanced-match@1.0.2: 636 balanced-match@1.0.2:
628 resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 637 resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
629 638
...@@ -649,6 +658,10 @@ packages: ...@@ -649,6 +658,10 @@ packages:
649 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 658 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
650 hasBin: true 659 hasBin: true
651 660
661 + call-bind-apply-helpers@1.0.2:
662 + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
663 + engines: {node: '>= 0.4'}
664 +
652 callsites@3.1.0: 665 callsites@3.1.0:
653 resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 666 resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
654 engines: {node: '>=6'} 667 engines: {node: '>=6'}
...@@ -675,6 +688,10 @@ packages: ...@@ -675,6 +688,10 @@ packages:
675 color-name@1.1.4: 688 color-name@1.1.4:
676 resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 689 resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
677 690
691 + combined-stream@1.0.8:
692 + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
693 + engines: {node: '>= 0.8'}
694 +
678 commander@4.1.1: 695 commander@4.1.1:
679 resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 696 resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
680 engines: {node: '>= 6'} 697 engines: {node: '>= 6'}
...@@ -709,12 +726,20 @@ packages: ...@@ -709,12 +726,20 @@ packages:
709 deep-is@0.1.4: 726 deep-is@0.1.4:
710 resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 727 resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
711 728
729 + delayed-stream@1.0.0:
730 + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
731 + engines: {node: '>=0.4.0'}
732 +
712 didyoumean@1.2.2: 733 didyoumean@1.2.2:
713 resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} 734 resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
714 735
715 dlv@1.1.3: 736 dlv@1.1.3:
716 resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 737 resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
717 738
739 + dunder-proto@1.0.1:
740 + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
741 + engines: {node: '>= 0.4'}
742 +
718 eastasianwidth@0.2.0: 743 eastasianwidth@0.2.0:
719 resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 744 resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
720 745
...@@ -731,6 +756,22 @@ packages: ...@@ -731,6 +756,22 @@ packages:
731 resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 756 resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
732 engines: {node: '>=0.12'} 757 engines: {node: '>=0.12'}
733 758
759 + es-define-property@1.0.1:
760 + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
761 + engines: {node: '>= 0.4'}
762 +
763 + es-errors@1.3.0:
764 + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
765 + engines: {node: '>= 0.4'}
766 +
767 + es-object-atoms@1.1.1:
768 + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
769 + engines: {node: '>= 0.4'}
770 +
771 + es-set-tostringtag@2.1.0:
772 + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
773 + engines: {node: '>= 0.4'}
774 +
734 esbuild@0.21.5: 775 esbuild@0.21.5:
735 resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 776 resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
736 engines: {node: '>=12'} 777 engines: {node: '>=12'}
...@@ -838,10 +879,23 @@ packages: ...@@ -838,10 +879,23 @@ packages:
838 flatted@3.3.3: 879 flatted@3.3.3:
839 resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 880 resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
840 881
882 + follow-redirects@1.15.9:
883 + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
884 + engines: {node: '>=4.0'}
885 + peerDependencies:
886 + debug: '*'
887 + peerDependenciesMeta:
888 + debug:
889 + optional: true
890 +
841 foreground-child@3.3.1: 891 foreground-child@3.3.1:
842 resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} 892 resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
843 engines: {node: '>=14'} 893 engines: {node: '>=14'}
844 894
895 + form-data@4.0.2:
896 + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==}
897 + engines: {node: '>= 6'}
898 +
845 fraction.js@4.3.7: 899 fraction.js@4.3.7:
846 resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} 900 resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
847 901
...@@ -857,6 +911,14 @@ packages: ...@@ -857,6 +911,14 @@ packages:
857 resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 911 resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
858 engines: {node: '>=6.9.0'} 912 engines: {node: '>=6.9.0'}
859 913
914 + get-intrinsic@1.3.0:
915 + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
916 + engines: {node: '>= 0.4'}
917 +
918 + get-proto@1.0.1:
919 + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
920 + engines: {node: '>= 0.4'}
921 +
860 glob-parent@5.1.2: 922 glob-parent@5.1.2:
861 resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 923 resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
862 engines: {node: '>= 6'} 924 engines: {node: '>= 6'}
...@@ -881,10 +943,22 @@ packages: ...@@ -881,10 +943,22 @@ packages:
881 resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 943 resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
882 engines: {node: '>=18'} 944 engines: {node: '>=18'}
883 945
946 + gopd@1.2.0:
947 + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
948 + engines: {node: '>= 0.4'}
949 +
884 has-flag@4.0.0: 950 has-flag@4.0.0:
885 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 951 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
886 engines: {node: '>=8'} 952 engines: {node: '>=8'}
887 953
954 + has-symbols@1.1.0:
955 + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
956 + engines: {node: '>= 0.4'}
957 +
958 + has-tostringtag@1.0.2:
959 + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
960 + engines: {node: '>= 0.4'}
961 +
888 hasown@2.0.2: 962 hasown@2.0.2:
889 resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 963 resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
890 engines: {node: '>= 0.4'} 964 engines: {node: '>= 0.4'}
...@@ -994,6 +1068,10 @@ packages: ...@@ -994,6 +1068,10 @@ packages:
994 magic-string@0.30.17: 1068 magic-string@0.30.17:
995 resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} 1069 resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
996 1070
1071 + math-intrinsics@1.1.0:
1072 + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
1073 + engines: {node: '>= 0.4'}
1074 +
997 merge2@1.4.1: 1075 merge2@1.4.1:
998 resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1076 resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
999 engines: {node: '>= 8'} 1077 engines: {node: '>= 8'}
...@@ -1002,6 +1080,14 @@ packages: ...@@ -1002,6 +1080,14 @@ packages:
1002 resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1080 resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
1003 engines: {node: '>=8.6'} 1081 engines: {node: '>=8.6'}
1004 1082
1083 + mime-db@1.52.0:
1084 + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
1085 + engines: {node: '>= 0.6'}
1086 +
1087 + mime-types@2.1.35:
1088 + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
1089 + engines: {node: '>= 0.6'}
1090 +
1005 minimatch@3.1.2: 1091 minimatch@3.1.2:
1006 resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1092 resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
1007 1093
...@@ -1152,6 +1238,9 @@ packages: ...@@ -1152,6 +1238,9 @@ packages:
1152 resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1238 resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
1153 engines: {node: '>= 0.8.0'} 1239 engines: {node: '>= 0.8.0'}
1154 1240
1241 + proxy-from-env@1.1.0:
1242 + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
1243 +
1155 punycode@2.3.1: 1244 punycode@2.3.1:
1156 resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1245 resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
1157 engines: {node: '>=6'} 1246 engines: {node: '>=6'}
...@@ -1921,6 +2010,8 @@ snapshots: ...@@ -1921,6 +2010,8 @@ snapshots:
1921 2010
1922 argparse@2.0.1: {} 2011 argparse@2.0.1: {}
1923 2012
2013 + asynckit@0.4.0: {}
2014 +
1924 autoprefixer@10.4.21(postcss@8.5.3): 2015 autoprefixer@10.4.21(postcss@8.5.3):
1925 dependencies: 2016 dependencies:
1926 browserslist: 4.24.4 2017 browserslist: 4.24.4
...@@ -1931,6 +2022,14 @@ snapshots: ...@@ -1931,6 +2022,14 @@ snapshots:
1931 postcss: 8.5.3 2022 postcss: 8.5.3
1932 postcss-value-parser: 4.2.0 2023 postcss-value-parser: 4.2.0
1933 2024
2025 + axios@1.8.4:
2026 + dependencies:
2027 + follow-redirects: 1.15.9
2028 + form-data: 4.0.2
2029 + proxy-from-env: 1.1.0
2030 + transitivePeerDependencies:
2031 + - debug
2032 +
1934 balanced-match@1.0.2: {} 2033 balanced-match@1.0.2: {}
1935 2034
1936 binary-extensions@2.3.0: {} 2035 binary-extensions@2.3.0: {}
...@@ -1957,6 +2056,11 @@ snapshots: ...@@ -1957,6 +2056,11 @@ snapshots:
1957 node-releases: 2.0.19 2056 node-releases: 2.0.19
1958 update-browserslist-db: 1.1.3(browserslist@4.24.4) 2057 update-browserslist-db: 1.1.3(browserslist@4.24.4)
1959 2058
2059 + call-bind-apply-helpers@1.0.2:
2060 + dependencies:
2061 + es-errors: 1.3.0
2062 + function-bind: 1.1.2
2063 +
1960 callsites@3.1.0: {} 2064 callsites@3.1.0: {}
1961 2065
1962 camelcase-css@2.0.1: {} 2066 camelcase-css@2.0.1: {}
...@@ -1986,6 +2090,10 @@ snapshots: ...@@ -1986,6 +2090,10 @@ snapshots:
1986 2090
1987 color-name@1.1.4: {} 2091 color-name@1.1.4: {}
1988 2092
2093 + combined-stream@1.0.8:
2094 + dependencies:
2095 + delayed-stream: 1.0.0
2096 +
1989 commander@4.1.1: {} 2097 commander@4.1.1: {}
1990 2098
1991 concat-map@0.0.1: {} 2099 concat-map@0.0.1: {}
...@@ -2008,10 +2116,18 @@ snapshots: ...@@ -2008,10 +2116,18 @@ snapshots:
2008 2116
2009 deep-is@0.1.4: {} 2117 deep-is@0.1.4: {}
2010 2118
2119 + delayed-stream@1.0.0: {}
2120 +
2011 didyoumean@1.2.2: {} 2121 didyoumean@1.2.2: {}
2012 2122
2013 dlv@1.1.3: {} 2123 dlv@1.1.3: {}
2014 2124
2125 + dunder-proto@1.0.1:
2126 + dependencies:
2127 + call-bind-apply-helpers: 1.0.2
2128 + es-errors: 1.3.0
2129 + gopd: 1.2.0
2130 +
2015 eastasianwidth@0.2.0: {} 2131 eastasianwidth@0.2.0: {}
2016 2132
2017 electron-to-chromium@1.5.137: {} 2133 electron-to-chromium@1.5.137: {}
...@@ -2022,6 +2138,21 @@ snapshots: ...@@ -2022,6 +2138,21 @@ snapshots:
2022 2138
2023 entities@4.5.0: {} 2139 entities@4.5.0: {}
2024 2140
2141 + es-define-property@1.0.1: {}
2142 +
2143 + es-errors@1.3.0: {}
2144 +
2145 + es-object-atoms@1.1.1:
2146 + dependencies:
2147 + es-errors: 1.3.0
2148 +
2149 + es-set-tostringtag@2.1.0:
2150 + dependencies:
2151 + es-errors: 1.3.0
2152 + get-intrinsic: 1.3.0
2153 + has-tostringtag: 1.0.2
2154 + hasown: 2.0.2
2155 +
2025 esbuild@0.21.5: 2156 esbuild@0.21.5:
2026 optionalDependencies: 2157 optionalDependencies:
2027 '@esbuild/aix-ppc64': 0.21.5 2158 '@esbuild/aix-ppc64': 0.21.5
...@@ -2186,11 +2317,20 @@ snapshots: ...@@ -2186,11 +2317,20 @@ snapshots:
2186 2317
2187 flatted@3.3.3: {} 2318 flatted@3.3.3: {}
2188 2319
2320 + follow-redirects@1.15.9: {}
2321 +
2189 foreground-child@3.3.1: 2322 foreground-child@3.3.1:
2190 dependencies: 2323 dependencies:
2191 cross-spawn: 7.0.6 2324 cross-spawn: 7.0.6
2192 signal-exit: 4.1.0 2325 signal-exit: 4.1.0
2193 2326
2327 + form-data@4.0.2:
2328 + dependencies:
2329 + asynckit: 0.4.0
2330 + combined-stream: 1.0.8
2331 + es-set-tostringtag: 2.1.0
2332 + mime-types: 2.1.35
2333 +
2194 fraction.js@4.3.7: {} 2334 fraction.js@4.3.7: {}
2195 2335
2196 fsevents@2.3.3: 2336 fsevents@2.3.3:
...@@ -2200,6 +2340,24 @@ snapshots: ...@@ -2200,6 +2340,24 @@ snapshots:
2200 2340
2201 gensync@1.0.0-beta.2: {} 2341 gensync@1.0.0-beta.2: {}
2202 2342
2343 + get-intrinsic@1.3.0:
2344 + dependencies:
2345 + call-bind-apply-helpers: 1.0.2
2346 + es-define-property: 1.0.1
2347 + es-errors: 1.3.0
2348 + es-object-atoms: 1.1.1
2349 + function-bind: 1.1.2
2350 + get-proto: 1.0.1
2351 + gopd: 1.2.0
2352 + has-symbols: 1.1.0
2353 + hasown: 2.0.2
2354 + math-intrinsics: 1.1.0
2355 +
2356 + get-proto@1.0.1:
2357 + dependencies:
2358 + dunder-proto: 1.0.1
2359 + es-object-atoms: 1.1.1
2360 +
2203 glob-parent@5.1.2: 2361 glob-parent@5.1.2:
2204 dependencies: 2362 dependencies:
2205 is-glob: 4.0.3 2363 is-glob: 4.0.3
...@@ -2225,8 +2383,16 @@ snapshots: ...@@ -2225,8 +2383,16 @@ snapshots:
2225 2383
2226 globals@14.0.0: {} 2384 globals@14.0.0: {}
2227 2385
2386 + gopd@1.2.0: {}
2387 +
2228 has-flag@4.0.0: {} 2388 has-flag@4.0.0: {}
2229 2389
2390 + has-symbols@1.1.0: {}
2391 +
2392 + has-tostringtag@1.0.2:
2393 + dependencies:
2394 + has-symbols: 1.1.0
2395 +
2230 hasown@2.0.2: 2396 hasown@2.0.2:
2231 dependencies: 2397 dependencies:
2232 function-bind: 1.1.2 2398 function-bind: 1.1.2
...@@ -2315,6 +2481,8 @@ snapshots: ...@@ -2315,6 +2481,8 @@ snapshots:
2315 dependencies: 2481 dependencies:
2316 '@jridgewell/sourcemap-codec': 1.5.0 2482 '@jridgewell/sourcemap-codec': 1.5.0
2317 2483
2484 + math-intrinsics@1.1.0: {}
2485 +
2318 merge2@1.4.1: {} 2486 merge2@1.4.1: {}
2319 2487
2320 micromatch@4.0.8: 2488 micromatch@4.0.8:
...@@ -2322,6 +2490,12 @@ snapshots: ...@@ -2322,6 +2490,12 @@ snapshots:
2322 braces: 3.0.3 2490 braces: 3.0.3
2323 picomatch: 2.3.1 2491 picomatch: 2.3.1
2324 2492
2493 + mime-db@1.52.0: {}
2494 +
2495 + mime-types@2.1.35:
2496 + dependencies:
2497 + mime-db: 1.52.0
2498 +
2325 minimatch@3.1.2: 2499 minimatch@3.1.2:
2326 dependencies: 2500 dependencies:
2327 brace-expansion: 1.1.11 2501 brace-expansion: 1.1.11
...@@ -2447,6 +2621,8 @@ snapshots: ...@@ -2447,6 +2621,8 @@ snapshots:
2447 2621
2448 prelude-ls@1.2.1: {} 2622 prelude-ls@1.2.1: {}
2449 2623
2624 + proxy-from-env@1.1.0: {}
2625 +
2450 punycode@2.3.1: {} 2626 punycode@2.3.1: {}
2451 2627
2452 queue-microtask@1.2.3: {} 2628 queue-microtask@1.2.3: {}
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
13 * @Description: 文件描述 13 * @Description: 文件描述
14 */ 14 */
15 <template> 15 <template>
16 + <AppProvider>
16 <div class="flex flex-col min-h-screen"> 17 <div class="flex flex-col min-h-screen">
17 <Header /> 18 <Header />
18 <main class="flex-grow"> 19 <main class="flex-grow">
...@@ -20,12 +21,14 @@ ...@@ -20,12 +21,14 @@
20 </main> 21 </main>
21 <Footer /> 22 <Footer />
22 </div> 23 </div>
24 + </AppProvider>
23 </template> 25 </template>
24 26
25 <script setup> 27 <script setup>
26 import { onMounted } from 'vue' 28 import { onMounted } from 'vue'
27 import Header from './components/layout/Header.vue' 29 import Header from './components/layout/Header.vue'
28 import Footer from './components/layout/Footer.vue' 30 import Footer from './components/layout/Footer.vue'
31 +import AppProvider from './providers/AppProvider.vue'
29 32
30 // 更新文档标题 33 // 更新文档标题
31 onMounted(() => { 34 onMounted(() => {
......
1 +<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
2 + <circle cx="64" cy="64" r="64" fill="#e0e0e0"/>
3 + <circle cx="64" cy="56" r="24" fill="#bdbdbd"/>
4 + <path d="M64 84c-16 0-48 8-48 24v20h96v-20c0-16-32-24-48-24z" fill="#bdbdbd"/>
5 +</svg>
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
42 <div class="relative"> 42 <div class="relative">
43 <button @click="toggleProfileDropdown" class="flex items-center space-x-2"> 43 <button @click="toggleProfileDropdown" class="flex items-center space-x-2">
44 <div class="h-8 w-8 rounded-full overflow-hidden border-2 border-green-500"> 44 <div class="h-8 w-8 rounded-full overflow-hidden border-2 border-green-500">
45 - <img :src="currentUser?.avatar || '/assets/images/avatars/default_avatar.png'" alt="User Avatar" class="h-full w-full object-cover" /> 45 + <img :src="currentUser?.avatar || '/src/assets/images/avatars/default_avatar.svg'" alt="User Avatar" class="h-full w-full object-cover" />
46 </div> 46 </div>
47 <span class="hidden lg:block text-sm font-medium text-gray-700">{{ currentUser?.name || 'User' }}</span> 47 <span class="hidden lg:block text-sm font-medium text-gray-700">{{ currentUser?.name || 'User' }}</span>
48 <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> 48 <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
19 </button> 19 </button>
20 </template> 20 </template>
21 21
22 -<script setup> 22 +<script>
23 import { computed } from 'vue' 23 import { computed } from 'vue'
24 24
25 const buttonVariants = { 25 const buttonVariants = {
...@@ -50,7 +50,10 @@ const buttonRounded = { ...@@ -50,7 +50,10 @@ const buttonRounded = {
50 50
51 const buttonBlock = 'w-full flex justify-center' 51 const buttonBlock = 'w-full flex justify-center'
52 52
53 -const props = defineProps({ 53 +const baseClasses = 'flex items-center justify-center font-medium border shadow-sm transition duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed'
54 +
55 +export default {
56 + props: {
54 variant: { 57 variant: {
55 type: String, 58 type: String,
56 default: 'primary', 59 default: 'primary',
...@@ -90,13 +93,20 @@ const props = defineProps({ ...@@ -90,13 +93,20 @@ const props = defineProps({
90 type: String, 93 type: String,
91 default: 'button' 94 default: 'button'
92 } 95 }
93 -}) 96 + },
94 - 97 + emits: ['click'],
95 -defineEmits(['click']) 98 + setup(props) {
96 - 99 + const variantClass = computed(() => buttonVariants[props.variant] || buttonVariants.primary)
97 -const baseClasses = 'flex items-center justify-center font-medium border shadow-sm transition duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed' 100 + const sizeClass = computed(() => buttonSizes[props.size] || buttonSizes.md)
101 + const roundedClass = computed(() => buttonRounded[props.rounded] || buttonRounded.md)
98 102
99 -const variantClass = computed(() => buttonVariants[props.variant] || buttonVariants.primary) 103 + return {
100 -const sizeClass = computed(() => buttonSizes[props.size] || buttonSizes.md) 104 + baseClasses,
101 -const roundedClass = computed(() => buttonRounded[props.rounded] || buttonRounded.md) 105 + variantClass,
106 + sizeClass,
107 + roundedClass,
108 + buttonBlock
109 + }
110 + }
111 +}
102 </script> 112 </script>
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
51 </div> 51 </div>
52 </template> 52 </template>
53 53
54 -<script setup> 54 +<script>
55 import { computed } from 'vue' 55 import { computed } from 'vue'
56 56
57 const inputSizes = { 57 const inputSizes = {
...@@ -60,7 +60,9 @@ const inputSizes = { ...@@ -60,7 +60,9 @@ const inputSizes = {
60 lg: 'px-4 py-3 text-lg' 60 lg: 'px-4 py-3 text-lg'
61 } 61 }
62 62
63 -const props = defineProps({ 63 +export default {
64 + name: 'Input',
65 + props: {
64 modelValue: { 66 modelValue: {
65 type: [String, Number], 67 type: [String, Number],
66 default: '' 68 default: ''
...@@ -114,10 +116,16 @@ const props = defineProps({ ...@@ -114,10 +116,16 @@ const props = defineProps({
114 type: [String, Object], 116 type: [String, Object],
115 default: null 117 default: null
116 } 118 }
117 -}) 119 + },
118 - 120 + emits: ['update:modelValue', 'blur'],
119 -defineEmits(['update:modelValue', 'blur']) 121 + setup(props) {
122 + const inputId = computed(() => `input-${props.name}`)
123 + const sizeClass = computed(() => inputSizes[props.size] || inputSizes.md)
120 124
121 -const inputId = computed(() => `input-${props.name}`) 125 + return {
122 -const sizeClass = computed(() => inputSizes[props.size] || inputSizes.md) 126 + inputId,
127 + sizeClass
128 + }
129 + }
130 +}
123 </script> 131 </script>
......
1 <script setup> 1 <script setup>
2 -import { ref, onMounted, onUnmounted, watch } from 'vue'; 2 +import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
3 +
4 +// Set sizes based on the size prop
5 +const sizeClasses = {
6 + sm: 'max-w-md',
7 + md: 'max-w-lg',
8 + lg: 'max-w-2xl',
9 + xl: 'max-w-4xl',
10 + full: 'max-w-full mx-4'
11 +};
3 12
4 const props = defineProps({ 13 const props = defineProps({
5 isOpen: { 14 isOpen: {
...@@ -33,15 +42,6 @@ const emit = defineEmits(['close']); ...@@ -33,15 +42,6 @@ const emit = defineEmits(['close']);
33 const modalRef = ref(null); 42 const modalRef = ref(null);
34 const isMounted = ref(false); 43 const isMounted = ref(false);
35 44
36 -// Set sizes based on the size prop
37 -const sizeClasses = {
38 - sm: 'max-w-md',
39 - md: 'max-w-lg',
40 - lg: 'max-w-2xl',
41 - xl: 'max-w-4xl',
42 - full: 'max-w-full mx-4'
43 -};
44 -
45 const modalSize = computed(() => sizeClasses[props.size] || sizeClasses.md); 45 const modalSize = computed(() => sizeClasses[props.size] || sizeClasses.md);
46 46
47 // Handle ESC key press 47 // Handle ESC key press
......
...@@ -21,6 +21,12 @@ ...@@ -21,6 +21,12 @@
21 </div> 21 </div>
22 </template> 22 </template>
23 23
24 +<script>
25 +// Define valid values for variant and size props
26 +const validVariants = ['underline', 'pills', 'bordered'];
27 +const validSizes = ['sm', 'md', 'lg'];
28 +</script>
29 +
24 <script setup> 30 <script setup>
25 import { ref, computed } from 'vue'; 31 import { ref, computed } from 'vue';
26 32
...@@ -39,13 +45,13 @@ const props = defineProps({ ...@@ -39,13 +45,13 @@ const props = defineProps({
39 }, 45 },
40 variant: { 46 variant: {
41 type: String, 47 type: String,
42 - default: 'underline', // 'underline', 'pills', 'bordered' 48 + default: 'underline',
43 - validator: (value) => ['underline', 'pills', 'bordered'].includes(value) 49 + validator: (value) => validVariants.includes(value)
44 }, 50 },
45 size: { 51 size: {
46 type: String, 52 type: String,
47 - default: 'md', // 'sm', 'md', 'lg' 53 + default: 'md',
48 - validator: (value) => ['sm', 'md', 'lg'].includes(value) 54 + validator: (value) => validSizes.includes(value)
49 } 55 }
50 }); 56 });
51 57
......
1 +{
2 + "activities": [
3 + {
4 + "id": "A0001",
5 + "title": "Vue.js 3.0 读书会",
6 + "description": "每周四晚上8点,我们一起学习Vue.js 3.0的新特性和最佳实践。",
7 + "start_time": "2024-04-18 20:00:00",
8 + "end_time": "2024-04-18 22:00:00",
9 + "location": "线上会议室",
10 + "max_participants": 20,
11 + "current_participants": 5,
12 + "organizer_id": "U0001",
13 + "organizer_name": "张三",
14 + "status": "upcoming",
15 + "is_public": true,
16 + "tags": [
17 + "Vue.js",
18 + "前端开发",
19 + "读书会"
20 + ],
21 + "requirements": "需要基本的JavaScript和Vue.js基础知识",
22 + "materials": [
23 + "Vue.js 3.0官方文档",
24 + "示例代码仓库"
25 + ],
26 + "created_at": "2024-04-10 10:00:00",
27 + "updated_at": "2024-04-10 10:00:00"
28 + }
29 + ]
30 +}
1 +{
2 + "messages": [
3 + {
4 + "id": "M0001",
5 + "sender_id": "system",
6 + "recipient_id": "U0001",
7 + "title": "活动提醒",
8 + "content": "您报名的Vue.js 3.0读书会将在明天晚上8点开始,请准时参加。",
9 + "type": "notification",
10 + "priority": "normal",
11 + "read_status": false,
12 + "created_at": "2024-04-17 10:00:00",
13 + "updated_at": "2024-04-17 10:00:00"
14 + }
15 + ]
16 +}
1 +{
2 + "registrations": [
3 + {
4 + "id": "R0001",
5 + "activity_id": "A0001",
6 + "user_id": "U0001",
7 + "registration_time": "2024-04-15 14:30:00",
8 + "status": "confirmed",
9 + "custom_fields": [
10 + {
11 + "field_name": "experience_level",
12 + "field_type": "select",
13 + "field_label": "Vue.js经验水平",
14 + "field_options": ["入门", "进阶", "专家"]
15 + }
16 + ],
17 + "custom_answers": {
18 + "experience_level": "进阶"
19 + },
20 + "notes": "期待参加读书会!",
21 + "created_at": "2024-04-15 14:30:00",
22 + "updated_at": "2024-04-15 14:30:00"
23 + }
24 + ]
25 +}
1 +{
2 + "users": [
3 + {
4 + "id": "U0001",
5 + "name": "张三",
6 + "email": "zhangsan@example.com",
7 + "avatar": "/assets/images/avatars/default.png",
8 + "role": "member",
9 + "created_at": "2024-01-01 00:00:00",
10 + "updated_at": "2024-01-01 00:00:00",
11 + "last_login": "2024-04-17 10:00:00",
12 + "status": "active",
13 + "preferences": {
14 + "notification_email": true,
15 + "notification_web": true
16 + }
17 + }
18 + ]
19 +}
...@@ -379,17 +379,22 @@ const submitRegistration = async () => { ...@@ -379,17 +379,22 @@ const submitRegistration = async () => {
379 onMounted(async () => { 379 onMounted(async () => {
380 try { 380 try {
381 const activityId = route.params.id 381 const activityId = route.params.id
382 - const response = await store.fetchActivity(activityId) 382 + const foundActivity = activities.value.find(a => a.id === activityId)
383 - activity.value = response 383 + if (foundActivity) {
384 - loading.value = false 384 + activity.value = foundActivity
385 -
386 // Check registration status 385 // Check registration status
387 - const registration = await store.checkRegistration(activityId) 386 + const registration = registrations.value.find(r => r.activity_id === activityId)
388 hasRegistered.value = registration !== null 387 hasRegistered.value = registration !== null
389 registrationStatus.value = registration?.status 388 registrationStatus.value = registration?.status
390 389
391 - // Fetch similar activities 390 + // Find similar activities
392 - similarActivities.value = await store.fetchSimilarActivities(activityId) 391 + similarActivities.value = activities.value
392 + .filter(a => a.id !== activityId && a.category === foundActivity.category)
393 + .slice(0, 3)
394 + } else {
395 + error.value = '活动不存在'
396 + }
397 + loading.value = false
393 } catch (err) { 398 } catch (err) {
394 error.value = err.message 399 error.value = err.message
395 loading.value = false 400 loading.value = false
......
...@@ -258,12 +258,16 @@ ...@@ -258,12 +258,16 @@
258 <script setup> 258 <script setup>
259 import { ref, onMounted, watch } from 'vue' 259 import { ref, onMounted, watch } from 'vue'
260 import { useRoute, useRouter } from 'vue-router' 260 import { useRoute, useRouter } from 'vue-router'
261 -import { useAppStore } from '../stores/app' 261 +import activitiesData from '../data/activities.json'
262 +import registrationsData from '../data/registrations.json'
263 +import usersData from '../data/users.json'
262 import Button from '../components/shared/Button.vue' 264 import Button from '../components/shared/Button.vue'
263 265
264 const route = useRoute() 266 const route = useRoute()
265 const router = useRouter() 267 const router = useRouter()
266 -const appStore = useAppStore() 268 +const activities = ref(activitiesData.activities)
269 +const registrations = ref(registrationsData.registrations)
270 +const currentUser = ref(usersData.users[0])
267 271
268 const activityId = route.params.activityId 272 const activityId = route.params.activityId
269 const activity = ref(null) 273 const activity = ref(null)
...@@ -280,21 +284,19 @@ const isSubmitting = ref(false) ...@@ -280,21 +284,19 @@ const isSubmitting = ref(false)
280 // Fetch activity details and user registration 284 // Fetch activity details and user registration
281 const fetchData = async () => { 285 const fetchData = async () => {
282 try { 286 try {
283 - if (!appStore.currentUser) { 287 + if (!currentUser.value) {
284 error.value = '请先登录' 288 error.value = '请先登录'
285 loading.value = false 289 loading.value = false
286 return 290 return
287 } 291 }
288 292
289 - if (appStore.activities.length > 0) { 293 + const foundActivity = activities.value.find(a => a.id === activityId)
290 - const foundActivity = appStore.getActivityById(activityId)
291 -
292 if (foundActivity) { 294 if (foundActivity) {
293 activity.value = foundActivity 295 activity.value = foundActivity
294 296
295 // Find user registration for this activity 297 // Find user registration for this activity
296 - const registration = appStore.registrations.find( 298 + const registration = registrations.value.find(
297 - reg => reg.activity_id === activityId && reg.user_id === appStore.currentUser.id 299 + reg => reg.activity_id === activityId && reg.user_id === currentUser.value.id
298 ) 300 )
299 301
300 if (registration) { 302 if (registration) {
...@@ -314,7 +316,7 @@ const fetchData = async () => { ...@@ -314,7 +316,7 @@ const fetchData = async () => {
314 } else { 316 } else {
315 error.value = '未找到活动信息' 317 error.value = '未找到活动信息'
316 } 318 }
317 - } 319 +
318 loading.value = false 320 loading.value = false
319 } catch (err) { 321 } catch (err) {
320 console.error('Failed to fetch data:', err) 322 console.error('Failed to fetch data:', err)
......
...@@ -86,12 +86,12 @@ ...@@ -86,12 +86,12 @@
86 </template> 86 </template>
87 87
88 <script setup> 88 <script setup>
89 -import { ref, computed, watchEffect } from 'vue' 89 +import { ref, watchEffect } from 'vue'
90 -import { useAppStore } from '../stores/app' 90 +import activitiesData from '../data/activities.json'
91 import ActivityCard from '../components/shared/ActivityCard.vue' 91 import ActivityCard from '../components/shared/ActivityCard.vue'
92 92
93 -const store = useAppStore() 93 +const activities = ref(activitiesData.activities)
94 -const { activities, loading } = store 94 +const loading = ref(false)
95 95
96 const upcomingActivities = ref([]) 96 const upcomingActivities = ref([])
97 const ongoingActivities = ref([]) 97 const ongoingActivities = ref([])
......
...@@ -169,13 +169,15 @@ ...@@ -169,13 +169,15 @@
169 <script setup> 169 <script setup>
170 import { ref, computed, onMounted } from 'vue' 170 import { ref, computed, onMounted } from 'vue'
171 import { useRoute, useRouter } from 'vue-router' 171 import { useRoute, useRouter } from 'vue-router'
172 -import { useAppStore } from '../stores/app' 172 +import activitiesData from '../data/activities.json'
173 +import registrationsData from '../data/registrations.json'
173 import Button from '../components/shared/Button.vue' 174 import Button from '../components/shared/Button.vue'
174 import Input from '../components/shared/Input.vue' 175 import Input from '../components/shared/Input.vue'
175 176
176 const route = useRoute() 177 const route = useRoute()
177 const router = useRouter() 178 const router = useRouter()
178 -const store = useAppStore() 179 +const activities = ref(activitiesData.activities)
180 +const registrations = ref(registrationsData.registrations)
179 181
180 const activityId = route.params.activityId 182 const activityId = route.params.activityId
181 const activity = ref(null) 183 const activity = ref(null)
...@@ -196,9 +198,7 @@ const formErrors = ref({}) ...@@ -196,9 +198,7 @@ const formErrors = ref({})
196 // Fetch activity details 198 // Fetch activity details
197 onMounted(async () => { 199 onMounted(async () => {
198 try { 200 try {
199 - if (store.activities.length > 0) { 201 + const foundActivity = activities.value.find(a => a.id === activityId)
200 - const foundActivity = store.getActivityById(activityId)
201 -
202 if (foundActivity) { 202 if (foundActivity) {
203 activity.value = foundActivity 203 activity.value = foundActivity
204 204
...@@ -214,7 +214,7 @@ onMounted(async () => { ...@@ -214,7 +214,7 @@ onMounted(async () => {
214 } else { 214 } else {
215 error.value = '未找到活动信息' 215 error.value = '未找到活动信息'
216 } 216 }
217 - } 217 +
218 loading.value = false 218 loading.value = false
219 } catch (err) { 219 } catch (err) {
220 console.error('Failed to fetch activity details:', err) 220 console.error('Failed to fetch activity details:', err)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
17 <div class="flex flex-col md:flex-row items-center"> 17 <div class="flex flex-col md:flex-row items-center">
18 <div 18 <div
19 class="h-24 w-24 md:h-32 md:w-32 rounded-full overflow-hidden border-4 border-white mb-4 md:mb-0 md:mr-6"> 19 class="h-24 w-24 md:h-32 md:w-32 rounded-full overflow-hidden border-4 border-white mb-4 md:mb-0 md:mr-6">
20 - <img :src="currentUser.avatar || '/assets/images/avatars/default_avatar.png'" 20 + <img :src="currentUser.avatar || '/src/assets/images/avatars/default_avatar.svg'"
21 :alt="currentUser.name" class="h-full w-full object-cover" /> 21 :alt="currentUser.name" class="h-full w-full object-cover" />
22 </div> 22 </div>
23 <div class="text-center md:text-left"> 23 <div class="text-center md:text-left">
......
1 import { defineStore } from 'pinia' 1 import { defineStore } from 'pinia'
2 import { ref, computed } from 'vue' 2 import { ref, computed } from 'vue'
3 +import usersData from '../data/users.json'
4 +import activitiesData from '../data/activities.json'
5 +import registrationsData from '../data/registrations.json'
6 +import messagesData from '../data/messages.json'
3 7
4 export const useAppStore = defineStore('app', () => { 8 export const useAppStore = defineStore('app', () => {
5 const currentUser = ref(null) 9 const currentUser = ref(null)
...@@ -10,29 +14,21 @@ export const useAppStore = defineStore('app', () => { ...@@ -10,29 +14,21 @@ export const useAppStore = defineStore('app', () => {
10 const userMessages = ref([]) 14 const userMessages = ref([])
11 15
12 // 初始化应用数据 16 // 初始化应用数据
13 - async function fetchInitialData() { 17 + function fetchInitialData() {
14 try { 18 try {
15 loading.value = true 19 loading.value = true
16 20
17 // 获取用户数据 21 // 获取用户数据
18 - const usersResponse = await fetch('/data/users.json') 22 + currentUser.value = usersData.users[0]
19 - const usersData = await usersResponse.json()
20 - currentUser.value = usersData[0]
21 23
22 // 获取活动数据 24 // 获取活动数据
23 - const activitiesResponse = await fetch('/data/activities.json') 25 + activities.value = activitiesData.activities
24 - const activitiesData = await activitiesResponse.json()
25 - activities.value = activitiesData
26 26
27 // 获取报名数据 27 // 获取报名数据
28 - const registrationsResponse = await fetch('/data/registrations.json') 28 + registrations.value = registrationsData.registrations
29 - const registrationsData = await registrationsResponse.json()
30 - registrations.value = registrationsData
31 29
32 // 获取消息数据 30 // 获取消息数据
33 - const messagesResponse = await fetch('/data/messages.json') 31 + userMessages.value = messagesData.messages
34 - const messagesData = await messagesResponse.json()
35 - userMessages.value = messagesData
36 32
37 loading.value = false 33 loading.value = false
38 } catch (err) { 34 } catch (err) {
......
1 +import axios from 'axios'
2 +
3 +// 创建axios实例
4 +const instance = axios.create({
5 + baseURL: '/src/data', // 基础URL,根据实际环境配置
6 + timeout: 10000, // 请求超时时间
7 + headers: {
8 + 'Content-Type': 'application/json',
9 + },
10 +})
11 +
12 +// 请求拦截器
13 +instance.interceptors.request.use(
14 + (config) => {
15 + // 在发送请求之前做些什么
16 + // 例如:添加token
17 + // const token = localStorage.getItem('token');
18 + // if (token) {
19 + // config.headers.Authorization = `Bearer ${token}`;
20 + // }
21 + return config
22 + },
23 + (error) => {
24 + // 对请求错误做些什么
25 + console.error('Request error:', error)
26 + return Promise.reject(error)
27 + },
28 +)
29 +
30 +// 响应拦截器
31 +instance.interceptors.response.use(
32 + (response) => {
33 + // 对响应数据做点什么
34 + return response.data
35 + },
36 + (error) => {
37 + // 对响应错误做点什么
38 + console.error('Response error:', error)
39 + if (error.response) {
40 + switch (error.response.status) {
41 + case 401:
42 + // 未授权处理
43 + break
44 + case 404:
45 + // 资源不存在处理
46 + break
47 + case 500:
48 + // 服务器错误处理
49 + break
50 + default:
51 + break
52 + }
53 + }
54 + return Promise.reject(error)
55 + },
56 +)
57 +
58 +export default instance