Compare commits
	
		
			2 Commits
		
	
	
		
			d6d5e4619b
			...
			3ee52b2faf
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 3ee52b2faf | |
|  | d09a9a3a0e | 
|  | @ -93,6 +93,9 @@ const install = (Vue, vm) => { | ||||||
|     // 发送消息
 |     // 发送消息
 | ||||||
|     let SendMessageApi = (params = {}) => vm.$u.post('api/ChatAI/CreateChat', params); |     let SendMessageApi = (params = {}) => vm.$u.post('api/ChatAI/CreateChat', params); | ||||||
| 
 | 
 | ||||||
|  |     // 获取图形验证码
 | ||||||
|  |     let GetCaptcha = (params = {}) => vm.$u.get('api/Login/GetCaptcha', params); | ||||||
|  | 
 | ||||||
|     // 将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
 |     // 将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
 | ||||||
|     vm.$u.api = { |     vm.$u.api = { | ||||||
|         LoginApp, |         LoginApp, | ||||||
|  | @ -132,7 +135,8 @@ const install = (Vue, vm) => { | ||||||
|         getVerifyInfo, |         getVerifyInfo, | ||||||
|         getInfoByCard, |         getInfoByCard, | ||||||
|         updateCard, |         updateCard, | ||||||
|         SendMessageApi |         SendMessageApi, | ||||||
|  |         GetCaptcha | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -66,6 +66,14 @@ | ||||||
|         "navigationStyle": "custom" |         "navigationStyle": "custom" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |       "path": "pages/home/userInfo/index", | ||||||
|  |       "style": { | ||||||
|  |         "navigationBarTitleText": "个人信息", | ||||||
|  |         "enablePullDownRefresh": false, | ||||||
|  |         "navigationStyle": "custom" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|       "path": "pages/login/login/login", |       "path": "pages/login/login/login", | ||||||
|       "style": { |       "style": { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,330 @@ | ||||||
|  | <template> | ||||||
|  |   <view class="userInfo-container"> | ||||||
|  |     <view class="header"> | ||||||
|  |       <div class="header-left"> | ||||||
|  |         <u-icon | ||||||
|  |           class="header-left-icon" | ||||||
|  |           name="arrow-left" | ||||||
|  |           @click="handleLeftClick" | ||||||
|  |         ></u-icon> | ||||||
|  |       </div> | ||||||
|  |       <text class="header-title">个人信息</text> | ||||||
|  |       <div></div> | ||||||
|  |     </view> | ||||||
|  | 
 | ||||||
|  |     <view class="user-info-content"> | ||||||
|  |       <!-- 第一个卡片:头像 --> | ||||||
|  |       <view class="info-card"> | ||||||
|  |         <view class="info-item avatar-item"> | ||||||
|  |           <text class="item-label">头像</text> | ||||||
|  |           <view class="item-content avatar-content"> | ||||||
|  |             <image | ||||||
|  |               class="avatar-image" | ||||||
|  |               :src=" | ||||||
|  |                 userInfo.avatar || '/static/common/images/avatar_default.png' | ||||||
|  |               " | ||||||
|  |               mode="aspectFill" | ||||||
|  |               @click="chooseAvatar" | ||||||
|  |             ></image> | ||||||
|  |           </view> | ||||||
|  |         </view> | ||||||
|  |       </view> | ||||||
|  | 
 | ||||||
|  |       <!-- 第二个卡片:姓名和性别 --> | ||||||
|  |       <view class="info-card"> | ||||||
|  |         <view class="info-item"> | ||||||
|  |           <text class="item-label">姓名</text> | ||||||
|  |           <view class="item-content"> | ||||||
|  |             <text>{{ userInfo.name }}</text> | ||||||
|  |           </view> | ||||||
|  |         </view> | ||||||
|  | 
 | ||||||
|  |         <view class="info-item"> | ||||||
|  |           <text class="item-label">性别</text> | ||||||
|  |           <view class="item-content" @click="openPicker('gender')"> | ||||||
|  |             <text class="placeholder-text" v-if="!userInfo.gender" | ||||||
|  |               >请选择性别</text | ||||||
|  |             > | ||||||
|  |             <text v-else>{{ userInfo.gender }}</text> | ||||||
|  |             <text class="arrow-icon">></text> | ||||||
|  |           </view> | ||||||
|  |         </view> | ||||||
|  |       </view> | ||||||
|  | 
 | ||||||
|  |       <!-- 第三个卡片:归属地、高考年份、生源高中、意向学院专业 --> | ||||||
|  |       <view class="info-card"> | ||||||
|  |         <view class="info-item"> | ||||||
|  |           <text class="item-label">归属地</text> | ||||||
|  |           <view class="item-content" @click="openPicker('region')"> | ||||||
|  |             <text class="placeholder-text" v-if="!userInfo.region" | ||||||
|  |               >请选择归属地</text | ||||||
|  |             > | ||||||
|  |             <text v-else>{{ userInfo.region }}</text> | ||||||
|  |             <text class="arrow-icon">></text> | ||||||
|  |           </view> | ||||||
|  |         </view> | ||||||
|  | 
 | ||||||
|  |         <view class="info-item"> | ||||||
|  |           <text class="item-label">高考年份</text> | ||||||
|  |           <view class="item-content" @click="openPicker('examYear')"> | ||||||
|  |             <text class="placeholder-text" v-if="!userInfo.examYear" | ||||||
|  |               >请选择高考年份</text | ||||||
|  |             > | ||||||
|  |             <text v-else>{{ userInfo.examYear }}</text> | ||||||
|  |             <text class="arrow-icon">></text> | ||||||
|  |           </view> | ||||||
|  |         </view> | ||||||
|  | 
 | ||||||
|  |         <view class="info-item"> | ||||||
|  |           <text class="item-label">生源高中</text> | ||||||
|  |           <view class="item-content"> | ||||||
|  |             <input | ||||||
|  |               class="item-input" | ||||||
|  |               v-model="userInfo.highSchool" | ||||||
|  |               placeholder="请输入生源高中" | ||||||
|  |               placeholder-style="color: #CCCCCC;" | ||||||
|  |             /> | ||||||
|  |           </view> | ||||||
|  |         </view> | ||||||
|  | 
 | ||||||
|  |         <view class="info-item"> | ||||||
|  |           <text class="item-label">意向学院专业</text> | ||||||
|  |           <view class="item-content" @click="openPicker('major')"> | ||||||
|  |             <text class="placeholder-text" v-if="!userInfo.major" | ||||||
|  |               >请选择意向学院专业</text | ||||||
|  |             > | ||||||
|  |             <text v-else>{{ userInfo.major }}</text> | ||||||
|  |             <text class="arrow-icon">></text> | ||||||
|  |           </view> | ||||||
|  |         </view> | ||||||
|  |       </view> | ||||||
|  |     </view> | ||||||
|  | 
 | ||||||
|  |     <div class="user-info-footer"> | ||||||
|  |       <u-button class="user-info-footer-button" @click="handleSave"> | ||||||
|  |         保存 | ||||||
|  |       </u-button> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|  |     <!-- 选择器弹窗 --> | ||||||
|  |     <u-picker | ||||||
|  |       v-model="showPicker" | ||||||
|  |       :columns="pickerColumns" | ||||||
|  |       @confirm="onPickerConfirm" | ||||||
|  |       @cancel="showPicker = false" | ||||||
|  |     ></u-picker> | ||||||
|  |   </view> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | export default { | ||||||
|  |   components: {}, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       userInfo: { | ||||||
|  |         avatar: "/static/common/images/avatar_default.png", | ||||||
|  |         name: "杨翼", | ||||||
|  |         gender: "", | ||||||
|  |         region: "", | ||||||
|  |         examYear: "", | ||||||
|  |         highSchool: "", | ||||||
|  |         major: "", | ||||||
|  |       }, | ||||||
|  |       showPicker: false, | ||||||
|  |       currentPicker: "", | ||||||
|  |       pickerColumns: [], | ||||||
|  |       pickerData: { | ||||||
|  |         gender: ["男", "女"], | ||||||
|  |         region: ["北京", "上海", "广州", "深圳", "江西", "湖南"], | ||||||
|  |         examYear: ["2023", "2024", "2025", "2026"], | ||||||
|  |         major: [ | ||||||
|  |           "计算机科学与技术", | ||||||
|  |           "软件工程", | ||||||
|  |           "人工智能", | ||||||
|  |           "电子信息工程", | ||||||
|  |           "机械工程", | ||||||
|  |         ], | ||||||
|  |       }, | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  |   mounted() {}, | ||||||
|  |   onLoad(options) { | ||||||
|  |     if (options.userId) { | ||||||
|  |       this.userId = options.userId; | ||||||
|  |       this.getUserInfo(); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     handleLeftClick() { | ||||||
|  |       uni.navigateBack(); | ||||||
|  |     }, | ||||||
|  |     getUserInfo() { | ||||||
|  |       // 模拟获取用户信息的接口 | ||||||
|  |       console.log("获取用户ID为", this.userId, "的信息"); | ||||||
|  |       // 实际开发中这里应该调用接口获取用户信息 | ||||||
|  |     }, | ||||||
|  |     chooseAvatar() { | ||||||
|  |       uni.chooseImage({ | ||||||
|  |         count: 1, | ||||||
|  |         sizeType: ["compressed"], | ||||||
|  |         sourceType: ["album", "camera"], | ||||||
|  |         success: (res) => { | ||||||
|  |           this.userInfo.avatar = res.tempFilePaths[0]; | ||||||
|  |           // 实际开发中这里应该上传头像到服务器 | ||||||
|  |         }, | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |     openPicker(type) { | ||||||
|  |       this.currentPicker = type; | ||||||
|  |       this.pickerColumns = [this.pickerData[type]]; | ||||||
|  |       this.showPicker = true; | ||||||
|  |     }, | ||||||
|  |     onPickerConfirm(e) { | ||||||
|  |       const value = e.value[0]; | ||||||
|  |       switch (this.currentPicker) { | ||||||
|  |         case "gender": | ||||||
|  |           this.userInfo.gender = value; | ||||||
|  |           break; | ||||||
|  |         case "region": | ||||||
|  |           this.userInfo.region = value; | ||||||
|  |           break; | ||||||
|  |         case "examYear": | ||||||
|  |           this.userInfo.examYear = value; | ||||||
|  |           break; | ||||||
|  |         case "major": | ||||||
|  |           this.userInfo.major = value; | ||||||
|  |           break; | ||||||
|  |       } | ||||||
|  |       this.showPicker = false; | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .userInfo-container { | ||||||
|  |   min-height: 100vh; | ||||||
|  |   padding-bottom: calc(112rpx + env(safe-area-inset-bottom)); | ||||||
|  |   padding: 32rpx; | ||||||
|  |   padding-top: calc(88rpx + 40rpx); | ||||||
|  | 
 | ||||||
|  |   background-image: url(/static//common/images/images_bg.png); | ||||||
|  |   background-repeat: no-repeat; | ||||||
|  |   background-size: 100% 100%; | ||||||
|  |   background-position: center; | ||||||
|  | 
 | ||||||
|  |   .header { | ||||||
|  |     position: fixed; | ||||||
|  |     top: 0; | ||||||
|  |     left: 0; | ||||||
|  |     right: 0; | ||||||
|  |     // background-color: #ffffff; | ||||||
|  |     height: 88rpx; | ||||||
|  |     display: flex; | ||||||
|  |     align-items: center; | ||||||
|  |     justify-content: space-between; | ||||||
|  |     padding: 0 30rpx; | ||||||
|  |     z-index: 99; | ||||||
|  | 
 | ||||||
|  |     .header-left { | ||||||
|  |       font-size: 36rpx; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .header-title { | ||||||
|  |       font-size: 36rpx; | ||||||
|  |       font-weight: 500; | ||||||
|  |       color: #333333; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .user-info-content { | ||||||
|  |     .info-card { | ||||||
|  |       background-color: #ffffff; | ||||||
|  |       border-radius: 20rpx; | ||||||
|  |       padding: 0 32rpx; | ||||||
|  |       margin-bottom: 32rpx; | ||||||
|  | 
 | ||||||
|  |       .info-item { | ||||||
|  |         height: 110rpx; | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: space-between; | ||||||
|  |         align-items: center; | ||||||
|  |         border-bottom: 1rpx solid #f2f2f2; | ||||||
|  | 
 | ||||||
|  |         &:last-child { | ||||||
|  |           border-bottom: none; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .item-label { | ||||||
|  |           font-family: PingFang SC; | ||||||
|  |           font-size: 28rpx; | ||||||
|  |           color: #333333; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .item-content { | ||||||
|  |           flex: 1; | ||||||
|  |           display: flex; | ||||||
|  |           justify-content: flex-end; | ||||||
|  |           align-items: center; | ||||||
|  |           font-size: 28rpx; | ||||||
|  |           color: #333333; | ||||||
|  | 
 | ||||||
|  |           .item-input { | ||||||
|  |             text-align: right; | ||||||
|  |             width: 100%; | ||||||
|  |             font-size: 28rpx; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           .placeholder-text { | ||||||
|  |             color: #cccccc; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           .arrow-icon { | ||||||
|  |             margin-left: 10rpx; | ||||||
|  |             color: #cccccc; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         &.avatar-item { | ||||||
|  |           .avatar-content { | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           .avatar-image { | ||||||
|  |             width: 68rpx; | ||||||
|  |             height: 68rpx; | ||||||
|  |             border-radius: 50%; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .user-info-footer { | ||||||
|  |     position: fixed; | ||||||
|  |     bottom: 32rpx; | ||||||
|  |     left: 0; | ||||||
|  |     right: 0; | ||||||
|  |     padding: 0 32rpx; | ||||||
|  |     .user-info-footer-button { | ||||||
|  |       width: 100%; | ||||||
|  |       height: 85rpx; | ||||||
|  |       background: #4f6aff; | ||||||
|  |       color: #ffffff; | ||||||
|  |       border-radius: 16rpx; | ||||||
|  |       opacity: 0.9; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* 响应式布局 - PC端样式 */ | ||||||
|  | @media screen and (min-width: 768px) { | ||||||
|  |   .userInfo-container { | ||||||
|  |     .user-info-content { | ||||||
|  |       max-width: 1200rpx; | ||||||
|  |       margin: 0 auto; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -37,40 +37,98 @@ | ||||||
| 
 | 
 | ||||||
|       <view class="form-content"> |       <view class="form-content"> | ||||||
|         <view class="form-item"> |         <view class="form-item"> | ||||||
|           <text class="form-label">手机号</text> |           <text class="form-label" | ||||||
|  |             ><image | ||||||
|  |               class="image_icon" | ||||||
|  |               src="/static/common/images/icon_phoneNumber.png" | ||||||
|  |               mode="scaleToFill" | ||||||
|  |             /> | ||||||
|  |             手机号</text | ||||||
|  |           > | ||||||
|           <view class="input-wrapper"> |           <view class="input-wrapper"> | ||||||
|             <input |             <input | ||||||
|               type="text" |               type="text" | ||||||
|               class="form-input" |               class="form-input" | ||||||
|               placeholder="请输入手机号" |               placeholder="请输入手机号" | ||||||
|               v-model="phone" |               v-model="phone" | ||||||
|  |               @blur="validatePhone" | ||||||
|             /> |             /> | ||||||
|           </view> |           </view> | ||||||
|  |           <text v-if="errors.phone" class="error-tip">{{ errors.phone }}</text> | ||||||
|         </view> |         </view> | ||||||
| 
 | 
 | ||||||
|         <view class="form-item" v-if="isTeacher && loginType === 'psd'"> |         <view class="form-item" v-if="isTeacher && loginType === 'psd'"> | ||||||
|           <text class="form-label">密码</text> |           <text class="form-label" | ||||||
|  |             ><image | ||||||
|  |               class="image_icon" | ||||||
|  |               src="/static/common/images/icon_password.png" | ||||||
|  |               mode="scaleToFill" | ||||||
|  |             />密码</text | ||||||
|  |           > | ||||||
|           <view class="input-wrapper"> |           <view class="input-wrapper"> | ||||||
|             <input |             <input | ||||||
|               type="text" |               type="text" | ||||||
|               class="form-input" |               class="form-input" | ||||||
|               placeholder="请输入密码" |               placeholder="请输入密码" | ||||||
|               v-model="password" |               v-model="password" | ||||||
|  |               @blur="validatePassword" | ||||||
|             /> |             /> | ||||||
|           </view> |           </view> | ||||||
|  |           <text v-if="errors.password" class="error-tip">{{ | ||||||
|  |             errors.password | ||||||
|  |           }}</text> | ||||||
|         </view> |         </view> | ||||||
| 
 | 
 | ||||||
|         <view class="form-item" v-if="loginType === 'code'"> |         <view class="form-item" v-if="loginType === 'code'"> | ||||||
|           <text class="form-label">验证码</text> |           <text class="form-label"> | ||||||
|  |             <image | ||||||
|  |               class="image_icon" | ||||||
|  |               src="/static/common/images/icon_verificationCode.png" | ||||||
|  |               mode="scaleToFill" | ||||||
|  |             /> | ||||||
|  |             图形验证码</text | ||||||
|  |           > | ||||||
|  |           <view class="input-wrapper"> | ||||||
|  |             <input | ||||||
|  |               type="text" | ||||||
|  |               class="form-input" | ||||||
|  |               placeholder="请输入验证码" | ||||||
|  |               v-model="captcha" | ||||||
|  |               @blur="validateCaptcha" | ||||||
|  |             /> | ||||||
|  |             <view class="captcha-img" @click="refreshCaptcha"> | ||||||
|  |               <image | ||||||
|  |                 v-if="captchaUrl" | ||||||
|  |                 :src="captchaUrl" | ||||||
|  |                 mode="widthFix" | ||||||
|  |               ></image> | ||||||
|  |             </view> | ||||||
|  |           </view> | ||||||
|  |           <text v-if="errors.captcha" class="error-tip">{{ | ||||||
|  |             errors.captcha | ||||||
|  |           }}</text> | ||||||
|  |         </view> | ||||||
|  | 
 | ||||||
|  |         <view class="form-item" v-if="loginType === 'code'"> | ||||||
|  |           <text class="form-label"> | ||||||
|  |             <image | ||||||
|  |               class="image_icon" | ||||||
|  |               src="/static/common/images/icon_verificationCode.png" | ||||||
|  |               mode="scaleToFill" | ||||||
|  |             /> | ||||||
|  |             验证码</text | ||||||
|  |           > | ||||||
|           <view class="input-wrapper"> |           <view class="input-wrapper"> | ||||||
|             <input |             <input | ||||||
|               type="text" |               type="text" | ||||||
|               class="form-input" |               class="form-input" | ||||||
|               placeholder="请输入验证码" |               placeholder="请输入验证码" | ||||||
|               v-model="code" |               v-model="code" | ||||||
|  |               @blur="validateCode" | ||||||
|             /> |             /> | ||||||
|             <text class="get-code-btn" @click="getCode">获取验证码</text> |             <text class="get-code-btn" @click="getCode">{{ codeText }}</text> | ||||||
|           </view> |           </view> | ||||||
|  |           <text v-if="errors.code" class="error-tip">{{ errors.code }}</text> | ||||||
|         </view> |         </view> | ||||||
|       </view> |       </view> | ||||||
| 
 | 
 | ||||||
|  | @ -85,22 +143,196 @@ | ||||||
| export default { | export default { | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       isTeacher: true, // 是否是教师 |       isTeacher: false, // 是否是教师 | ||||||
|       phone: "", |       phone: "", | ||||||
|       password: "", |       password: "", | ||||||
|       code: "", |       code: "", | ||||||
|  |       captcha: "", // 图形验证码 | ||||||
|  |       captchaId: "", // 图形验证码ID | ||||||
|  |       captchaUrl: "", // 图形验证码URL,实际使用时需替换 | ||||||
|       loginType: "code", // 默认验证码登录,与图片一致 |       loginType: "code", // 默认验证码登录,与图片一致 | ||||||
|  |       codeText: "获取验证码", | ||||||
|  |       countdown: 60, | ||||||
|  |       timer: null, | ||||||
|  |       errors: { | ||||||
|  |         phone: "", | ||||||
|  |         password: "", | ||||||
|  |         code: "", | ||||||
|  |         captcha: "", | ||||||
|  |       }, | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|  |   mounted() { | ||||||
|  |     this.refreshCaptcha(); | ||||||
|  |   }, | ||||||
|  |   beforeDestroy() { | ||||||
|  |     if (this.timer) { | ||||||
|  |       clearInterval(this.timer); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     switchLoginType(type) { |     switchLoginType(type) { | ||||||
|       this.loginType = type; |       this.loginType = type; | ||||||
|  |       this.clearErrors(); | ||||||
|     }, |     }, | ||||||
|  | 
 | ||||||
|  |     // 刷新图形验证码 | ||||||
|  |     refreshCaptcha() { | ||||||
|  |       // 获取图形验证码 | ||||||
|  |       this.$u.api.GetCaptcha().then((res) => { | ||||||
|  |         console.log("获取图形验证码...", res); | ||||||
|  |         this.captchaId = res.captchaId; | ||||||
|  |         this.captchaUrl = "data:image/png;base64," + res.imageBase64; | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     // 获取短信验证码 | ||||||
|     getCode() { |     getCode() { | ||||||
|       // 获取验证码 |       if (!this.validatePhone()) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (this.loginType === "code" && !this.validateCaptcha()) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (this.codeText !== "获取验证码") { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // 模拟发送验证码 | ||||||
|  |       this.startCountdown(); | ||||||
|  | 
 | ||||||
|  |       // 实际应用中应该调用API发送验证码 | ||||||
|  |       uni.showToast({ | ||||||
|  |         title: "验证码已发送", | ||||||
|  |         icon: "success", | ||||||
|  |       }); | ||||||
|     }, |     }, | ||||||
|  | 
 | ||||||
|  |     // 开始倒计时 | ||||||
|  |     startCountdown() { | ||||||
|  |       this.countdown = 60; | ||||||
|  |       this.codeText = `${this.countdown}秒后重新获取`; | ||||||
|  |       this.timer = setInterval(() => { | ||||||
|  |         this.countdown--; | ||||||
|  |         this.codeText = `${this.countdown}秒后重新获取`; | ||||||
|  |         if (this.countdown <= 0) { | ||||||
|  |           clearInterval(this.timer); | ||||||
|  |           this.codeText = "获取验证码"; | ||||||
|  |         } | ||||||
|  |       }, 1000); | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     // 校验手机号 | ||||||
|  |     validatePhone() { | ||||||
|  |       if (!this.phone) { | ||||||
|  |         this.errors.phone = "请输入手机号"; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (!/^1[3-9]\d{9}$/.test(this.phone)) { | ||||||
|  |         this.errors.phone = "手机号格式不正确"; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       this.errors.phone = ""; | ||||||
|  |       return true; | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     // 校验密码 | ||||||
|  |     validatePassword() { | ||||||
|  |       if (!this.password) { | ||||||
|  |         this.errors.password = "请输入密码"; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // if (this.password.length < 6) { | ||||||
|  |       //   this.errors.password = "密码不能少于6位"; | ||||||
|  |       //   return false; | ||||||
|  |       // } | ||||||
|  | 
 | ||||||
|  |       this.errors.password = ""; | ||||||
|  |       return true; | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     // 校验图形验证码 | ||||||
|  |     validateCaptcha() { | ||||||
|  |       if (!this.captcha) { | ||||||
|  |         this.errors.captcha = "请输入图形验证码"; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // if (this.captcha.length < 4) { | ||||||
|  |       //   this.errors.captcha = "图形验证码错误请重新输入"; | ||||||
|  |       //   return false; | ||||||
|  |       // } | ||||||
|  | 
 | ||||||
|  |       // 实际应用中应该验证图形验证码是否正确 | ||||||
|  |       this.errors.captcha = ""; | ||||||
|  |       return true; | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     // 校验短信验证码 | ||||||
|  |     validateCode() { | ||||||
|  |       if (!this.code) { | ||||||
|  |         this.errors.code = "请输入验证码"; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (this.code.length < 4) { | ||||||
|  |         this.errors.code = "验证码错误请重新输入"; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       this.errors.code = ""; | ||||||
|  |       return true; | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     // 清除所有错误提示 | ||||||
|  |     clearErrors() { | ||||||
|  |       this.errors = { | ||||||
|  |         phone: "", | ||||||
|  |         password: "", | ||||||
|  |         code: "", | ||||||
|  |         captcha: "", | ||||||
|  |       }; | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     // 登录 | ||||||
|     login() { |     login() { | ||||||
|       // 登录 |       let isValid = true; | ||||||
|  | 
 | ||||||
|  |       // 校验手机号 | ||||||
|  |       if (!this.validatePhone()) { | ||||||
|  |         isValid = false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // 根据登录类型校验其他字段 | ||||||
|  |       if (this.loginType === "psd") { | ||||||
|  |         if (!this.validatePassword()) { | ||||||
|  |           isValid = false; | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         if (!this.validateCaptcha()) { | ||||||
|  |           isValid = false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!this.validateCode()) { | ||||||
|  |           isValid = false; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (!isValid) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // 校验通过,执行登录 | ||||||
|  |       uni.showLoading({ | ||||||
|  |         title: "登录中...", | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  | @ -116,7 +348,7 @@ export default { | ||||||
|   flex-direction: column; |   flex-direction: column; | ||||||
|   box-sizing: border-box; |   box-sizing: border-box; | ||||||
| 
 | 
 | ||||||
|   background-image: url(/static//common/images/images_bg.png); |   background-image: url(/static/common/images/images_bg.png); | ||||||
|   background-repeat: no-repeat; |   background-repeat: no-repeat; | ||||||
|   background-size: 100% 100%; |   background-size: 100% 100%; | ||||||
|   background-position: 50%; |   background-position: 50%; | ||||||
|  | @ -130,7 +362,7 @@ export default { | ||||||
|     .logo-container { |     .logo-container { | ||||||
|       display: flex; |       display: flex; | ||||||
|       align-items: center; |       align-items: center; | ||||||
|       margin-bottom: 20rpx; |       margin-bottom: 32rpx; | ||||||
| 
 | 
 | ||||||
|       .logo-icon { |       .logo-icon { | ||||||
|         width: 48rpx; |         width: 48rpx; | ||||||
|  | @ -217,23 +449,18 @@ export default { | ||||||
|         .form-label { |         .form-label { | ||||||
|           display: block; |           display: block; | ||||||
|           position: relative; |           position: relative; | ||||||
|           padding-left: 30rpx; |           // padding-left: 30rpx; | ||||||
|           font-family: PingFang SC; |           font-family: PingFang SC; | ||||||
|           font-size: 28rpx; |           font-size: 28rpx; | ||||||
|           color: #333333; |           color: #333333; | ||||||
|           margin-bottom: 16rpx; |           margin-bottom: 16rpx; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|           &::before { |         .image_icon { | ||||||
|             content: ""; |           width: 28rpx; | ||||||
|             position: absolute; |           height: 28rpx; | ||||||
|             left: 0; |           vertical-align: text-top; | ||||||
|             top: 50%; |           margin-right: 16rpx; | ||||||
|             transform: translateY(-50%); |  | ||||||
|             width: 20rpx; |  | ||||||
|             height: 20rpx; |  | ||||||
|             border: 2rpx solid #4370fe; |  | ||||||
|             border-radius: 4rpx; |  | ||||||
|           } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         &:nth-child(2) { |         &:nth-child(2) { | ||||||
|  | @ -264,13 +491,38 @@ export default { | ||||||
|             right: 0; |             right: 0; | ||||||
|             top: 50%; |             top: 50%; | ||||||
|             transform: translateY(-50%); |             transform: translateY(-50%); | ||||||
|  |             width: 220rpx; | ||||||
|             height: 60rpx; |             height: 60rpx; | ||||||
|             line-height: 60rpx; |             line-height: 60rpx; | ||||||
|             padding: 0 30rpx; |             padding-left: 30rpx; | ||||||
|             color: #4370fe; |             color: #4370fe; | ||||||
|             font-size: 28rpx; |             font-size: 28rpx; | ||||||
|             border-left: 1px solid #557bf9; |             border-left: 1px solid #b7c1ff; | ||||||
|           } |           } | ||||||
|  | 
 | ||||||
|  |           .captcha-img { | ||||||
|  |             position: absolute; | ||||||
|  |             right: 0; | ||||||
|  |             top: 50%; | ||||||
|  |             transform: translateY(-50%); | ||||||
|  |             height: 60rpx; | ||||||
|  |             width: 220rpx; | ||||||
|  |             padding-left: 30rpx; | ||||||
|  |             border-left: 1px solid #b7c1ff; | ||||||
|  | 
 | ||||||
|  |             image { | ||||||
|  |               width: 80%; | ||||||
|  |               height: 100%; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .error-tip { | ||||||
|  |           display: block; | ||||||
|  |           font-size: 24rpx; | ||||||
|  |           color: #FF6481; | ||||||
|  |           margin-top: 10rpx; | ||||||
|  |           padding-left: 10rpx; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.3 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.1 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.7 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 31 KiB | 
		Loading…
	
		Reference in New Issue