hookehuyr

feat(router): 添加历史足迹页面路由和视图组件

添加新的历史足迹页面路由'/recall',并创建对应的视图组件Index.vue
组件包含用户头像、欢迎语、加入时间统计等信息
移除vite配置中未使用的postcss插件配置
...@@ -97,6 +97,12 @@ export const routes = [ ...@@ -97,6 +97,12 @@ export const routes = [
97 meta: { title: '我的活动' }, 97 meta: { title: '我的活动' },
98 }, 98 },
99 { 99 {
100 + path: '/recall',
101 + name: 'Recall',
102 + component: () => import('../views/recall/Index.vue'),
103 + meta: { title: '历史足迹' },
104 + },
105 + {
100 path: '/checkout', 106 path: '/checkout',
101 name: 'CheckoutPage', 107 name: 'CheckoutPage',
102 component: () => import('../views/checkout/CheckoutPage.vue'), 108 component: () => import('../views/checkout/CheckoutPage.vue'),
......
1 +<!--
2 + * @Date: 2025-12-19 15:40:34
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-12-19 16:00:08
5 + * @FilePath: /mlaj/src/views/recall/Index.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div class="min-h-screen bg-[#F0FBF9] flex flex-col items-center pt-20 pb-10 px-6 relative overflow-hidden">
10 + <!-- 头像 -->
11 + <div class="relative mb-6">
12 + <img
13 + :src="userAvatar || defaultAvatar"
14 + class="w-24 h-24 rounded-full border-4 border-white shadow-lg object-cover"
15 + alt="User Avatar"
16 + />
17 + </div>
18 +
19 + <!-- 欢迎语 -->
20 + <h1 class="text-2xl font-bold text-[#1A3B34] mb-2">{{ userName }}</h1>
21 + <h2 class="text-xl font-bold text-[#1A3B34] mb-4">欢迎回归美乐爱觉宇宙</h2>
22 + <p class="text-slate-500 text-sm mb-12">您与Behalo的故事从这里开始</p>
23 +
24 + <!-- 时间卡片 -->
25 + <div class="bg-white rounded-3xl p-8 shadow-xl w-full max-w-sm text-center mb-auto relative z-10">
26 + <p class="text-slate-500 mb-4">您加入Behalo的时间</p>
27 + <div class="text-3xl font-bold text-[#1A3B34] mb-4 tracking-wide">{{ joinDateFormatted }}</div>
28 + <div class="text-slate-500">
29 + 已有 <span class="text-[#1A3B34] font-bold text-lg">{{ durationString }}</span>
30 + </div>
31 + </div>
32 +
33 + <!-- 底部引导 -->
34 + <div class="flex flex-col items-center mt-12 animate-bounce cursor-pointer">
35 + <ChevronDoubleDownIcon class="w-6 h-6 text-[#4ADE80] mb-2" />
36 + <span class="text-[#4ADE80] font-medium text-sm">向上滑动,探索更多历程</span>
37 + </div>
38 + </div>
39 +</template>
40 +
41 +<script setup>
42 +import { computed, onMounted } from 'vue';
43 +import { useAuth } from '@/contexts/auth';
44 +import { ChevronDoubleDownIcon } from '@heroicons/vue/24/solid';
45 +import dayjs from 'dayjs';
46 +
47 +// 状态
48 +const { currentUser } = useAuth();
49 +// 使用一个通用的默认头像URL,实际项目中应替换为本地资源或配置的默认图
50 +const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/default_avatar.png';
51 +
52 +const userAvatar = computed(() => {
53 + let avatar = currentUser.value?.avatar;
54 + if (avatar && avatar.includes('cdn.ipadbiz.cn')) {
55 + avatar += '?imageMogr2/thumbnail/200x/strip/quality/70';
56 + }
57 + return avatar;
58 +});
59 +
60 +const userName = computed(() => currentUser.value?.name || '旅行者');
61 +
62 +// 加入时间逻辑
63 +// 优先使用 created_at,如果没有则尝试 reg_time,最后回退到当前时间(防止报错)
64 +const joinDate = computed(() => {
65 + return currentUser.value?.created_at || currentUser.value?.reg_time || new Date();
66 +});
67 +
68 +const joinDateFormatted = computed(() => {
69 + return dayjs(joinDate.value).format('YYYY年M月D日');
70 +});
71 +
72 +const durationString = computed(() => {
73 + const start = dayjs(joinDate.value);
74 + const now = dayjs();
75 + const years = now.diff(start, 'year');
76 + const months = now.diff(start, 'month') % 12;
77 +
78 + // 如果不满一个月,显示天数
79 + if (years === 0 && months === 0) {
80 + const days = now.diff(start, 'day');
81 + return `${days} 天`;
82 + }
83 +
84 + if (years > 0) {
85 + return `${years} 年 ${months} 个月`;
86 + } else {
87 + return `${months} 个月`;
88 + }
89 +});
90 +
91 +onMounted(() => {
92 + // 调试用,确认用户信息字段
93 + console.log('Recall Page - Current User:', currentUser.value);
94 +});
95 +</script>
96 +
97 +<style scoped>
98 +/* 针对不同屏幕尺寸的微调可以放在这里,或者直接使用 Tailwind */
99 +</style>
...@@ -3,6 +3,7 @@ export default { ...@@ -3,6 +3,7 @@ export default {
3 content: [ 3 content: [
4 "./index.html", 4 "./index.html",
5 "./src/**/*.{vue,js,ts,jsx,tsx}", 5 "./src/**/*.{vue,js,ts,jsx,tsx}",
6 + // Force refresh
6 ], 7 ],
7 theme: { 8 theme: {
8 extend: { 9 extend: {
......
1 /* 1 /*
2 * @Date: 2025-03-20 19:53:12 2 * @Date: 2025-03-20 19:53:12
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-25 17:58:03 4 + * @LastEditTime: 2025-12-19 15:58:39
5 * @FilePath: /mlaj/vite.config.js 5 * @FilePath: /mlaj/vite.config.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -66,25 +66,6 @@ export default ({ command, mode }) => { ...@@ -66,25 +66,6 @@ export default ({ command, mode }) => {
66 }, 66 },
67 css: { 67 css: {
68 modules: '', // 配置 CSS modules 的行为。选项将被传递给 postcss-modules。 68 modules: '', // 配置 CSS modules 的行为。选项将被传递给 postcss-modules。
69 - postcss: { // 内联的 PostCSS 配置(格式同 postcss.config.js),或者一个(默认基于项目根目录的)自定义的 PostCSS 配置路径。其路径搜索是通过 postcss-load-config 实现的。 注意,如果提供了该内联配置,Vite 将不会搜索其他 PostCSS 配置源。
70 - plugins: [
71 - // postcsspxtoviewport({
72 - // unitToConvert: 'px', // 要转化的单位
73 - // viewportWidth: 375, // UI设计稿的宽度
74 - // unitPrecision: 6, // 转换后的精度,即小数点位数
75 - // propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
76 - // viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
77 - // fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
78 - // selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名,
79 - // minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
80 - // mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
81 - // replace: true, // 是否转换后直接更换属性值
82 - // // exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
83 - // exclude: [],
84 - // landscape: false // 是否处理横屏情况
85 - // })
86 - ]
87 - },
88 preprocessorOptions: { 69 preprocessorOptions: {
89 // less: { 70 // less: {
90 // javascriptEnabled: true, 71 // javascriptEnabled: true,
......