refactor(components): 替换Tabs组件为内联实现
在ActivityDetail.vue和UserProfile.vue中,将Tabs组件替换为内联实现,以提高代码的可读性和维护性。同时修复了路径中的空格问题,并调整了路由参数的命名。
Showing
6 changed files
with
80 additions
and
42 deletions
| ... | @@ -10,7 +10,6 @@ | ... | @@ -10,7 +10,6 @@ |
| 10 | "preview": "vite preview" | 10 | "preview": "vite preview" |
| 11 | }, | 11 | }, |
| 12 | "dependencies": { | 12 | "dependencies": { |
| 13 | - "@vitejs/plugin-vue-jsx": "4.1.2", | ||
| 14 | "axios": "^1.8.4", | 13 | "axios": "^1.8.4", |
| 15 | "pinia": "^2.1.7", | 14 | "pinia": "^2.1.7", |
| 16 | "vue": "^3.4.21", | 15 | "vue": "^3.4.21", |
| ... | @@ -18,6 +17,7 @@ | ... | @@ -18,6 +17,7 @@ |
| 18 | }, | 17 | }, |
| 19 | "devDependencies": { | 18 | "devDependencies": { |
| 20 | "@vitejs/plugin-vue": "^5.0.4", | 19 | "@vitejs/plugin-vue": "^5.0.4", |
| 20 | + "@vitejs/plugin-vue-jsx": "4.1.2", | ||
| 21 | "@vue/compiler-sfc": "^3.4.21", | 21 | "@vue/compiler-sfc": "^3.4.21", |
| 22 | "autoprefixer": "^10.4.20", | 22 | "autoprefixer": "^10.4.20", |
| 23 | "eslint": "^9.9.0", | 23 | "eslint": "^9.9.0", | ... | ... |
| ... | @@ -8,9 +8,6 @@ importers: | ... | @@ -8,9 +8,6 @@ importers: |
| 8 | 8 | ||
| 9 | .: | 9 | .: |
| 10 | dependencies: | 10 | dependencies: |
| 11 | - '@vitejs/plugin-vue-jsx': | ||
| 12 | - specifier: 4.1.2 | ||
| 13 | - version: 4.1.2(vite@5.4.18)(vue@3.5.13) | ||
| 14 | axios: | 11 | axios: |
| 15 | specifier: ^1.8.4 | 12 | specifier: ^1.8.4 |
| 16 | version: 1.8.4 | 13 | version: 1.8.4 |
| ... | @@ -27,6 +24,9 @@ importers: | ... | @@ -27,6 +24,9 @@ importers: |
| 27 | '@vitejs/plugin-vue': | 24 | '@vitejs/plugin-vue': |
| 28 | specifier: ^5.0.4 | 25 | specifier: ^5.0.4 |
| 29 | version: 5.2.3(vite@5.4.18)(vue@3.5.13) | 26 | version: 5.2.3(vite@5.4.18)(vue@3.5.13) |
| 27 | + '@vitejs/plugin-vue-jsx': | ||
| 28 | + specifier: 4.1.2 | ||
| 29 | + version: 4.1.2(vite@5.4.18)(vue@3.5.13) | ||
| 30 | '@vue/compiler-sfc': | 30 | '@vue/compiler-sfc': |
| 31 | specifier: ^3.4.21 | 31 | specifier: ^3.4.21 |
| 32 | version: 3.5.13 | 32 | version: 3.5.13 | ... | ... |
| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | ||
| 17 | <!-- Tab content --> | 17 | <!-- Tab content --> |
| 18 | <div class="pt-4"> | 18 | <div class="pt-4"> |
| 19 | - <component :is="tabs[currentTab]?.content" /> | 19 | + <component :is="tabs[currentTab]?.component" /> |
| 20 | </div> | 20 | </div> |
| 21 | </div> | 21 | </div> |
| 22 | </template> | 22 | </template> | ... | ... |
| 1 | +/* | ||
| 2 | + * @Date: 2025-04-17 14:26:17 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-21 13:26:32 | ||
| 5 | + * @FilePath: /mlaj-reading-club/src/main.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 1 | import { createApp } from 'vue' | 8 | import { createApp } from 'vue' |
| 2 | import { createPinia } from 'pinia' | 9 | import { createPinia } from 'pinia' |
| 3 | import { createRouter, createWebHistory } from 'vue-router' | 10 | import { createRouter, createWebHistory } from 'vue-router' |
| ... | @@ -16,7 +23,7 @@ const router = createRouter({ | ... | @@ -16,7 +23,7 @@ const router = createRouter({ |
| 16 | history: createWebHistory(), | 23 | history: createWebHistory(), |
| 17 | routes: [ | 24 | routes: [ |
| 18 | { path: '/', component: () => import('./pages/HomePage.vue') }, | 25 | { path: '/', component: () => import('./pages/HomePage.vue') }, |
| 19 | - { path: '/activity/:activityId', component: () => import('./pages/ActivityDetail.vue') }, | 26 | + { path: '/activity/:id', component: () => import('./pages/ActivityDetail.vue') }, |
| 20 | { path: '/create-activity', component: () => import('./pages/CreateActivity.vue') }, | 27 | { path: '/create-activity', component: () => import('./pages/CreateActivity.vue') }, |
| 21 | { path: '/profile', component: () => import('./pages/UserProfile.vue') }, | 28 | { path: '/profile', component: () => import('./pages/UserProfile.vue') }, |
| 22 | { path: '/registration/:activityId', component: () => import('./pages/Registration.vue') }, | 29 | { path: '/registration/:activityId', component: () => import('./pages/Registration.vue') }, | ... | ... |
| ... | @@ -75,7 +75,64 @@ | ... | @@ -75,7 +75,64 @@ |
| 75 | </div> | 75 | </div> |
| 76 | 76 | ||
| 77 | <!-- Activity Tabs --> | 77 | <!-- Activity Tabs --> |
| 78 | - <Tabs :tabs="tabs" /> | 78 | + <div> |
| 79 | + <!-- Tab headers --> | ||
| 80 | + <div class="flex border-b border-gray-200"> | ||
| 81 | + <button v-for="(tab, index) in tabs" :key="index" | ||
| 82 | + class="text-base py-2 px-4 font-medium transition-all duration-200 focus:outline-none border-b-2" | ||
| 83 | + :class="currentTab === index | ||
| 84 | + ? 'border-green-500 text-green-600' | ||
| 85 | + : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'" | ||
| 86 | + @click="currentTab = index" role="tab" :aria-selected="currentTab === index"> | ||
| 87 | + {{ tab.label }} | ||
| 88 | + </button> | ||
| 89 | + </div> | ||
| 90 | + | ||
| 91 | + <!-- Tab content --> | ||
| 92 | + <div class="pt-4"> | ||
| 93 | + <div v-if="tabs[currentTab].label === '活动详情'"> | ||
| 94 | + <div class="space-y-4"> | ||
| 95 | + <div v-for="(paragraph, idx) in activity.description.split('\n')" :key="idx" | ||
| 96 | + class="mb-4"> | ||
| 97 | + {{ paragraph }} | ||
| 98 | + </div> | ||
| 99 | + </div> | ||
| 100 | + </div> | ||
| 101 | + <div v-if="tabs[currentTab].label === '参与须知'"> | ||
| 102 | + <div class="space-y-4"> | ||
| 103 | + <h3 class="font-medium text-lg">参与须知</h3> | ||
| 104 | + <ul class="list-disc pl-5 space-y-2"> | ||
| 105 | + <li>请准时到达活动地点或登录线上会议</li> | ||
| 106 | + <li>请提前阅读相关书籍或材料</li> | ||
| 107 | + <li>活动开始后,请将手机调至静音模式</li> | ||
| 108 | + <li>尊重他人发言,不打断他人</li> | ||
| 109 | + <li>可携带笔记本进行记录</li> | ||
| 110 | + <li>如需取消参与,请提前24小时通知主办方</li> | ||
| 111 | + </ul> | ||
| 112 | + </div> | ||
| 113 | + </div> | ||
| 114 | + <div v-if="tabs[currentTab].label === '常见问题'"> | ||
| 115 | + | ||
| 116 | + <div class="space-y-6"> | ||
| 117 | + <div> | ||
| 118 | + <h4 class="font-medium text-gray-900">如何取消报名?</h4> | ||
| 119 | + <p class="mt-2 text-gray-600"> | ||
| 120 | + 您可以在"我的活动"页面找到已报名的活动,点击"取消报名"按钮即可。请注意,活动开始前24小时内取消将无法获得退款。</p> | ||
| 121 | + </div> | ||
| 122 | + <div> | ||
| 123 | + <h4 class="font-medium text-gray-900">活动材料如何获取?</h4> | ||
| 124 | + <p class="mt-2 text-gray-600">报名成功后,您将在"我的活动"页面看到活动详情,相关材料可在页面底部下载或通过邮件接收。 | ||
| 125 | + </p> | ||
| 126 | + </div> | ||
| 127 | + <div> | ||
| 128 | + <h4 class="font-medium text-gray-900">线上活动如何参加?</h4> | ||
| 129 | + <p class="mt-2 text-gray-600"> | ||
| 130 | + 线上活动将在活动开始前30分钟发送会议链接到您的邮箱和手机短信,您也可以在"我的活动"页面找到入口链接。</p> | ||
| 131 | + </div> | ||
| 132 | + </div> | ||
| 133 | + </div> | ||
| 134 | + </div> | ||
| 135 | + </div> | ||
| 79 | </div> | 136 | </div> |
| 80 | 137 | ||
| 81 | <!-- Sidebar --> | 138 | <!-- Sidebar --> |
| ... | @@ -226,13 +283,17 @@ | ... | @@ -226,13 +283,17 @@ |
| 226 | </template> | 283 | </template> |
| 227 | 284 | ||
| 228 | <script setup> | 285 | <script setup> |
| 229 | -import { ref, computed, onMounted } from 'vue' | 286 | +import { ref, computed, onMounted, h, defineComponent } from 'vue' |
| 230 | import { useRoute, useRouter } from 'vue-router' | 287 | import { useRoute, useRouter } from 'vue-router' |
| 231 | import { useAppStore } from '../stores/app' | 288 | import { useAppStore } from '../stores/app' |
| 232 | import Button from '../components/shared/Button.vue' | 289 | import Button from '../components/shared/Button.vue' |
| 233 | import Modal from '../components/shared/Modal.vue' | 290 | import Modal from '../components/shared/Modal.vue' |
| 234 | -import Tabs from '../components/shared/Tabs.vue' | ||
| 235 | import ActivityCard from '../components/shared/ActivityCard.vue' | 291 | import ActivityCard from '../components/shared/ActivityCard.vue' |
| 292 | +import activitiesData from '../data/activities.json' | ||
| 293 | +import registrationsData from '../data/registrations.json' | ||
| 294 | + | ||
| 295 | +const activities = ref(activitiesData.activities) | ||
| 296 | +const registrations = ref(registrationsData.registrations) | ||
| 236 | 297 | ||
| 237 | const route = useRoute() | 298 | const route = useRoute() |
| 238 | const router = useRouter() | 299 | const router = useRouter() |
| ... | @@ -246,6 +307,7 @@ const showRegisterModal = ref(false) | ... | @@ -246,6 +307,7 @@ const showRegisterModal = ref(false) |
| 246 | const similarActivities = ref([]) | 307 | const similarActivities = ref([]) |
| 247 | const hasRegistered = ref(false) | 308 | const hasRegistered = ref(false) |
| 248 | const registrationStatus = ref(null) | 309 | const registrationStatus = ref(null) |
| 310 | +const currentTab = ref(0) | ||
| 249 | 311 | ||
| 250 | // Computed | 312 | // Computed |
| 251 | const activityStatus = computed(() => { | 313 | const activityStatus = computed(() => { |
| ... | @@ -305,44 +367,13 @@ const registrationStatusBadge = computed(() => { | ... | @@ -305,44 +367,13 @@ const registrationStatusBadge = computed(() => { |
| 305 | const tabs = computed(() => [ | 367 | const tabs = computed(() => [ |
| 306 | { | 368 | { |
| 307 | label: '活动详情', | 369 | label: '活动详情', |
| 308 | - content: activity.value?.description.split('\n').map((paragraph, idx) => ( | ||
| 309 | - `<p key="${idx}" class="mb-4">${paragraph}</p>` | ||
| 310 | - )).join('') | ||
| 311 | }, | 370 | }, |
| 312 | { | 371 | { |
| 313 | label: '参与须知', | 372 | label: '参与须知', |
| 314 | - content: ` | ||
| 315 | - <h3 class="font-medium text-lg mb-4">参与须知</h3> | ||
| 316 | - <ul class="list-disc pl-5 space-y-2"> | ||
| 317 | - <li>请准时到达活动地点或登录线上会议</li> | ||
| 318 | - <li>请提前阅读相关书籍或材料</li> | ||
| 319 | - <li>活动开始后,请将手机调至静音模式</li> | ||
| 320 | - <li>尊重他人发言,不打断他人</li> | ||
| 321 | - <li>可携带笔记本进行记录</li> | ||
| 322 | - <li>如需取消参与,请提前24小时通知主办方</li> | ||
| 323 | - </ul> | ||
| 324 | - ` | ||
| 325 | }, | 373 | }, |
| 326 | { | 374 | { |
| 327 | label: '常见问题', | 375 | label: '常见问题', |
| 328 | - content: ` | 376 | + } |
| 329 | - <div className="py-4"> | ||
| 330 | - <div className="space-y-6"> | ||
| 331 | - <div> | ||
| 332 | - <h4 className="font-medium text-gray-900">如何取消报名?</h4> | ||
| 333 | - <p className="mt-2 text-gray-600">您可以在"我的活动"页面找到已报名的活动,点击"取消报名"按钮即可。请注意,活动开始前24小时内取消将无法获得退款。</p> | ||
| 334 | - </div> | ||
| 335 | - <div> | ||
| 336 | - <h4 className="font-medium text-gray-900">活动材料如何获取?</h4> | ||
| 337 | - <p className="mt-2 text-gray-600">报名成功后,您将在"我的活动"页面看到活动详情,相关材料可在页面底部下载或通过邮件接收。</p> | ||
| 338 | - </div> | ||
| 339 | - <div> | ||
| 340 | - <h4 className="font-medium text-gray-900">线上活动如何参加?</h4> | ||
| 341 | - <p className="mt-2 text-gray-600">线上活动将在活动开始前30分钟发送会议链接到您的邮箱和手机短信,您也可以在"我的活动"页面找到入口链接。</p> | ||
| 342 | - </div> | ||
| 343 | - </div> | ||
| 344 | - </div> | ||
| 345 | - `} | ||
| 346 | ]) | 377 | ]) |
| 347 | 378 | ||
| 348 | // Functions | 379 | // Functions |
| ... | @@ -351,7 +382,7 @@ const goBack = () => { | ... | @@ -351,7 +382,7 @@ const goBack = () => { |
| 351 | } | 382 | } |
| 352 | 383 | ||
| 353 | const getActivityImage = (activityId) => { | 384 | const getActivityImage = (activityId) => { |
| 354 | - return `/ assets / images / activities / ${activityId}.jpg` | 385 | + return `/assets/images/activities/${activityId}.jpg` |
| 355 | } | 386 | } |
| 356 | 387 | ||
| 357 | const formatDate = (dateString) => { | 388 | const formatDate = (dateString) => { | ... | ... |
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment