hookehuyr

docs(welcome): 调整功能入口为3个,采用环绕式布局

功能入口调整:
- 移除时光机入口,保留3个核心功能(课程、活动、我的)
- 图标改为使用图片: /img/wecome_btn_1.png
- 布局调整为环绕式,模拟天体行星轨道效果

布局设计:
- 🌌 环绕式布局: 3个图标呈弧形排列
- 📍 位置: 页面中下位置
- ✨ 效果: 星空宇宙主题,旋转虚线轨道
- 🖼️ 图标: 统一使用图片图标,圆形发光效果

技术实现:
- 使用绝对定位形成环绕效果
- 左侧: 课程中心 (左下)
- 顶部: 活动中心 (中上)
- 右侧: 个人中心 (右下)
- 添加旋转轨道动画 (60s 匀速旋转)

更新文件:
- plan.md: 更新功能入口配置和布局代码
- README.md: 更新开发进度和布局说明
- brainstorm.md: 更新待确认事项

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
...@@ -70,17 +70,18 @@ VITE_WELCOME_VIDEO_URL=https://cdn.ipadbiz.cn/mlaj/video/welcome-bg.mp4 ...@@ -70,17 +70,18 @@ VITE_WELCOME_VIDEO_URL=https://cdn.ipadbiz.cn/mlaj/video/welcome-bg.mp4
70 - [x] 通用上传工具 (`scripts/upload-to-qiniu.sh`) 70 - [x] 通用上传工具 (`scripts/upload-to-qiniu.sh`)
71 - [x] 详细实现计划 (`plan.md`) 71 - [x] 详细实现计划 (`plan.md`)
72 - [x] 头脑风暴文档 (`brainstorm.md`) 72 - [x] 头脑风暴文档 (`brainstorm.md`)
73 -- [x] 功能入口列表确定(课程、活动、时光机、我的) 73 +- [x] 功能入口列表确定(3个入口:课程、活动、我的)
74 +- [x] 功能图标确定 (`/img/wecome_btn_1.png`)
74 75
75 ### ⏳ 待开发 76 ### ⏳ 待开发
76 - [ ] VideoBackground 组件 77 - [ ] VideoBackground 组件
77 -- [ ] WelcomeContent 组件 78 +- [ ] WelcomeContent 组件(环绕式布局)
78 -- [ ] WelcomeEntryItem 组件 79 +- [ ] WelcomeEntryItem 组件(图片图标)
79 - [ ] 路由与首次访问逻辑 80 - [ ] 路由与首次访问逻辑
80 -- [ ] 功能入口配置实现
81 81
82 ### ❌ 待确认 82 ### ❌ 待确认
83 - [ ] 页面效果图 (设计稿) 83 - [ ] 页面效果图 (设计稿)
84 +- [ ] 环绕式布局的具体位置参数
84 - [ ] 页面布局细节 (顶部/底部元素) 85 - [ ] 页面布局细节 (顶部/底部元素)
85 86
86 --- 87 ---
...@@ -148,8 +149,13 @@ window.showWelcome() ...@@ -148,8 +149,13 @@ window.showWelcome()
148 1. **课程中心** (`/courses`) - 探索精选课程 149 1. **课程中心** (`/courses`) - 探索精选课程
149 2. **活动中心** (`/activity`) - 精彩活动不容错过 150 2. **活动中心** (`/activity`) - 精彩活动不容错过
150 - ⚠️ **注意**: 当前为外链跳转,跳转到 `https://wxm.behalo.cc/pages/activity/activity` 151 - ⚠️ **注意**: 当前为外链跳转,跳转到 `https://wxm.behalo.cc/pages/activity/activity`
151 -3. **时光机** (`/recall/login`) - 回顾学习历程 152 +3. **个人中心** (`/profile`) - 管理您的账户
152 -4. **个人中心** (`/profile`) - 管理您的账户 153 +
154 +**布局设计:**
155 +- 🌌 **环绕式布局**: 3个图标像天体行星一样环绕排列
156 +- 📍 **位置**: 页面中下位置
157 +-**效果**: 星空宇宙主题,有旋转的虚线轨道
158 +- 🖼️ **图标**: 统一使用 `/img/wecome_btn_1.png`
153 159
154 --- 160 ---
155 161
......
...@@ -419,11 +419,12 @@ const posterUrl = 'https://cdn.ipadbiz.cn/mlaj/video/welcome-bg.mp4?vframe/jpg/o ...@@ -419,11 +419,12 @@ const posterUrl = 'https://cdn.ipadbiz.cn/mlaj/video/welcome-bg.mp4?vframe/jpg/o
419 419
420 1.**背景视频文件** - `video/welcome-bg.mp4` 已添加并上传到七牛云 420 1.**背景视频文件** - `video/welcome-bg.mp4` 已添加并上传到七牛云
421 2.**页面效果图** - `img/` 文件夹为空,需要设计稿确认布局 421 2.**页面效果图** - `img/` 文件夹为空,需要设计稿确认布局
422 -3.**功能入口列表** - 已确定底部Tab的四个功能入口 422 +3.**功能入口列表** - 已确定3个功能入口
423 - 课程中心: `/courses` 423 - 课程中心: `/courses`
424 - 活动中心: `/activity` (⚠️ 当前为外链跳转: `https://wxm.behalo.cc/pages/activity/activity`) 424 - 活动中心: `/activity` (⚠️ 当前为外链跳转: `https://wxm.behalo.cc/pages/activity/activity`)
425 - - 时光机: `/recall/login`
426 - 个人中心: `/profile` 425 - 个人中心: `/profile`
426 + -**图标确定**: 使用 `/img/wecome_btn_1.png` (图片图标)
427 + -**布局确定**: 环绕式布局,位于页面中下,天体行星感觉
427 4.**页面布局细节** - 顶部/底部是否需要元素(Logo、标语、按钮等) 428 4.**页面布局细节** - 顶部/底部是否需要元素(Logo、标语、按钮等)
428 429
429 **建议:** 先完成技术框架和上传工具,等设计稿确认后再填充内容。 430 **建议:** 先完成技术框架和上传工具,等设计稿确认后再填充内容。
......
...@@ -765,14 +765,14 @@ if (import.meta.env.DEV) { ...@@ -765,14 +765,14 @@ if (import.meta.env.DEV) {
765 ```javascript 765 ```javascript
766 /** 766 /**
767 * 欢迎页功能入口配置 767 * 欢迎页功能入口配置
768 - * 对应项目底部Tab的四个主要功能入口 768 + * 采用环绕式布局,3个功能入口像天体行星一样排列
769 */ 769 */
770 export const welcomeEntries = [ 770 export const welcomeEntries = [
771 { 771 {
772 id: 'courses', 772 id: 'courses',
773 title: '课程中心', 773 title: '课程中心',
774 subtitle: '探索精选课程', 774 subtitle: '探索精选课程',
775 - icon: '📚', 775 + icon: '/img/wecome_btn_1.png', // 使用图片图标
776 route: '/courses', 776 route: '/courses',
777 color: '#4CAF50', 777 color: '#4CAF50',
778 priority: 1 778 priority: 1
...@@ -781,7 +781,7 @@ export const welcomeEntries = [ ...@@ -781,7 +781,7 @@ export const welcomeEntries = [
781 id: 'activity', 781 id: 'activity',
782 title: '活动中心', 782 title: '活动中心',
783 subtitle: '精彩活动不容错过', 783 subtitle: '精彩活动不容错过',
784 - icon: '🎉', 784 + icon: '/img/wecome_btn_1.png', // 使用图片图标
785 route: '/activity', 785 route: '/activity',
786 color: '#FF9800', 786 color: '#FF9800',
787 priority: 2, 787 priority: 2,
...@@ -789,22 +789,13 @@ export const welcomeEntries = [ ...@@ -789,22 +789,13 @@ export const welcomeEntries = [
789 externalUrl: 'https://wxm.behalo.cc/pages/activity/activity?token=&user_id=' 789 externalUrl: 'https://wxm.behalo.cc/pages/activity/activity?token=&user_id='
790 }, 790 },
791 { 791 {
792 - id: 'recall',
793 - title: '时光机',
794 - subtitle: '回顾学习历程',
795 - icon: '⏰',
796 - route: '/recall/login',
797 - color: '#9C27B0',
798 - priority: 3
799 - },
800 - {
801 id: 'profile', 792 id: 'profile',
802 title: '个人中心', 793 title: '个人中心',
803 subtitle: '管理您的账户', 794 subtitle: '管理您的账户',
804 - icon: '👤', 795 + icon: '/img/wecome_btn_1.png', // 使用图片图标
805 route: '/profile', 796 route: '/profile',
806 color: '#2196F3', 797 color: '#2196F3',
807 - priority: 4 798 + priority: 3
808 } 799 }
809 ] 800 ]
810 801
...@@ -828,17 +819,18 @@ export function getSortedEntries() { ...@@ -828,17 +819,18 @@ export function getSortedEntries() {
828 - 查看最新活动信息 819 - 查看最新活动信息
829 - 活动报名和参与 820 - 活动报名和参与
830 - ⚠️ **特殊处理**: 当前为外链跳转,跳转到 `https://wxm.behalo.cc/pages/activity/activity` 821 - ⚠️ **特殊处理**: 当前为外链跳转,跳转到 `https://wxm.behalo.cc/pages/activity/activity`
831 - - 未来可能需要集成到项目内
832 -
833 -3. **时光机** (`/recall/login`)
834 - - 回顾功能和历史记录
835 - - 用户成长历程展示
836 822
837 -4. **个人中心** (`/profile`) 823 +3. **个人中心** (`/profile`)
838 - 对应底部Tab第四个入口 824 - 对应底部Tab第四个入口
839 - 个人资料管理 825 - 个人资料管理
840 - 学习记录和设置 826 - 学习记录和设置
841 827
828 +**布局设计:**
829 +- 🌌 **环绕式布局**: 3个图标像天体行星一样环绕排列
830 +- 📍 **位置**: 页面中下位置
831 +- 🎨 **视觉效果**: 星空宇宙主题,行星轨道感
832 +- 🖼️ **图标**: 统一使用 `/img/wecome_btn_1.png`
833 +
842 #### 步骤 2: 创建功能入口项组件 834 #### 步骤 2: 创建功能入口项组件
843 835
844 **文件:** `src/components/welcome/WelcomeEntryItem.vue` 836 **文件:** `src/components/welcome/WelcomeEntryItem.vue`
...@@ -850,9 +842,9 @@ export function getSortedEntries() { ...@@ -850,9 +842,9 @@ export function getSortedEntries() {
850 :style="{ '--index': index }" 842 :style="{ '--index': index }"
851 @click="handleClick" 843 @click="handleClick"
852 > 844 >
853 - <!-- 图标 --> 845 + <!-- 图标 (图片) -->
854 - <div class="entry-icon" :style="{ color: entry.color }"> 846 + <div class="entry-icon">
855 - {{ entry.icon }} 847 + <img :src="entry.icon" :alt="entry.title" />
856 </div> 848 </div>
857 849
858 <!-- 标题 --> 850 <!-- 标题 -->
...@@ -860,7 +852,7 @@ export function getSortedEntries() { ...@@ -860,7 +852,7 @@ export function getSortedEntries() {
860 {{ entry.title }} 852 {{ entry.title }}
861 </div> 853 </div>
862 854
863 - <!-- 副标题(可选) --> 855 + <!-- 副标题 -->
864 <div v-if="entry.subtitle" class="entry-subtitle"> 856 <div v-if="entry.subtitle" class="entry-subtitle">
865 {{ entry.subtitle }} 857 {{ entry.subtitle }}
866 </div> 858 </div>
...@@ -905,25 +897,45 @@ const handleClick = () => { ...@@ -905,25 +897,45 @@ const handleClick = () => {
905 897
906 <style scoped lang="less"> 898 <style scoped lang="less">
907 .entry-item { 899 .entry-item {
900 + position: absolute; // 绝对定位,形成环绕效果
908 display: flex; 901 display: flex;
909 flex-direction: column; 902 flex-direction: column;
910 align-items: center; 903 align-items: center;
911 justify-content: center; 904 justify-content: center;
912 - padding: 1.5rem; 905 + padding: 1rem;
913 cursor: pointer; 906 cursor: pointer;
914 user-select: none; 907 user-select: none;
915 transition: all 0.3s ease; 908 transition: all 0.3s ease;
916 909
917 // 呼吸动画 910 // 呼吸动画
918 animation: breathe 2.5s ease-in-out infinite; 911 animation: breathe 2.5s ease-in-out infinite;
919 - animation-delay: calc(var(--index) * 0.3s); 912 + animation-delay: calc(var(--index) * 0.5s);
913 +
914 + // 环绕式布局位置计算
915 + &:nth-child(1) {
916 + // 左侧入口
917 + left: 0;
918 + bottom: 0;
919 + }
920 +
921 + &:nth-child(2) {
922 + // 顶部入口
923 + left: 50%;
924 + transform: translateX(-50%);
925 + bottom: 60%;
926 + }
927 +
928 + &:nth-child(3) {
929 + // 右侧入口
930 + right: 0;
931 + bottom: 0;
932 + }
920 933
921 &:hover { 934 &:hover {
922 animation-duration: 1s; 935 animation-duration: 1s;
923 - transform: scale(1.1);
924 936
925 - .entry-icon { 937 + .entry-icon img {
926 - transform: scale(1.2); 938 + transform: scale(1.15);
927 } 939 }
928 } 940 }
929 941
...@@ -934,19 +946,28 @@ const handleClick = () => { ...@@ -934,19 +946,28 @@ const handleClick = () => {
934 946
935 @keyframes breathe { 947 @keyframes breathe {
936 0%, 100% { 948 0%, 100% {
937 - transform: scale(1);
938 opacity: 0.9; 949 opacity: 0.9;
939 } 950 }
940 50% { 951 50% {
941 - transform: scale(1.08);
942 opacity: 1; 952 opacity: 1;
943 } 953 }
944 } 954 }
945 955
946 .entry-icon { 956 .entry-icon {
947 - font-size: 3rem; 957 + width: 80px;
958 + height: 80px;
948 margin-bottom: 0.75rem; 959 margin-bottom: 0.75rem;
949 - transition: transform 0.3s ease; 960 + border-radius: 50%;
961 + overflow: hidden;
962 + box-shadow: 0 0 20px rgba(255, 255, 255, 0.3);
963 + transition: all 0.3s ease;
964 +
965 + img {
966 + width: 100%;
967 + height: 100%;
968 + object-fit: cover;
969 + transition: transform 0.3s ease;
970 + }
950 } 971 }
951 972
952 .entry-title { 973 .entry-title {
...@@ -956,6 +977,7 @@ const handleClick = () => { ...@@ -956,6 +977,7 @@ const handleClick = () => {
956 text-align: center; 977 text-align: center;
957 text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); 978 text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
958 margin-bottom: 0.25rem; 979 margin-bottom: 0.25rem;
980 + white-space: nowrap;
959 } 981 }
960 982
961 .entry-subtitle { 983 .entry-subtitle {
...@@ -963,6 +985,7 @@ const handleClick = () => { ...@@ -963,6 +985,7 @@ const handleClick = () => {
963 color: rgba(255, 255, 255, 0.8); 985 color: rgba(255, 255, 255, 0.8);
964 text-align: center; 986 text-align: center;
965 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); 987 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
988 + white-space: nowrap;
966 } 989 }
967 </style> 990 </style>
968 ``` 991 ```
...@@ -1006,21 +1029,48 @@ const sortedEntries = computed(() => getSortedEntries()) ...@@ -1006,21 +1029,48 @@ const sortedEntries = computed(() => getSortedEntries())
1006 display: flex; 1029 display: flex;
1007 flex-direction: column; 1030 flex-direction: column;
1008 align-items: center; 1031 align-items: center;
1009 - justify-content: center; 1032 + justify-content: flex-end; // 内容靠下,位于中下位置
1010 padding: 2rem; 1033 padding: 2rem;
1034 + padding-bottom: 6rem; // 距离底部有足够空间
1011 } 1035 }
1012 1036
1013 .entries-grid { 1037 .entries-grid {
1014 - display: grid; 1038 + position: relative;
1015 - grid-template-columns: repeat(2, 1fr); 1039 + display: flex;
1016 - gap: 1.5rem; 1040 + justify-content: center;
1041 + align-items: center;
1017 width: 100%; 1042 width: 100%;
1018 - max-width: 600px; 1043 + max-width: 500px;
1044 +
1045 + // 环绕式布局:3个图标呈弧形排列
1046 + // 使用绝对定位模拟行星轨道效果
1047 + &::before {
1048 + content: '';
1049 + position: absolute;
1050 + width: 300px;
1051 + height: 300px;
1052 + border: 2px dashed rgba(255, 255, 255, 0.2);
1053 + border-radius: 50%;
1054 + animation: rotate 60s linear infinite;
1055 + }
1019 1056
1020 @media (min-width: 768px) { 1057 @media (min-width: 768px) {
1021 - grid-template-columns: repeat(3, 1fr); 1058 + max-width: 700px;
1022 - gap: 2rem; 1059 +
1023 - max-width: 900px; 1060 + &::before {
1061 + width: 450px;
1062 + height: 450px;
1063 + }
1064 + }
1065 +}
1066 +
1067 +// 旋转轨道动画
1068 +@keyframes rotate {
1069 + from {
1070 + transform: rotate(0deg);
1071 + }
1072 + to {
1073 + transform: rotate(360deg);
1024 } 1074 }
1025 } 1075 }
1026 </style> 1076 </style>
...@@ -1338,8 +1388,9 @@ https://cdn.ipadbiz.cn/mlaj/video/welcome-bg.mp4?vframe/jpg/offset/0.001/w/1920/ ...@@ -1338,8 +1388,9 @@ https://cdn.ipadbiz.cn/mlaj/video/welcome-bg.mp4?vframe/jpg/offset/0.001/w/1920/
1338 1388
1339 1.**背景视频文件** - `video/welcome-bg.mp4` 已添加并上传到七牛云 1389 1.**背景视频文件** - `video/welcome-bg.mp4` 已添加并上传到七牛云
1340 2.**页面效果图** - 需要设计稿确认布局 1390 2.**页面效果图** - 需要设计稿确认布局
1341 -3.**功能入口列表** - 已确定(课程、活动、时光机、我的) 1391 +3.**功能入口列表** - 已确定3个入口(课程、活动、我的)
1342 -4.**页面布局细节** - 顶部/底部是否需要元素(Logo、标语、按钮等) 1392 +4.**功能图标** - 已确定使用 `/img/wecome_btn_1.png`
1393 +5.**页面布局细节** - 顶部/底部是否需要其他元素(Logo、标语等)
1343 1394
1344 **建议:** 先完成技术框架和上传工具,等设计稿确认后再填充内容。 1395 **建议:** 先完成技术框架和上传工具,等设计稿确认后再填充内容。
1345 1396
......