hookehuyr

fix: 更新登录页面图标链接

更新美乐爱觉教育登录页面的品牌图标,使用新版本的logo图片地址。
1 <template> 1 <template>
2 <div 2 <div
3 - class="min-h-screen flex flex-col bg-gradient-to-br from-green-50 via-teal-50 to-blue-50 py-8 px-4 sm:px-6 lg:px-8" 3 + class="flex min-h-screen flex-col bg-gradient-to-br from-green-50 via-teal-50 to-blue-50 px-4 py-8 sm:px-6 lg:px-8"
4 > 4 >
5 - <div class="sm:mx-auto sm:w-full sm:max-w-md text-center"> 5 + <div class="text-center sm:mx-auto sm:w-full sm:max-w-md">
6 - <van-icon name="https://cdn.ipadbiz.cn/mlaj/icon/behalo-logo-1.png?imageMogr2/thumbnail/200x/strip/quality/70" size="10rem" style="margin-bottom: 0.5rem;" /> 6 + <van-icon
7 - <h1 class="text-center text-3xl font-bold text-gray-800 mb-2">美乐爱觉教育</h1> 7 + name="https://cdn.ipadbiz.cn/mlaj/icon/behalo-logo-2.png?imageMogr2/thumbnail/200x/strip/quality/70"
8 + size="10rem"
9 + style="margin-bottom: 0.5rem"
10 + />
11 + <h1 class="mb-2 text-center text-3xl font-bold text-gray-800">美乐爱觉教育</h1>
8 <!-- <h2 class="text-center text-xl font-medium text-gray-600">欢迎回来</h2> --> 12 <!-- <h2 class="text-center text-xl font-medium text-gray-600">欢迎回来</h2> -->
9 </div> 13 </div>
10 14
11 <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md"> 15 <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
12 - <FrostedGlass class="py-8 px-6 rounded-lg"> 16 + <FrostedGlass class="rounded-lg px-6 py-8">
13 <div 17 <div
14 v-if="error" 18 v-if="error"
15 - class="mb-4 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-md" 19 + class="mb-4 rounded-md border border-red-400 bg-red-100 px-4 py-3 text-red-700"
16 > 20 >
17 {{ error }} 21 {{ error }}
18 </div> 22 </div>
...@@ -35,7 +39,7 @@ ...@@ -35,7 +39,7 @@
35 @input="mobile = $event.target.value.replace(/\D/g, '')" 39 @input="mobile = $event.target.value.replace(/\D/g, '')"
36 @focus="handleInputFocus" 40 @focus="handleInputFocus"
37 @blur="validatePhone" 41 @blur="validatePhone"
38 - class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500" 42 + class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-green-500 focus:outline-none focus:ring-green-500"
39 /> 43 />
40 </div> 44 </div>
41 45
...@@ -51,7 +55,7 @@ ...@@ -51,7 +55,7 @@
51 autocomplete="current-password" 55 autocomplete="current-password"
52 required 56 required
53 placeholder="请输入6位密码" 57 placeholder="请输入6位密码"
54 - class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500" 58 + class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-green-500 focus:outline-none focus:ring-green-500"
55 /> 59 />
56 </div> 60 </div>
57 61
...@@ -67,13 +71,13 @@ ...@@ -67,13 +71,13 @@
67 required 71 required
68 maxlength="6" 72 maxlength="6"
69 placeholder="请输入验证码" 73 placeholder="请输入验证码"
70 - class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500" 74 + class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-green-500 focus:outline-none focus:ring-green-500"
71 /> 75 />
72 <button 76 <button
73 type="button" 77 type="button"
74 :disabled="countdown > 0 || !isPhoneValid" 78 :disabled="countdown > 0 || !isPhoneValid"
75 @click="sendVerificationCode" 79 @click="sendVerificationCode"
76 - class="mt-1 px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap" 80 + class="mt-1 whitespace-nowrap rounded-md border border-transparent bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
77 > 81 >
78 {{ countdown > 0 ? `${countdown}秒后重试` : '获取验证码' }} 82 {{ countdown > 0 ? `${countdown}秒后重试` : '获取验证码' }}
79 </button> 83 </button>
...@@ -104,10 +108,10 @@ ...@@ -104,10 +108,10 @@
104 <button 108 <button
105 type="submit" 109 type="submit"
106 :disabled="loading" 110 :disabled="loading"
107 - class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500" 111 + class="flex w-full justify-center rounded-md border border-transparent bg-gradient-to-r from-green-500 to-green-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:from-green-600 hover:to-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2"
108 - :class="{ 'opacity-70 cursor-not-allowed': loading }" 112 + :class="{ 'cursor-not-allowed opacity-70': loading }"
109 > 113 >
110 - {{ loading ? "登录中..." : "登录/注册BEHALO宇宙账号" }} 114 + {{ loading ? '登录中...' : '登录/注册BEHALO宇宙账号' }}
111 </button> 115 </button>
112 </div> 116 </div>
113 </form> 117 </form>
...@@ -157,11 +161,11 @@ ...@@ -157,11 +161,11 @@
157 </router-link> 161 </router-link>
158 </p> 162 </p>
159 </div> --> 163 </div> -->
160 - <div class="text-center mt-6"> 164 + <div class="mt-6 text-center">
161 <p class="text-sm text-gray-600"> 165 <p class="text-sm text-gray-600">
162 登录即表示同意 166 登录即表示同意
163 <span 167 <span
164 - class="font-medium text-green-600 hover:text-green-500 cursor-pointer" 168 + class="cursor-pointer font-medium text-green-600 hover:text-green-500"
165 @click="userAgreementRef.openAgreement()" 169 @click="userAgreementRef.openAgreement()"
166 > 170 >
167 《美乐爱觉宇宙用户协议》 171 《美乐爱觉宇宙用户协议》
...@@ -170,10 +174,15 @@ ...@@ -170,10 +174,15 @@
170 </p> 174 </p>
171 </div> 175 </div>
172 176
173 - <div class="mt-6 flex justify-center items-center gap-4" style="flex-direction: column;"> 177 + <div class="mt-6 flex items-center justify-center gap-4" style="flex-direction: column">
174 <div class="text-sm font-medium text-gray-600">其他登录方式</div> 178 <div class="text-sm font-medium text-gray-600">其他登录方式</div>
175 <div> 179 <div>
176 - <img :src="weixinLogo" alt="微信登录" style="width: 40px; height: 40px; border-radius: 8px;" @click="handleWxLoginClick"> 180 + <img
181 + :src="weixinLogo"
182 + alt="微信登录"
183 + style="width: 40px; height: 40px; border-radius: 8px"
184 + @click="handleWxLoginClick"
185 + />
177 </div> 186 </div>
178 </div> 187 </div>
179 </FrostedGlass> 188 </FrostedGlass>
...@@ -182,122 +191,126 @@ ...@@ -182,122 +191,126 @@
182 </template> 191 </template>
183 192
184 <script setup> 193 <script setup>
185 -import { ref } from "vue"; 194 +import { ref } from 'vue'
186 -import { useRoute, useRouter } from "vue-router"; 195 +import { useRoute, useRouter } from 'vue-router'
187 -import FrostedGlass from "@/components/effects/FrostedGlass.vue"; 196 +import FrostedGlass from '@/components/effects/FrostedGlass.vue'
188 -import { useAuth } from "@/contexts/auth"; 197 +import { useAuth } from '@/contexts/auth'
189 -import { loginAPI, getUserInfoAPI } from "@/api/users"; 198 +import { loginAPI, getUserInfoAPI } from '@/api/users'
190 -import { useTitle } from "@vueuse/core"; 199 +import { useTitle } from '@vueuse/core'
191 -import { smsAPI } from "@/api/common"; 200 +import { smsAPI } from '@/api/common'
192 -import { showToast } from "vant"; 201 +import { showToast } from 'vant'
193 -import UserAgreement from "@/components/common/UserAgreement.vue"; 202 +import UserAgreement from '@/components/common/UserAgreement.vue'
194 -import { setAuthHeaders } from "@/utils/axios"; 203 +import { setAuthHeaders } from '@/utils/axios'
195 -import { applyUserInfoAuth } from "@/utils/auth_user_info"; 204 +import { applyUserInfoAuth } from '@/utils/auth_user_info'
196 import weixinLogo from '@/assets/images/weixin_logo_lg.jpeg' 205 import weixinLogo from '@/assets/images/weixin_logo_lg.jpeg'
197 import { startWxAuth } from '@/router/guards' 206 import { startWxAuth } from '@/router/guards'
198 import { wxInfo } from '@/utils/tools' 207 import { wxInfo } from '@/utils/tools'
199 208
200 -const userAgreementRef = ref(null); 209 +const userAgreementRef = ref(null)
201 210
202 const handleInputFocus = () => { 211 const handleInputFocus = () => {
203 setTimeout(() => { 212 setTimeout(() => {
204 // 使用平滑滚动将页面向上移动200px(根据实际按钮区域高度调整) 213 // 使用平滑滚动将页面向上移动200px(根据实际按钮区域高度调整)
205 window.scrollTo({ 214 window.scrollTo({
206 top: 150, 215 top: 150,
207 - behavior: 'smooth' 216 + behavior: 'smooth',
208 - }); 217 + })
209 - }, 100); 218 + }, 100)
210 -}; 219 +}
211 - 220 +
212 -const $route = useRoute(); 221 +const $route = useRoute()
213 -useTitle($route.meta.title); 222 +useTitle($route.meta.title)
214 - 223 +
215 -const router = useRouter(); 224 +const router = useRouter()
216 -const { login } = useAuth(); 225 +const { login } = useAuth()
217 - 226 +
218 -const mobile = ref(""); 227 +const mobile = ref('')
219 -const password = ref(""); 228 +const password = ref('')
220 -const verificationCode = ref(""); 229 +const verificationCode = ref('')
221 -const error = ref(""); 230 +const error = ref('')
222 -const loading = ref(false); 231 +const loading = ref(false)
223 -const isVerifyCodeLogin = ref(true); 232 +const isVerifyCodeLogin = ref(true)
224 -const countdown = ref(0); 233 +const countdown = ref(0)
225 -const isPhoneValid = ref(false); 234 +const isPhoneValid = ref(false)
226 235
227 const validatePhone = () => { 236 const validatePhone = () => {
228 if (!mobile.value) { 237 if (!mobile.value) {
229 - error.value = '请输入手机号'; 238 + error.value = '请输入手机号'
230 - isPhoneValid.value = false; 239 + isPhoneValid.value = false
231 - return; 240 + return
232 } 241 }
233 242
234 if (!/^1[3-9]\d{9}$/.test(mobile.value)) { 243 if (!/^1[3-9]\d{9}$/.test(mobile.value)) {
235 - error.value = '请输入正确的手机号'; 244 + error.value = '请输入正确的手机号'
236 - isPhoneValid.value = false; 245 + isPhoneValid.value = false
237 - return; 246 + return
238 } 247 }
239 248
240 - error.value = ''; 249 + error.value = ''
241 - isPhoneValid.value = true; 250 + isPhoneValid.value = true
242 -}; 251 +}
243 252
244 const startCountdown = () => { 253 const startCountdown = () => {
245 - countdown.value = 60; 254 + countdown.value = 60
246 const timer = setInterval(() => { 255 const timer = setInterval(() => {
247 - countdown.value--; 256 + countdown.value--
248 if (countdown.value <= 0) { 257 if (countdown.value <= 0) {
249 - clearInterval(timer); 258 + clearInterval(timer)
250 } 259 }
251 - }, 1000); 260 + }, 1000)
252 -}; 261 +}
253 262
254 /** 263 /**
255 * @description 点击微信图标触发微信授权登录 264 * @description 点击微信图标触发微信授权登录
256 * @returns {void} 265 * @returns {void}
257 */ 266 */
258 const handleWxLoginClick = async () => { 267 const handleWxLoginClick = async () => {
259 - // 非微信环境提示并不触发授权 268 + // 非微信环境提示并不触发授权
260 - if (!import.meta.env.DEV && !wxInfo().isWeiXin) { 269 + if (!import.meta.env.DEV && !wxInfo().isWeiXin) {
261 - showToast('请在微信内打开以完成微信授权登录'); 270 + showToast('请在微信内打开以完成微信授权登录')
262 - return; 271 + return
263 - } 272 + }
264 273
265 - try { 274 + try {
266 - // 手动发起微信授权流程(guards.js中实现) 275 + // 手动发起微信授权流程(guards.js中实现)
267 - await startWxAuth(); 276 + await startWxAuth()
268 - } catch (e) { 277 + } catch (e) {
269 - console.error('微信授权触发失败:', e); 278 + console.error('微信授权触发失败:', e)
270 - showToast('微信授权失败,请稍后重试'); 279 + showToast('微信授权失败,请稍后重试')
271 - } 280 + }
272 -}; 281 +}
273 282
274 const sendVerificationCode = async () => { 283 const sendVerificationCode = async () => {
275 if (!isPhoneValid.value) { 284 if (!isPhoneValid.value) {
276 - return; 285 + return
277 } 286 }
278 287
279 try { 288 try {
280 - const { code } = await smsAPI({ mobile: mobile.value }); 289 + const { code } = await smsAPI({ mobile: mobile.value })
281 if (code === 1) { 290 if (code === 1) {
282 - showToast('验证码已发送'); 291 + showToast('验证码已发送')
283 - startCountdown(); 292 + startCountdown()
284 - return; 293 + return
285 } 294 }
286 } catch (err) { 295 } catch (err) {
287 - console.error('Send verification code error:', err); 296 + console.error('Send verification code error:', err)
288 - error.value = '发送验证码失败,请稍后重试'; 297 + error.value = '发送验证码失败,请稍后重试'
289 } 298 }
290 -}; 299 +}
291 300
292 const handleSubmit = async () => { 301 const handleSubmit = async () => {
293 - if (!mobile.value || (!isVerifyCodeLogin.value && !password.value) || (isVerifyCodeLogin.value && !verificationCode.value)) { 302 + if (
294 - error.value = "请填写所有字段"; 303 + !mobile.value ||
295 - return; 304 + (!isVerifyCodeLogin.value && !password.value) ||
305 + (isVerifyCodeLogin.value && !verificationCode.value)
306 + ) {
307 + error.value = '请填写所有字段'
308 + return
296 } 309 }
297 310
298 try { 311 try {
299 - error.value = ""; 312 + error.value = ''
300 - loading.value = true; 313 + loading.value = true
301 314
302 // 调用登录接口 315 // 调用登录接口
303 const response = await loginAPI({ 316 const response = await loginAPI({
...@@ -305,38 +318,36 @@ const handleSubmit = async () => { ...@@ -305,38 +318,36 @@ const handleSubmit = async () => {
305 ...(isVerifyCodeLogin.value 318 ...(isVerifyCodeLogin.value
306 ? { sms_code: verificationCode.value } 319 ? { sms_code: verificationCode.value }
307 : { password: password.value }), 320 : { password: password.value }),
308 - }); 321 + })
309 322
310 if (response.code !== 1) { 323 if (response.code !== 1) {
311 - error.value = response.msg || "登录失败,请检查您的输入项"; 324 + error.value = response.msg || '登录失败,请检查您的输入项'
312 - return; 325 + return
313 - } else {
314 - applyUserInfoAuth(response, { set_auth_headers: setAuthHeaders, storage: localStorage })
315 } 326 }
327 + applyUserInfoAuth(response, { set_auth_headers: setAuthHeaders, storage: localStorage })
316 328
317 - const { code, data } = await getUserInfoAPI(); 329 + const { code, data } = await getUserInfoAPI()
318 if (code === 1) { 330 if (code === 1) {
319 // 登录成功,更新auth状态,传递完整的用户信息包括打卡信息 331 // 登录成功,更新auth状态,传递完整的用户信息包括打卡信息
320 - const success = login({ ...data.user, ...data.checkin }); 332 + const success = login({ ...data.user, ...data.checkin })
321 333
322 if (success) { 334 if (success) {
323 // 如果有重定向参数,登录成功后跳转到对应页面 335 // 如果有重定向参数,登录成功后跳转到对应页面
324 // 说明:redirect 是经过 URL 编码的,需要先解码再跳转 336 // 说明:redirect 是经过 URL 编码的,需要先解码再跳转
325 - const redirect_raw = $route.query.redirect; 337 + const redirect_raw = $route.query.redirect
326 - const redirect = redirect_raw ? decodeURIComponent(redirect_raw) : "/"; 338 + const redirect = redirect_raw ? decodeURIComponent(redirect_raw) : '/'
327 - router.push(redirect); 339 + router.push(redirect)
328 } else { 340 } else {
329 - error.value = "登录失败,请检查您的输入项"; 341 + error.value = '登录失败,请检查您的输入项'
330 } 342 }
331 } 343 }
332 -
333 } catch (err) { 344 } catch (err) {
334 - console.error("Login error:", err); 345 + console.error('Login error:', err)
335 - error.value = "登录时发生错误"; 346 + error.value = '登录时发生错误'
336 } finally { 347 } finally {
337 - loading.value = false; 348 + loading.value = false
338 } 349 }
339 -}; 350 +}
340 351
341 // 说明:授权回跳的重定向处理已移动到路由层 352 // 说明:授权回跳的重定向处理已移动到路由层
342 </script> 353 </script>
......