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"
......
This diff is collapsed. Click to expand it.
...@@ -13,19 +13,22 @@ ...@@ -13,19 +13,22 @@
13 * @Description: 文件描述 13 * @Description: 文件描述
14 */ 14 */
15 <template> 15 <template>
16 - <div class="flex flex-col min-h-screen"> 16 + <AppProvider>
17 - <Header /> 17 + <div class="flex flex-col min-h-screen">
18 - <main class="flex-grow"> 18 + <Header />
19 - <router-view></router-view> 19 + <main class="flex-grow">
20 - </main> 20 + <router-view></router-view>
21 - <Footer /> 21 + </main>
22 - </div> 22 + <Footer />
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,53 +50,63 @@ const buttonRounded = { ...@@ -50,53 +50,63 @@ 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({
54 - variant: {
55 - type: String,
56 - default: 'primary',
57 - validator: (value) => Object.keys(buttonVariants).includes(value)
58 - },
59 - size: {
60 - type: String,
61 - default: 'md',
62 - validator: (value) => Object.keys(buttonSizes).includes(value)
63 - },
64 - rounded: {
65 - type: String,
66 - default: 'md',
67 - validator: (value) => Object.keys(buttonRounded).includes(value)
68 - },
69 - block: {
70 - type: Boolean,
71 - default: false
72 - },
73 - disabled: {
74 - type: Boolean,
75 - default: false
76 - },
77 - className: {
78 - type: String,
79 - default: ''
80 - },
81 - leftIcon: {
82 - type: [String, Object],
83 - default: null
84 - },
85 - rightIcon: {
86 - type: [String, Object],
87 - default: null
88 - },
89 - type: {
90 - type: String,
91 - default: 'button'
92 - }
93 -})
94 -
95 -defineEmits(['click'])
96 -
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' 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'
98 54
99 -const variantClass = computed(() => buttonVariants[props.variant] || buttonVariants.primary) 55 +export default {
100 -const sizeClass = computed(() => buttonSizes[props.size] || buttonSizes.md) 56 + props: {
101 -const roundedClass = computed(() => buttonRounded[props.rounded] || buttonRounded.md) 57 + variant: {
58 + type: String,
59 + default: 'primary',
60 + validator: (value) => Object.keys(buttonVariants).includes(value)
61 + },
62 + size: {
63 + type: String,
64 + default: 'md',
65 + validator: (value) => Object.keys(buttonSizes).includes(value)
66 + },
67 + rounded: {
68 + type: String,
69 + default: 'md',
70 + validator: (value) => Object.keys(buttonRounded).includes(value)
71 + },
72 + block: {
73 + type: Boolean,
74 + default: false
75 + },
76 + disabled: {
77 + type: Boolean,
78 + default: false
79 + },
80 + className: {
81 + type: String,
82 + default: ''
83 + },
84 + leftIcon: {
85 + type: [String, Object],
86 + default: null
87 + },
88 + rightIcon: {
89 + type: [String, Object],
90 + default: null
91 + },
92 + type: {
93 + type: String,
94 + default: 'button'
95 + }
96 + },
97 + emits: ['click'],
98 + setup(props) {
99 + const variantClass = computed(() => buttonVariants[props.variant] || buttonVariants.primary)
100 + const sizeClass = computed(() => buttonSizes[props.size] || buttonSizes.md)
101 + const roundedClass = computed(() => buttonRounded[props.rounded] || buttonRounded.md)
102 +
103 + return {
104 + baseClasses,
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,64 +60,72 @@ const inputSizes = { ...@@ -60,64 +60,72 @@ 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 - modelValue: { 64 + name: 'Input',
65 - type: [String, Number], 65 + props: {
66 - default: '' 66 + modelValue: {
67 + type: [String, Number],
68 + default: ''
69 + },
70 + label: {
71 + type: String,
72 + default: ''
73 + },
74 + name: {
75 + type: String,
76 + required: true
77 + },
78 + type: {
79 + type: String,
80 + default: 'text'
81 + },
82 + placeholder: {
83 + type: String,
84 + default: ''
85 + },
86 + error: {
87 + type: String,
88 + default: ''
89 + },
90 + size: {
91 + type: String,
92 + default: 'md',
93 + validator: (value) => Object.keys(inputSizes).includes(value)
94 + },
95 + required: {
96 + type: Boolean,
97 + default: false
98 + },
99 + disabled: {
100 + type: Boolean,
101 + default: false
102 + },
103 + className: {
104 + type: String,
105 + default: ''
106 + },
107 + helperText: {
108 + type: String,
109 + default: ''
110 + },
111 + leftIcon: {
112 + type: [String, Object],
113 + default: null
114 + },
115 + rightIcon: {
116 + type: [String, Object],
117 + default: null
118 + }
67 }, 119 },
68 - label: { 120 + emits: ['update:modelValue', 'blur'],
69 - type: String, 121 + setup(props) {
70 - default: '' 122 + const inputId = computed(() => `input-${props.name}`)
71 - }, 123 + const sizeClass = computed(() => inputSizes[props.size] || inputSizes.md)
72 - name: {
73 - type: String,
74 - required: true
75 - },
76 - type: {
77 - type: String,
78 - default: 'text'
79 - },
80 - placeholder: {
81 - type: String,
82 - default: ''
83 - },
84 - error: {
85 - type: String,
86 - default: ''
87 - },
88 - size: {
89 - type: String,
90 - default: 'md',
91 - validator: (value) => Object.keys(inputSizes).includes(value)
92 - },
93 - required: {
94 - type: Boolean,
95 - default: false
96 - },
97 - disabled: {
98 - type: Boolean,
99 - default: false
100 - },
101 - className: {
102 - type: String,
103 - default: ''
104 - },
105 - helperText: {
106 - type: String,
107 - default: ''
108 - },
109 - leftIcon: {
110 - type: [String, Object],
111 - default: null
112 - },
113 - rightIcon: {
114 - type: [String, Object],
115 - default: null
116 - }
117 -})
118 124
119 -defineEmits(['update:modelValue', 'blur']) 125 + return {
120 - 126 + inputId,
121 -const inputId = computed(() => `input-${props.name}`) 127 + sizeClass
122 -const sizeClass = computed(() => inputSizes[props.size] || inputSizes.md) 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 + activity.value = foundActivity
385 + // Check registration status
386 + const registration = registrations.value.find(r => r.activity_id === activityId)
387 + hasRegistered.value = registration !== null
388 + registrationStatus.value = registration?.status
389 +
390 + // Find similar activities
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 + }
384 loading.value = false 397 loading.value = false
385 -
386 - // Check registration status
387 - const registration = await store.checkRegistration(activityId)
388 - hasRegistered.value = registration !== null
389 - registrationStatus.value = registration?.status
390 -
391 - // Fetch similar activities
392 - similarActivities.value = await store.fetchSimilarActivities(activityId)
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,22 +284,20 @@ const isSubmitting = ref(false) ...@@ -280,22 +284,20 @@ 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) 294 + if (foundActivity) {
295 + activity.value = foundActivity
291 296
292 - if (foundActivity) { 297 + // Find user registration for this activity
293 - activity.value = foundActivity 298 + const registration = registrations.value.find(
294 - 299 + reg => reg.activity_id === activityId && reg.user_id === currentUser.value.id
295 - // Find user registration for this activity 300 + )
296 - const registration = appStore.registrations.find(
297 - reg => reg.activity_id === activityId && reg.user_id === appStore.currentUser.id
298 - )
299 301
300 if (registration) { 302 if (registration) {
301 userRegistration.value = registration 303 userRegistration.value = 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,10 +198,8 @@ const formErrors = ref({}) ...@@ -196,10 +198,8 @@ 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) 202 + if (foundActivity) {
201 -
202 - if (foundActivity) {
203 activity.value = foundActivity 203 activity.value = foundActivity
204 204
205 // Pre-fill form with user data if available 205 // Pre-fill form with user data if available
...@@ -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