caolinxuan 2 săptămâni în urmă
părinte
comite
fe6a41d5e3

+ 67 - 2
pages.json

@@ -19,7 +19,40 @@
 			"style": {
 				"navigationBarTitleText": "首页"
 			}
-		}
+		},
+		{
+			"path": "pages/discover/index",
+			"style": {
+				"navigationBarTitleText": "发现",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/message/index",
+			"style": {
+				"navigationBarTitleText": "消息",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/mine/index",
+			"style": {
+				"navigationBarTitleText": "我的",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/search/index",
+			"style": {
+				"navigationBarTitleText": "课程搜索"
+			}
+		},
+		{
+			"path": "pages/calendar/index",
+			"style": {
+				"navigationBarTitleText": "课程日历"
+			}
+		},
 	],
 	"globalStyle": {
 		"navigationBarTextStyle": "black",
@@ -27,5 +60,37 @@
 		"navigationBarBackgroundColor": "#F8F8F8",
 		"backgroundColor": "#F8F8F8"
 	},
-	"uniIdRouter": {}
+	"uniIdRouter": {},
+	"tabBar": {
+		"color": "#888",
+		"selectedColor": "#3498db",
+		"backgroundColor": "#fff",
+		"borderStyle": "black",
+		"list": [
+			{
+				"pagePath": "pages/index/index",
+				"iconPath": "static/tabbar/home.png",
+				"selectedIconPath": "static/tabbar/home_selected.png",
+				"text": "首页"
+			},
+			{
+				"pagePath": "pages/discover/index",
+				"iconPath": "static/tabbar/discover.png",
+				"selectedIconPath": "static/tabbar/discover_selected.png",
+				"text": "发现"
+			},
+			{
+				"pagePath": "pages/message/index",
+				"iconPath": "static/tabbar/message.png",
+				"selectedIconPath": "static/tabbar/message_selected.png",
+				"text": "消息"
+			},
+			{
+				"pagePath": "pages/mine/index",
+				"iconPath": "static/tabbar/mine.png",
+				"selectedIconPath": "static/tabbar/mine_selected.png",
+				"text": "我的"
+			}
+		]
+	}
 }

+ 179 - 26
pages/index/index.vue

@@ -1,9 +1,36 @@
 <template>
-	<view class="content">
-		<image class="logo" src="/static/logo.png"></image>
-		<view class="text-area">
-			<text class="title">{{title}}</text>
+	<view class="home-bg">
+		<!-- 顶部栏 -->
+		<view class="top-bar">
+			<view class="title">小鹅通</view>
+			<view class="top-icons">
+				<view class="iconfont icon-search" @click="goToSearch"></view>
+				<view class="iconfont icon-calendar" @click="goToCalendar">日历</view>
+			</view>
 		</view>
+		<!-- 水滴背景装饰 -->
+		<view class="waterdrop waterdrop-left"></view>
+		<view class="waterdrop waterdrop-right"></view>
+		<!-- 日期和插画区 -->
+		<view class="header-content">
+			<view class="date-motivation">
+				<view class="date">{{ today }}</view>
+				<view class="motivation">加油梦想是可以实现的</view>
+			</view>
+			<view class="illustration">
+				<image src="/static/illustration_book.png" class="book-img" mode="aspectFit" />
+			</view>
+		</view>
+		<!-- 我的课程模块 -->
+		<view class="my-course">
+			<view class="module-title">我的课程</view>
+			<view class="empty-course">
+				<image src="/static/empty_box.png" class="empty-img" mode="aspectFit" />
+				<view class="empty-tip">你还没有学习系列课程\n前往查看你的其他课程</view>
+				<button class="more-btn">更多课程</button>
+			</view>
+		</view>
+		<view class="find-course">找不到已购课程?</view>
 	</view>
 </template>
 
@@ -11,42 +38,168 @@
 	export default {
 		data() {
 			return {
-				title: 'Hello'
+				today: this.getToday()
 			}
 		},
-		onLoad() {
-
-		},
 		methods: {
-
+			getToday() {
+				const d = new Date()
+				const month = d.getMonth() + 1
+				const day = d.getDate()
+				return `${month < 10 ? '0' + month : month}/${day < 10 ? '0' + day : day}`
+			},
+			goToSearch() {
+				uni.navigateTo({ url: '/pages/search/index' })
+			},
+			goToCalendar() {
+				uni.navigateTo({ url: '/pages/calendar/index' })
+			}
 		}
 	}
 </script>
 
-<style>
-	.content {
+<style lang="scss">
+	.home-bg {
+		min-height: 100vh;
+		background: linear-gradient(180deg, #eaf6ff 0%, #f7f8fa 100%);
+		position: relative;
+		padding-bottom: 120rpx;
+	}
+	.top-bar {
 		display: flex;
-		flex-direction: column;
 		align-items: center;
 		justify-content: center;
+		position: relative;
+		height: 120rpx;
+		padding-top: 40rpx;
 	}
-
-	.logo {
-		height: 200rpx;
-		width: 200rpx;
-		margin-top: 200rpx;
-		margin-left: auto;
-		margin-right: auto;
-		margin-bottom: 50rpx;
+	.title {
+		font-size: 44rpx;
+		font-weight: bold;
+		color: #222;
+		letter-spacing: 2rpx;
+		text-align: center;
+		flex: 1;
+		font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
 	}
-
-	.text-area {
+	.top-icons {
+		position: absolute;
+		right: 40rpx;
+		top: 50%;
+		transform: translateY(-50%);
+		display: flex;
+		gap: 32rpx;
+	}
+	.iconfont {
+		font-size: 40rpx;
+		color: #222;
+	}
+	.icon-search {
+		margin-right: 8rpx;
+	}
+	.icon-calendar {
+	}
+	.waterdrop {
+		position: absolute;
+		width: 32rpx;
+		height: 32rpx;
+		background: linear-gradient(180deg, #b3e0ff 0%, #eaf6ff 100%);
+		border-radius: 50% 50% 60% 40%/60% 40% 50% 50%;
+		opacity: 0.7;
+		z-index: 1;
+	}
+	.waterdrop-left {
+		left: 80rpx;
+		top: 110rpx;
+	}
+	.waterdrop-right {
+		right: 80rpx;
+		top: 110rpx;
+	}
+	.header-content {
 		display: flex;
+		flex-direction: row;
+		align-items: flex-start;
+		justify-content: space-between;
+		margin: 0 40rpx 0 40rpx;
+		margin-top: 20rpx;
+	}
+	.date-motivation {
+		display: flex;
+		flex-direction: column;
+		align-items: flex-start;
+		margin-top: 20rpx;
+	}
+	.date {
+		font-size: 48rpx;
+		font-weight: 700;
+		color: #222;
+		margin-bottom: 8rpx;
+	}
+	.motivation {
+		font-size: 28rpx;
+		color: #4a90e2;
+		font-weight: 500;
+	}
+	.illustration {
+		width: 220rpx;
+		height: 140rpx;
+		margin-top: 0;
+	}
+	.book-img {
+		width: 100%;
+		height: 100%;
+	}
+	.my-course {
+		background: #fff;
+		border-radius: 24rpx;
+		margin: 40rpx 24rpx 0 24rpx;
+		box-shadow: 0 4rpx 24rpx rgba(0,0,0,0.04);
+		padding: 32rpx 24rpx 40rpx 24rpx;
+		position: relative;
+	}
+	.module-title {
+		font-size: 32rpx;
+		font-weight: 600;
+		color: #222;
+		margin-bottom: 24rpx;
+	}
+	.empty-course {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
 		justify-content: center;
+		padding: 40rpx 0 0 0;
 	}
-
-	.title {
-		font-size: 36rpx;
-		color: #8f8f94;
+	.empty-img {
+		width: 120rpx;
+		height: 120rpx;
+		margin-bottom: 24rpx;
+	}
+	.empty-tip {
+		font-size: 28rpx;
+		color: #888;
+		text-align: center;
+		margin-bottom: 32rpx;
+		white-space: pre-line;
+	}
+	.more-btn {
+		width: 320rpx;
+		height: 72rpx;
+		background: #fff;
+		border: 2rpx solid #3498db;
+		color: #3498db;
+		border-radius: 36rpx;
+		font-size: 30rpx;
+		font-weight: 600;
+		text-align: center;
+		line-height: 72rpx;
+		margin-top: 8rpx;
+	}
+	.find-course {
+		text-align: center;
+		color: #bbb;
+		font-size: 26rpx;
+		margin-top: 32rpx;
 	}
 </style>

+ 132 - 44
pages/login/index.vue

@@ -1,5 +1,4 @@
 <template>
-  111
   <view class="login-container">
     <view class="login-box">
       <!-- Logo区域 -->
@@ -52,7 +51,9 @@
 export default {
   data() {
     return {
-      isAgreed: false
+      isAgreed: false,
+      showServiceAgreement: false,
+      showPrivacyPolicy: false
     }
   },
   methods: {
@@ -61,55 +62,141 @@ export default {
       this.isAgreed = e.detail.value.length > 0
     },
 
-
-
     // 微信登录
     async handleWechatLogin() {
       if (!this.isAgreed) {
-        uni.showToast({
-          title: '请先同意服务协议和隐私政策',
-          icon: 'none'
-        })
+        uni.showToast({ title: '请先同意用户协议和隐私政策', icon: 'none' })
         return
       }
-      // 前端代码示例(微信小程序)
-	wx.login({
-	    success: function (res) {
-	        if (res.code) {
-	            console.log(res.code);
-	            // 将 code 发送给后端
-	            wx.request({
-	                url: 'http://localhost:9527/api/wx-login',
-	                method: 'POST',
-	                // 设置请求头,指定请求体为 JSON 格式
-	                header: {
-	                    'content-type': 'application/json'
-	                },
-	                data: {
-	                    code: res.code
-	                },
-	                success: function (response) {
-	                    console.log(response.data);
-	                },
-	                fail: function (err) {
-	                    console.error(err);
-	                }
-	            });
-	        } else {
-	            console.log('获取 code 失败!' + res.errMsg);
-	        }
-	    }
-	});
-
+      
+      try {
+        // 获取微信登录凭证
+        const loginResult = await new Promise((resolve, reject) => {
+          uni.login({
+            provider: 'weixin',
+            success: (res) => resolve(res),
+            fail: (err) => reject(err)
+          });
+        });
+        
+        if (!loginResult.code) {
+          uni.showToast({ title: '获取登录凭证失败', icon: 'none' });
+          return;
+        }
+
+        // 立即使用code,避免过期
+        console.log('获取到的code:', loginResult.code);
+        
+        // 获取用户信息
+        const userInfoResult = await new Promise((resolve, reject) => {
+          uni.getUserInfo({
+            provider: 'weixin',
+            withCredentials: true,
+            success: (res) => resolve(res),
+            fail: (err) => reject(err)
+          });
+        });
+        
+        if (!userInfoResult.userInfo) {
+          uni.showToast({ title: '获取用户信息失败', icon: 'none' });
+          return;
+        }
+        
+        // 调用后端登录接口
+        const loginRes = await uni.request({
+          url: 'http://localhost:9527/api/wx-login',
+          method: 'POST',
+          data: {
+            code: loginResult.code,
+            nickName: userInfoResult.userInfo.nickName,
+            avatarUrl: userInfoResult.userInfo.avatarUrl,
+            gender: userInfoResult.userInfo.gender.toString(),
+            country: userInfoResult.userInfo.country,
+            province: userInfoResult.userInfo.province,
+            city: userInfoResult.userInfo.city,
+            language: userInfoResult.userInfo.language,
+            rawData: userInfoResult.rawData,
+            signature: userInfoResult.signature,
+            encryptedData: userInfoResult.encryptedData,
+            iv: userInfoResult.iv
+          },
+          header: {
+            'content-type': 'application/json'
+          }
+        });
+
+        // 处理微信登录错误
+        if (loginRes.data.errcode === 40029) {
+          console.error('微信登录code无效,尝试重新获取');
+          // 重新获取code并重试
+          const newLoginResult = await new Promise((resolve, reject) => {
+            uni.login({
+              provider: 'weixin',
+              success: (res) => resolve(res),
+              fail: (err) => reject(err)
+            });
+          });
+
+          if (!newLoginResult.code) {
+            throw new Error('重新获取登录凭证失败');
+          }
+
+          // 使用新的code重试登录
+          const retryRes = await uni.request({
+            url: 'http://localhost:9527/api/wx-login',
+            method: 'POST',
+            data: {
+              code: newLoginResult.code,
+              nickName: userInfoResult.userInfo.nickName,
+              avatarUrl: userInfoResult.userInfo.avatarUrl,
+              gender: userInfoResult.userInfo.gender.toString(),
+              country: userInfoResult.userInfo.country,
+              province: userInfoResult.userInfo.province,
+              city: userInfoResult.userInfo.city,
+              language: userInfoResult.userInfo.language,
+              rawData: userInfoResult.rawData,
+              signature: userInfoResult.signature,
+              encryptedData: userInfoResult.encryptedData,
+              iv: userInfoResult.iv
+            },
+            header: {
+              'content-type': 'application/json'
+            }
+          });
+
+          if (retryRes.statusCode === 200 && !retryRes.data.errcode) {
+            // 登录成功,保存token
+            uni.setStorageSync('token', retryRes.data.data.token);
+            uni.setStorageSync('userInfo', retryRes.data.data.userInfo);
+            
+            // 跳转到发现页
+            uni.switchTab({
+              url: '/pages/discover/index'
+            });
+          } else {
+            throw new Error(retryRes.data.errmsg || '登录失败');
+          }
+        } else if (loginRes.statusCode === 200 && !loginRes.data.errcode) {
+          // 登录成功,保存token
+          uni.setStorageSync('token', loginRes.data.data.token);
+          uni.setStorageSync('userInfo', loginRes.data.data.userInfo);
+          
+          // 跳转到发现页
+          uni.switchTab({
+            url: '/pages/discover/index'
+          });
+        } else {
+          throw new Error(loginRes.data.errmsg || '登录失败');
+        }
+      } catch (error) {
+        console.error('登录过程出错:', error);
+        uni.showToast({ 
+          title: error.message || '登录失败,请重试', 
+          icon: 'none' 
+        });
+      }
     },
 
-    // // 跳转到密码登录页面
-    // navigateToPasswordLogin() {
-    //   uni.navigateTo({
-    //     url: '/pages/login/password'
-    //   })
-    // },
-
     // 跳转到验证码登录页面
     navigateToVerifyCodeLogin() {
       uni.navigateTo({
@@ -344,3 +431,4 @@ export default {
   }
 }
 </style>
+ 

+ 38 - 6
pages/login/verify-code.vue

@@ -106,10 +106,40 @@ export default {
         uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
         return
       }
-      // TODO: 调用发送验证码接口
-      this.counting = true
-      this.countdown = 60
-      this.startCountdown()
+
+      try {
+        // 调用获取验证码接口
+        const res = await uni.request({
+          url: 'http://localhost:9527/api/getCode',
+          method: 'POST',
+          data: {
+            phone: this.phone
+          },
+          header: {
+            'content-type': 'application/json'
+          },
+        });
+		console.log(res.statusCode);
+        if (res.statusCode === 200 ) {
+			console.log('验证码接口返回:', res);
+          uni.showToast({ 
+            title: '验证码已发送', 
+            icon: 'success' 
+          });
+          // 开始倒计时
+          this.counting = true
+          this.countdown = 60
+          this.startCountdown()
+        } else {
+          throw new Error(res.data.msg || '获取验证码失败')
+        }
+      } catch (error) {
+        console.error('获取验证码失败:', error);
+        uni.showToast({ 
+          title: error.message || '获取验证码失败,请重试', 
+          icon: 'none' 
+        });
+      }
     },
     startCountdown() {
       const timer = setInterval(() => {
@@ -128,14 +158,16 @@ export default {
         return
       }
       // TODO: 调用后端登录接口
-      uni.showToast({ title: '登录成功(示例)', icon: 'success' })
+      uni.switchTab({
+          url: '/pages/discover/index'  // 替换为实际页面路径
+      });
     },
     closePopup() {
       this.showServiceAgreement = false
       this.showPrivacyPolicy = false
     },
     goToWechatLogin() {
-      uni.navigateTo({
+      uni.switchTab({
         url: '/pages/login/index'
       })
     }

+ 1 - 1
unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map

@@ -1 +1 @@
-{"version":3,"file":"app.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;"}
+{"version":3,"file":"app.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}

+ 1 - 1
unpackage/dist/dev/.sourcemap/mp-weixin/common/assets.js.map

@@ -1 +1 @@
-{"version":3,"file":"assets.js","sources":["static/login.png","static/logo.png"],"sourcesContent":["export default \"__VITE_ASSET__ec1e9ea5__\"","export default \"__VITE_ASSET__46719607__\""],"names":[],"mappings":";AAAA,MAAe,eAAA;ACAf,MAAe,aAAA;;;"}
+{"version":3,"file":"assets.js","sources":["static/login.png","../../../static/illustration_book.png","../../../static/empty_box.png"],"sourcesContent":["export default \"__VITE_ASSET__ec1e9ea5__\"","export default \"/static/illustration_book.png\"","export default \"/static/empty_box.png\""],"names":[],"mappings":";AAAA,MAAe,eAAA;ACAf,MAAe,aAAA;ACAf,MAAe,aAAA;;;;"}

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map


+ 1 - 1
unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map

@@ -1 +1 @@
-{"version":3,"file":"index.js","sources":["../../../ruanjian/HBuilder X/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvaW5kZXgvaW5kZXgudnVl"],"sourcesContent":["import MiniProgramPage from 'D:/java file/2407_5/small_goose_vue/pages/index/index.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"}
+{"version":3,"file":"index.js","sources":["../../../ruanjian/HBuilder X/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvaW5kZXgvaW5kZXgudnVl"],"sourcesContent":["import MiniProgramPage from 'D:/java file/2407_5/small_goose_vue/pages/index/index.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"}

+ 1 - 1
unpackage/dist/dev/.sourcemap/mp-weixin/pages/login/index.js.map

@@ -1 +1 @@
-{"version":3,"file":"index.js","sources":["../../../ruanjian/HBuilder X/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbG9naW4vaW5kZXgudnVl"],"sourcesContent":["import MiniProgramPage from 'D:/java file/2407_5/small_goose_vue/pages/login/index.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"}
+{"version":3,"file":"index.js","sources":["../../../ruanjian/HBuilder X/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbG9naW4vaW5kZXgudnVl"],"sourcesContent":["import MiniProgramPage from 'D:/java file/2407_5/small_goose_vue/pages/login/index.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"}

+ 1 - 1
unpackage/dist/dev/.sourcemap/mp-weixin/pages/login/verify-code.js.map

@@ -1 +1 @@
-{"version":3,"file":"verify-code.js","sources":["../../../ruanjian/HBuilder X/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbG9naW4vdmVyaWZ5LWNvZGUudnVl"],"sourcesContent":["import MiniProgramPage from 'D:/java file/2407_5/small_goose_vue/pages/login/verify-code.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"}
+{"version":3,"file":"verify-code.js","sources":["../../../ruanjian/HBuilder X/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbG9naW4vdmVyaWZ5LWNvZGUudnVl"],"sourcesContent":["import MiniProgramPage from 'D:/java file/2407_5/small_goose_vue/pages/login/verify-code.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"}

+ 5 - 0
unpackage/dist/dev/mp-weixin/app.js

@@ -5,6 +5,11 @@ if (!Math) {
   "./pages/login/index.js";
   "./pages/login/verify-code.js";
   "./pages/index/index.js";
+  "./pages/discover/index.js";
+  "./pages/message/index.js";
+  "./pages/mine/index.js";
+  "./pages/search/index.js";
+  "./pages/calendar/index.js";
 }
 const _sfc_main = {
   onLaunch: function() {

+ 38 - 1
unpackage/dist/dev/mp-weixin/app.json

@@ -2,7 +2,12 @@
   "pages": [
     "pages/login/index",
     "pages/login/verify-code",
-    "pages/index/index"
+    "pages/index/index",
+    "pages/discover/index",
+    "pages/message/index",
+    "pages/mine/index",
+    "pages/search/index",
+    "pages/calendar/index"
   ],
   "window": {
     "navigationBarTextStyle": "black",
@@ -10,5 +15,37 @@
     "navigationBarBackgroundColor": "#F8F8F8",
     "backgroundColor": "#F8F8F8"
   },
+  "tabBar": {
+    "color": "#888",
+    "selectedColor": "#3498db",
+    "backgroundColor": "#fff",
+    "borderStyle": "black",
+    "list": [
+      {
+        "pagePath": "pages/index/index",
+        "iconPath": "static/tabbar/home.png",
+        "selectedIconPath": "static/tabbar/home_selected.png",
+        "text": "首页"
+      },
+      {
+        "pagePath": "pages/discover/index",
+        "iconPath": "static/tabbar/discover.png",
+        "selectedIconPath": "static/tabbar/discover_selected.png",
+        "text": "发现"
+      },
+      {
+        "pagePath": "pages/message/index",
+        "iconPath": "static/tabbar/message.png",
+        "selectedIconPath": "static/tabbar/message_selected.png",
+        "text": "消息"
+      },
+      {
+        "pagePath": "pages/mine/index",
+        "iconPath": "static/tabbar/mine.png",
+        "selectedIconPath": "static/tabbar/mine_selected.png",
+        "text": "我的"
+      }
+    ]
+  },
   "usingComponents": {}
 }

+ 3 - 1
unpackage/dist/dev/mp-weixin/common/assets.js

@@ -1,6 +1,8 @@
 "use strict";
 const _imports_0$1 = "/static/login.png";
-const _imports_0 = "/static/logo.png";
+const _imports_0 = "/static/illustration_book.png";
+const _imports_1 = "/static/empty_box.png";
 exports._imports_0 = _imports_0$1;
 exports._imports_0$1 = _imports_0;
+exports._imports_1 = _imports_1;
 //# sourceMappingURL=../../.sourcemap/mp-weixin/common/assets.js.map

+ 35 - 2
unpackage/dist/dev/mp-weixin/common/vendor.js

@@ -5076,7 +5076,40 @@ function patchStopImmediatePropagation(e2, value) {
     return value;
   }
 }
+function vFor(source, renderItem) {
+  let ret;
+  if (isArray(source) || isString(source)) {
+    ret = new Array(source.length);
+    for (let i = 0, l = source.length; i < l; i++) {
+      ret[i] = renderItem(source[i], i, i);
+    }
+  } else if (typeof source === "number") {
+    if (!Number.isInteger(source)) {
+      warn(`The v-for range expect an integer value but got ${source}.`);
+      return [];
+    }
+    ret = new Array(source);
+    for (let i = 0; i < source; i++) {
+      ret[i] = renderItem(i + 1, i, i);
+    }
+  } else if (isObject(source)) {
+    if (source[Symbol.iterator]) {
+      ret = Array.from(source, (item, i) => renderItem(item, i, i));
+    } else {
+      const keys = Object.keys(source);
+      ret = new Array(keys.length);
+      for (let i = 0, l = keys.length; i < l; i++) {
+        const key = keys[i];
+        ret[i] = renderItem(source[key], key, i);
+      }
+    }
+  } else {
+    ret = [];
+  }
+  return ret;
+}
 const o = (value, key) => vOn(value, key);
+const f = (source, renderItem) => vFor(source, renderItem);
 const e = (target, ...sources) => extend(target, ...sources);
 const n = (value) => normalizeClass(value);
 const t = (val) => toDisplayString(val);
@@ -6843,7 +6876,7 @@ function initOnError() {
 function initRuntimeSocketService() {
   const hosts = "192.168.225.1,192.168.189.1,192.168.171.80,127.0.0.1";
   const port = "8090";
-  const id = "mp-weixin_C-S7Uj";
+  const id = "mp-weixin_DtJ2X4";
   const lazy = typeof swan !== "undefined";
   let restoreError = lazy ? () => {
   } : initOnError();
@@ -7785,9 +7818,9 @@ const createSubpackageApp = initCreateSubpackageApp();
 exports._export_sfc = _export_sfc;
 exports.createSSRApp = createSSRApp;
 exports.e = e;
+exports.f = f;
 exports.index = index;
 exports.n = n;
 exports.o = o;
 exports.t = t;
-exports.wx$1 = wx$1;
 //# sourceMappingURL=../../.sourcemap/mp-weixin/common/vendor.js.map

+ 20 - 6
unpackage/dist/dev/mp-weixin/pages/index/index.js

@@ -4,17 +4,31 @@ const common_assets = require("../../common/assets.js");
 const _sfc_main = {
   data() {
     return {
-      title: "Hello"
+      today: this.getToday()
     };
   },
-  onLoad() {
-  },
-  methods: {}
+  methods: {
+    getToday() {
+      const d = /* @__PURE__ */ new Date();
+      const month = d.getMonth() + 1;
+      const day = d.getDate();
+      return `${month < 10 ? "0" + month : month}/${day < 10 ? "0" + day : day}`;
+    },
+    goToSearch() {
+      common_vendor.index.navigateTo({ url: "/pages/search/index" });
+    },
+    goToCalendar() {
+      common_vendor.index.navigateTo({ url: "/pages/calendar/index" });
+    }
+  }
 };
 function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
   return {
-    a: common_assets._imports_0$1,
-    b: common_vendor.t($data.title)
+    a: common_vendor.o((...args) => $options.goToSearch && $options.goToSearch(...args)),
+    b: common_vendor.o((...args) => $options.goToCalendar && $options.goToCalendar(...args)),
+    c: common_vendor.t($data.today),
+    d: common_assets._imports_0$1,
+    e: common_assets._imports_1
   };
 }
 const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);

+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/index/index.wxml

@@ -1 +1 @@
-<view class="content"><image class="logo" src="{{a}}"></image><view class="text-area"><text class="title">{{b}}</text></view></view>
+<view class="home-bg"><view class="top-bar"><view class="title">小鹅通</view><view class="top-icons"><view class="iconfont icon-search" bindtap="{{a}}"></view><view class="iconfont icon-calendar" bindtap="{{b}}">日历</view></view></view><view class="waterdrop waterdrop-left"></view><view class="waterdrop waterdrop-right"></view><view class="header-content"><view class="date-motivation"><view class="date">{{c}}</view><view class="motivation">加油梦想是可以实现的</view></view><view class="illustration"><image src="{{d}}" class="book-img" mode="aspectFit"/></view></view><view class="my-course"><view class="module-title">我的课程</view><view class="empty-course"><image src="{{e}}" class="empty-img" mode="aspectFit"/><view class="empty-tip">你还没有学习系列课程\n前往查看你的其他课程</view><button class="more-btn">更多课程</button></view></view><view class="find-course">找不到已购课程?</view></view>

+ 163 - 20
unpackage/dist/dev/mp-weixin/pages/index/index.wxss

@@ -1,23 +1,166 @@
-
-.content {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-}
-.logo {
-		height: 200rpx;
-		width: 200rpx;
-		margin-top: 200rpx;
-		margin-left: auto;
-		margin-right: auto;
-		margin-bottom: 50rpx;
-}
-.text-area {
-		display: flex;
-		justify-content: center;
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+.home-bg {
+  min-height: 100vh;
+  background: linear-gradient(180deg, #eaf6ff 0%, #f7f8fa 100%);
+  position: relative;
+  padding-bottom: 120rpx;
+}
+.top-bar {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+  height: 120rpx;
+  padding-top: 40rpx;
 }
 .title {
-		font-size: 36rpx;
-		color: #8f8f94;
+  font-size: 44rpx;
+  font-weight: bold;
+  color: #222;
+  letter-spacing: 2rpx;
+  text-align: center;
+  flex: 1;
+  font-family: "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
+}
+.top-icons {
+  position: absolute;
+  right: 40rpx;
+  top: 50%;
+  transform: translateY(-50%);
+  display: flex;
+  gap: 32rpx;
+}
+.iconfont {
+  font-size: 40rpx;
+  color: #222;
+}
+.icon-search {
+  margin-right: 8rpx;
+}
+.waterdrop {
+  position: absolute;
+  width: 32rpx;
+  height: 32rpx;
+  background: linear-gradient(180deg, #b3e0ff 0%, #eaf6ff 100%);
+  border-radius: 50% 50% 60% 40%/60% 40% 50% 50%;
+  opacity: 0.7;
+  z-index: 1;
+}
+.waterdrop-left {
+  left: 80rpx;
+  top: 110rpx;
+}
+.waterdrop-right {
+  right: 80rpx;
+  top: 110rpx;
+}
+.header-content {
+  display: flex;
+  flex-direction: row;
+  align-items: flex-start;
+  justify-content: space-between;
+  margin: 0 40rpx 0 40rpx;
+  margin-top: 20rpx;
+}
+.date-motivation {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  margin-top: 20rpx;
+}
+.date {
+  font-size: 48rpx;
+  font-weight: 700;
+  color: #222;
+  margin-bottom: 8rpx;
+}
+.motivation {
+  font-size: 28rpx;
+  color: #4a90e2;
+  font-weight: 500;
+}
+.illustration {
+  width: 220rpx;
+  height: 140rpx;
+  margin-top: 0;
+}
+.book-img {
+  width: 100%;
+  height: 100%;
+}
+.my-course {
+  background: #fff;
+  border-radius: 24rpx;
+  margin: 40rpx 24rpx 0 24rpx;
+  box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.04);
+  padding: 32rpx 24rpx 40rpx 24rpx;
+  position: relative;
+}
+.module-title {
+  font-size: 32rpx;
+  font-weight: 600;
+  color: #222;
+  margin-bottom: 24rpx;
+}
+.empty-course {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 40rpx 0 0 0;
+}
+.empty-img {
+  width: 120rpx;
+  height: 120rpx;
+  margin-bottom: 24rpx;
+}
+.empty-tip {
+  font-size: 28rpx;
+  color: #888;
+  text-align: center;
+  margin-bottom: 32rpx;
+  white-space: pre-line;
+}
+.more-btn {
+  width: 320rpx;
+  height: 72rpx;
+  background: #fff;
+  border: 2rpx solid #3498db;
+  color: #3498db;
+  border-radius: 36rpx;
+  font-size: 30rpx;
+  font-weight: 600;
+  text-align: center;
+  line-height: 72rpx;
+  margin-top: 8rpx;
 }
+.find-course {
+  text-align: center;
+  color: #bbb;
+  font-size: 26rpx;
+  margin-top: 32rpx;
+}

+ 104 - 33
unpackage/dist/dev/mp-weixin/pages/login/index.js

@@ -4,7 +4,9 @@ const common_assets = require("../../common/assets.js");
 const _sfc_main = {
   data() {
     return {
-      isAgreed: false
+      isAgreed: false,
+      showServiceAgreement: false,
+      showPrivacyPolicy: false
     };
   },
   methods: {
@@ -15,45 +17,114 @@ const _sfc_main = {
     // 微信登录
     async handleWechatLogin() {
       if (!this.isAgreed) {
-        common_vendor.index.showToast({
-          title: "请先同意服务协议和隐私政策",
-          icon: "none"
-        });
+        common_vendor.index.showToast({ title: "请先同意用户协议和隐私政策", icon: "none" });
         return;
       }
-      common_vendor.wx$1.login({
-        success: function(res) {
-          if (res.code) {
-            common_vendor.index.__f__("log", "at pages/login/index.vue:79", res.code);
-            common_vendor.wx$1.request({
-              url: "http://localhost:9527/api/wx-login",
-              method: "POST",
-              // 设置请求头,指定请求体为 JSON 格式
-              header: {
-                "content-type": "application/json"
-              },
-              data: {
-                code: res.code
-              },
-              success: function(response) {
-                common_vendor.index.__f__("log", "at pages/login/index.vue:92", response.data);
-              },
-              fail: function(err) {
-                common_vendor.index.__f__("error", "at pages/login/index.vue:95", err);
-              }
+      try {
+        const loginResult = await new Promise((resolve, reject) => {
+          common_vendor.index.login({
+            provider: "weixin",
+            success: (res) => resolve(res),
+            fail: (err) => reject(err)
+          });
+        });
+        if (!loginResult.code) {
+          common_vendor.index.showToast({ title: "获取登录凭证失败", icon: "none" });
+          return;
+        }
+        common_vendor.index.__f__("log", "at pages/login/index.vue:88", "获取到的code:", loginResult.code);
+        const userInfoResult = await new Promise((resolve, reject) => {
+          common_vendor.index.getUserInfo({
+            provider: "weixin",
+            withCredentials: true,
+            success: (res) => resolve(res),
+            fail: (err) => reject(err)
+          });
+        });
+        if (!userInfoResult.userInfo) {
+          common_vendor.index.showToast({ title: "获取用户信息失败", icon: "none" });
+          return;
+        }
+        const loginRes = await common_vendor.index.request({
+          url: "http://localhost:9527/api/wx-login",
+          method: "POST",
+          data: {
+            code: loginResult.code,
+            nickName: userInfoResult.userInfo.nickName,
+            avatarUrl: userInfoResult.userInfo.avatarUrl,
+            gender: userInfoResult.userInfo.gender.toString(),
+            country: userInfoResult.userInfo.country,
+            province: userInfoResult.userInfo.province,
+            city: userInfoResult.userInfo.city,
+            language: userInfoResult.userInfo.language,
+            rawData: userInfoResult.rawData,
+            signature: userInfoResult.signature,
+            encryptedData: userInfoResult.encryptedData,
+            iv: userInfoResult.iv
+          },
+          header: {
+            "content-type": "application/json"
+          }
+        });
+        if (loginRes.data.errcode === 40029) {
+          common_vendor.index.__f__("error", "at pages/login/index.vue:130", "微信登录code无效,尝试重新获取");
+          const newLoginResult = await new Promise((resolve, reject) => {
+            common_vendor.index.login({
+              provider: "weixin",
+              success: (res) => resolve(res),
+              fail: (err) => reject(err)
+            });
+          });
+          if (!newLoginResult.code) {
+            throw new Error("重新获取登录凭证失败");
+          }
+          const retryRes = await common_vendor.index.request({
+            url: "http://localhost:9527/api/wx-login",
+            method: "POST",
+            data: {
+              code: newLoginResult.code,
+              nickName: userInfoResult.userInfo.nickName,
+              avatarUrl: userInfoResult.userInfo.avatarUrl,
+              gender: userInfoResult.userInfo.gender.toString(),
+              country: userInfoResult.userInfo.country,
+              province: userInfoResult.userInfo.province,
+              city: userInfoResult.userInfo.city,
+              language: userInfoResult.userInfo.language,
+              rawData: userInfoResult.rawData,
+              signature: userInfoResult.signature,
+              encryptedData: userInfoResult.encryptedData,
+              iv: userInfoResult.iv
+            },
+            header: {
+              "content-type": "application/json"
+            }
+          });
+          if (retryRes.statusCode === 200 && !retryRes.data.errcode) {
+            common_vendor.index.setStorageSync("token", retryRes.data.data.token);
+            common_vendor.index.setStorageSync("userInfo", retryRes.data.data.userInfo);
+            common_vendor.index.switchTab({
+              url: "/pages/discover/index"
             });
           } else {
-            common_vendor.index.__f__("log", "at pages/login/index.vue:99", "获取 code 失败!" + res.errMsg);
+            throw new Error(retryRes.data.errmsg || "登录失败");
           }
+        } else if (loginRes.statusCode === 200 && !loginRes.data.errcode) {
+          common_vendor.index.setStorageSync("token", loginRes.data.data.token);
+          common_vendor.index.setStorageSync("userInfo", loginRes.data.data.userInfo);
+          common_vendor.index.switchTab({
+            url: "/pages/discover/index"
+          });
+        } else {
+          throw new Error(loginRes.data.errmsg || "登录失败");
         }
-      });
+      } catch (error) {
+        common_vendor.index.__f__("error", "at pages/login/index.vue:192", "登录过程出错:", error);
+        common_vendor.index.showToast({
+          title: error.message || "登录失败,请重试",
+          icon: "none"
+        });
+      }
     },
-    // // 跳转到密码登录页面
-    // navigateToPasswordLogin() {
-    //   uni.navigateTo({
-    //     url: '/pages/login/password'
-    //   })
-    // },
     // 跳转到验证码登录页面
     navigateToVerifyCodeLogin() {
       common_vendor.index.navigateTo({

+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/login/index.wxml

@@ -1 +1 @@
- 111 <view class="login-container"><view class="login-box"><view class="logo-area"><image class="logo" src="{{a}}" mode="aspectFit"></image><text class="title">小鹅通</text><text class="slogan">让知识分享更简单</text></view><view class="login-methods"><button class="login-btn wechat" bindtap="{{b}}"><text class="iconfont icon-wechat"></text> 微信一键登录 </button><view class="other-login"><text class="divider">其他登录方式</text><view class="login-options"><view class="option" bindtap="{{c}}"><text class="iconfont icon-verify"></text><text>手机号码登录</text></view></view></view></view><view class="agreement"><checkbox-group bindchange="{{g}}"><label class="agreement-label"><checkbox checked="{{d}}" color="#007AFF"/><text class="agreement-text"> 我已阅读并同意 <text class="link" bindtap="{{e}}">《服务协议》</text> 和 <text class="link" bindtap="{{f}}">《隐私政策》</text></text></label></checkbox-group></view></view></view>
+<view class="login-container"><view class="login-box"><view class="logo-area"><image class="logo" src="{{a}}" mode="aspectFit"></image><text class="title">小鹅通</text><text class="slogan">让知识分享更简单</text></view><view class="login-methods"><button class="login-btn wechat" bindtap="{{b}}"><text class="iconfont icon-wechat"></text> 微信一键登录 </button><view class="other-login"><text class="divider">其他登录方式</text><view class="login-options"><view class="option" bindtap="{{c}}"><text class="iconfont icon-verify"></text><text>手机号码登录</text></view></view></view></view><view class="agreement"><checkbox-group bindchange="{{g}}"><label class="agreement-label"><checkbox checked="{{d}}" color="#007AFF"/><text class="agreement-text"> 我已阅读并同意 <text class="link" bindtap="{{e}}">《服务协议》</text> 和 <text class="link" bindtap="{{f}}">《隐私政策》</text></text></label></checkbox-group></view></view></view>

+ 36 - 5
unpackage/dist/dev/mp-weixin/pages/login/verify-code.js

@@ -38,9 +38,37 @@ const _sfc_main = {
         common_vendor.index.showToast({ title: "请输入正确的手机号", icon: "none" });
         return;
       }
-      this.counting = true;
-      this.countdown = 60;
-      this.startCountdown();
+      try {
+        const res = await common_vendor.index.request({
+          url: "http://localhost:9527/api/getCode",
+          method: "POST",
+          data: {
+            phone: this.phone
+          },
+          header: {
+            "content-type": "application/json"
+          }
+        });
+        common_vendor.index.__f__("log", "at pages/login/verify-code.vue:122", res.statusCode);
+        if (res.statusCode === 200) {
+          common_vendor.index.__f__("log", "at pages/login/verify-code.vue:124", "验证码接口返回:", res);
+          common_vendor.index.showToast({
+            title: "验证码已发送",
+            icon: "success"
+          });
+          this.counting = true;
+          this.countdown = 60;
+          this.startCountdown();
+        } else {
+          throw new Error(res.data.msg || "获取验证码失败");
+        }
+      } catch (error) {
+        common_vendor.index.__f__("error", "at pages/login/verify-code.vue:137", "获取验证码失败:", error);
+        common_vendor.index.showToast({
+          title: error.message || "获取验证码失败,请重试",
+          icon: "none"
+        });
+      }
     },
     startCountdown() {
       const timer = setInterval(() => {
@@ -59,14 +87,17 @@ const _sfc_main = {
         common_vendor.index.showToast({ title: "请先同意服务协议和隐私政策", icon: "none" });
         return;
       }
-      common_vendor.index.showToast({ title: "登录成功(示例)", icon: "success" });
+      common_vendor.index.switchTab({
+        url: "/pages/discover/index"
+        // 替换为实际页面路径
+      });
     },
     closePopup() {
       this.showServiceAgreement = false;
       this.showPrivacyPolicy = false;
     },
     goToWechatLogin() {
-      common_vendor.index.navigateTo({
+      common_vendor.index.switchTab({
         url: "/pages/login/index"
       });
     }

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff