hookehuyr

refactor(登录认证): 重构登录认证流程并简化照片查询入口

移除照片查询页面的登录校验,改为统一由路由守卫处理
重构登录跳转逻辑,增加安全导航函数处理重定向
将token有效期从7天改为3天
1 /* 1 /*
2 * @Date: 2025-10-30 10:29:15 2 * @Date: 2025-10-30 10:29:15
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-11-11 12:56:04 4 + * @LastEditTime: 2025-11-11 22:10:22
5 * @FilePath: /stdj_h5/src/router/index.js 5 * @FilePath: /stdj_h5/src/router/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -98,14 +98,18 @@ router.beforeEach((to, from, next) => { ...@@ -98,14 +98,18 @@ router.beforeEach((to, from, next) => {
98 } 98 }
99 99
100 /** 100 /**
101 - * 访问控制:仅在进入 /studentInfo 时校验登录状态 101 + * 访问控制:除首页('/')与登录页外,其余页面均需登录
102 * 说明:优先读取 Cookie 中的 token;若不存在则回退读取本地存储 token,避免重复登录。 102 * 说明:优先读取 Cookie 中的 token;若不存在则回退读取本地存储 token,避免重复登录。
103 */ 103 */
104 - const has_token_cookie = !!Cookies.get('token-stdj') 104 + const token_cookie = Cookies.get('token-stdj')
105 - const is_login = has_token_cookie 105 + const is_login = !!(token_cookie)
106 106
107 - if (to.path === '/studentInfo' && !is_login) { 107 + // 白名单:无需登录校验的路径
108 - // 关键:在重定向前关闭或重置上一跳的loading,避免计数残留 108 + const white_list = ['/', '/login']
109 + const need_auth = !white_list.includes(to.path)
110 +
111 + if (need_auth && !is_login) {
112 + // 在重定向前关闭或重置上一跳的loading,避免计数残留
109 try { 113 try {
110 const loading = useLoadingStore() 114 const loading = useLoadingStore()
111 loading.reset() 115 loading.reset()
...@@ -116,7 +120,6 @@ router.beforeEach((to, from, next) => { ...@@ -116,7 +120,6 @@ router.beforeEach((to, from, next) => {
116 return 120 return
117 } 121 }
118 122
119 - // 其他页面不做登录校验
120 next() 123 next()
121 }) 124 })
122 125
......
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
125 <div class="photo-section" @click="handlePhotoClick"> 125 <div class="photo-section" @click="handlePhotoClick">
126 <div class="photo-content"> 126 <div class="photo-content">
127 <div class="photo-title">照片查询下载</div> 127 <div class="photo-title">照片查询下载</div>
128 - <div class="more-button"><span class="more-text">身份验证</span></div> 128 + <div class="more-button"><span class="more-text">进入</span></div>
129 </div> 129 </div>
130 </div> 130 </div>
131 </div> 131 </div>
...@@ -184,7 +184,6 @@ import VideoPlayer from '@/components/VideoPlayer.vue' ...@@ -184,7 +184,6 @@ import VideoPlayer from '@/components/VideoPlayer.vue'
184 import { useTitle } from '@vueuse/core'; 184 import { useTitle } from '@vueuse/core';
185 import { useRouter } from 'vue-router' 185 import { useRouter } from 'vue-router'
186 import { showToast } from 'vant' 186 import { showToast } from 'vant'
187 -import Cookies from 'js-cookie'
188 187
189 // 导入接口 188 // 导入接口
190 import { homePageAPI } from '@/api/index.js' 189 import { homePageAPI } from '@/api/index.js'
...@@ -653,16 +652,9 @@ const dismissSwipeHint = () => { ...@@ -653,16 +652,9 @@ const dismissSwipeHint = () => {
653 * 说明:未登录跳转登录页;已登录进入戒子信息页面。 652 * 说明:未登录跳转登录页;已登录进入戒子信息页面。
654 * @returns {void} 653 * @returns {void}
655 */ 654 */
656 -// 登录状态获取
657 -const hasLogin = computed(() => Boolean(Cookies.get('token-stdj')))
658 655
659 const handlePhotoClick = () => { 656 const handlePhotoClick = () => {
660 - // 判断是否已登录
661 - if (hasLogin.value) {
662 router.push('/studentInfo') 657 router.push('/studentInfo')
663 - } else {
664 - router.push('/login')
665 - }
666 } 658 }
667 </script> 659 </script>
668 660
......
1 <!-- 1 <!--
2 * @Date: 2025-11-10 18:08:59 2 * @Date: 2025-11-10 18:08:59
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-11-11 15:51:10 4 + * @LastEditTime: 2025-11-11 22:45:33
5 * @FilePath: /stdj_h5/src/views/Login.vue 5 * @FilePath: /stdj_h5/src/views/Login.vue
6 * @Description: 登录页 6 * @Description: 登录页
7 --> 7 -->
...@@ -162,6 +162,24 @@ const on_send_sms = async function () { ...@@ -162,6 +162,24 @@ const on_send_sms = async function () {
162 } 162 }
163 } 163 }
164 164
165 +const safe_navigate = function () {
166 + // 跳转目标处理:兼容 redirect 携带 query/hash 的场景
167 + // 说明:当地址形如 /login?redirect=/masters?pid=3651943 时,使用字符串导航更安全;
168 + // 同时解析并保留查询与哈希,避免对象形式 path 丢失查询参数。
169 + const redirect_raw = String(route.query.redirect || '').trim()
170 + let redirect_target = '/home'
171 + if (redirect_raw) {
172 + try {
173 + const url = new URL(redirect_raw, window.location.origin)
174 + redirect_target = url.pathname + url.search + url.hash
175 + } catch (err) {
176 + // 若不是标准URL(仅相对路径),直接使用或回退到默认页
177 + redirect_target = redirect_raw.startsWith('/') ? redirect_raw : '/home'
178 + }
179 + }
180 + router.replace(redirect_target)
181 +}
182 +
165 /** 183 /**
166 * 登录 184 * 登录
167 * @returns {Promise<void>} 185 * @returns {Promise<void>}
...@@ -181,10 +199,12 @@ const on_login = async function () { ...@@ -181,10 +199,12 @@ const on_login = async function () {
181 const { code, data } = await loginAPI({ mobile: phone.value, code: code.value }) 199 const { code, data } = await loginAPI({ mobile: phone.value, code: code.value })
182 if (code) { 200 if (code) {
183 // 登录成功后,将token存储到cookie中 201 // 登录成功后,将token存储到cookie中
184 - Cookies.set('token-stdj', data.token, { expires: 7 }) 202 + Cookies.set('token-stdj', data.token, { expires: 3 })
185 showSuccessToast('登录成功') 203 showSuccessToast('登录成功')
186 - // 跳转戒子详情页 204 + setTimeout(() => {
187 - router.replace({ path: route.query.redirect }) 205 + // 登录成功后,跳转至 redirect 目标页或默认首页
206 + safe_navigate()
207 + }, 1000)
188 } 208 }
189 } catch (e) { 209 } catch (e) {
190 showFailToast('网络异常,请稍后重试') 210 showFailToast('网络异常,请稍后重试')
......