feat(router): 优化周期选择和未完成表单检查逻辑
重构路由守卫中的周期选择检查逻辑,改为同步+异步结合的方式 添加未完成表单检查功能,在跳转前提示用户继续或删除 将表单检查逻辑提取为公共函数 checkUnfinishedForm
Showing
2 changed files
with
105 additions
and
38 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2022-05-26 13:57:28 | 2 | * @Date: 2022-05-26 13:57:28 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-09-08 15:52:35 | 4 | + * @LastEditTime: 2025-09-09 10:29:55 |
| 5 | * @FilePath: /data-table/src/router.js | 5 | * @FilePath: /data-table/src/router.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -43,40 +43,41 @@ const router = createRouter({ | ... | @@ -43,40 +43,41 @@ const router = createRouter({ |
| 43 | * @param {Object} to 目标路由 | 43 | * @param {Object} to 目标路由 |
| 44 | * @returns {Promise<boolean>} 是否需要周期选择 | 44 | * @returns {Promise<boolean>} 是否需要周期选择 |
| 45 | */ | 45 | */ |
| 46 | -const checkCycleSelection = async (to) => { | 46 | +const checkCycleSelection = (to) => { |
| 47 | // 如果已经在周期选择页面,不需要再检查 | 47 | // 如果已经在周期选择页面,不需要再检查 |
| 48 | if (to.path === '/cycle-selection') { | 48 | if (to.path === '/cycle-selection') { |
| 49 | - return false; | 49 | + return Promise.resolve(false); |
| 50 | } | 50 | } |
| 51 | - | 51 | + |
| 52 | // 只有在page_type=add或者没有page_type参数时才进行周期判断 | 52 | // 只有在page_type=add或者没有page_type参数时才进行周期判断 |
| 53 | if (to.query.page_type && to.query.page_type !== 'add') { | 53 | if (to.query.page_type && to.query.page_type !== 'add') { |
| 54 | - return false; | 54 | + return Promise.resolve(false); |
| 55 | } | 55 | } |
| 56 | - | 56 | + |
| 57 | // 如果没有表单代码,不需要周期选择 | 57 | // 如果没有表单代码,不需要周期选择 |
| 58 | if (!to.query.code) { | 58 | if (!to.query.code) { |
| 59 | - return false; | 59 | + return Promise.resolve(false); |
| 60 | } | 60 | } |
| 61 | - | 61 | + |
| 62 | // 如果用户已经选择过周期,不需要再选择 | 62 | // 如果用户已经选择过周期,不需要再选择 |
| 63 | if (to.query.cycle_selected === '1') { | 63 | if (to.query.cycle_selected === '1') { |
| 64 | - return false; | 64 | + return Promise.resolve(false); |
| 65 | } | 65 | } |
| 66 | - | 66 | + |
| 67 | // 如果是预览模式,不需要周期选择 | 67 | // 如果是预览模式,不需要周期选择 |
| 68 | if (to.query.model === 'preview') { | 68 | if (to.query.model === 'preview') { |
| 69 | - return false; | 69 | + return Promise.resolve(false); |
| 70 | - } | ||
| 71 | - | ||
| 72 | - try { | ||
| 73 | - const { data } = await getCycleListAPI({ form_code: to.query.code }); | ||
| 74 | - // 如果需要周期选择且有周期列表 | ||
| 75 | - return data.is_cycle && data.cycle_list && data.cycle_list.length > 0; | ||
| 76 | - } catch (error) { | ||
| 77 | - console.error('检查周期选择失败:', error); | ||
| 78 | - return false; | ||
| 79 | } | 70 | } |
| 71 | + | ||
| 72 | + return getCycleListAPI({ form_code: to.query.code }) | ||
| 73 | + .then(({ data }) => { | ||
| 74 | + // 如果需要周期选择且有周期列表 | ||
| 75 | + return data.is_cycle && data.cycle_list && data.cycle_list.length > 0; | ||
| 76 | + }) | ||
| 77 | + .catch(error => { | ||
| 78 | + console.error('检查周期选择失败:', error); | ||
| 79 | + return false; | ||
| 80 | + }); | ||
| 80 | }; | 81 | }; |
| 81 | 82 | ||
| 82 | router.beforeEach((to, from, next) => { | 83 | router.beforeEach((to, from, next) => { |
| ... | @@ -93,7 +94,32 @@ router.beforeEach((to, from, next) => { | ... | @@ -93,7 +94,32 @@ router.beforeEach((to, from, next) => { |
| 93 | next({ ...to.redirectedFrom, replace: true }); | 94 | next({ ...to.redirectedFrom, replace: true }); |
| 94 | }, 1000); | 95 | }, 1000); |
| 95 | } else { | 96 | } else { |
| 96 | - // 检查是否需要周期选择 - 使用Promise.then避免async/await | 97 | + // 先进行同步检查,避免异步问题 |
| 98 | + // 如果已经在周期选择页面,直接通过 | ||
| 99 | + if (to.path === '/cycle-selection') { | ||
| 100 | + next(); | ||
| 101 | + return; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + // 如果用户已经选择过周期,直接通过 | ||
| 105 | + if (to.query.cycle_selected === '1') { | ||
| 106 | + next(); | ||
| 107 | + return; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + // 如果不是新增状态或预览模式,直接通过 | ||
| 111 | + if ((to.query.page_type && to.query.page_type !== 'add') || to.query.model === 'preview') { | ||
| 112 | + next(); | ||
| 113 | + return; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + // 如果没有表单代码,直接通过 | ||
| 117 | + if (!to.query.code) { | ||
| 118 | + next(); | ||
| 119 | + return; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + // 异步检查周期选择 | ||
| 97 | checkCycleSelection(to).then(needsCycleSelection => { | 123 | checkCycleSelection(to).then(needsCycleSelection => { |
| 98 | if (needsCycleSelection) { | 124 | if (needsCycleSelection) { |
| 99 | // 保存目标路由到sessionStorage | 125 | // 保存目标路由到sessionStorage |
| ... | @@ -102,16 +128,16 @@ router.beforeEach((to, from, next) => { | ... | @@ -102,16 +128,16 @@ router.beforeEach((to, from, next) => { |
| 102 | query: to.query, | 128 | query: to.query, |
| 103 | params: to.params | 129 | params: to.params |
| 104 | })); | 130 | })); |
| 105 | - // 跳转到周期选择页面,保留所有原始参数 | 131 | + // 直接跳转,不使用next |
| 106 | - next({ | 132 | + router.push({ |
| 107 | path: '/cycle-selection', | 133 | path: '/cycle-selection', |
| 108 | query: to.query // 保留所有原始查询参数 | 134 | query: to.query // 保留所有原始查询参数 |
| 109 | }); | 135 | }); |
| 110 | - return; | 136 | + return; // 有周期选择需求时,直接返回,不执行后续表单检查 |
| 111 | } | 137 | } |
| 112 | - | 138 | + |
| 113 | - // 继续原有的表单检查逻辑 | 139 | + // 只有在不需要周期选择时,才执行表单检查逻辑 |
| 114 | - if (to.query.page_type === 'add' || to.query.page_type === undefined) { // 表单为新增状态, 检查是否有未完成的表单信息 | 140 | + if (to.query.page_type === 'add' || to.query.page_type === undefined) { |
| 115 | const existingCookie = Cookies.get(to.query.code); | 141 | const existingCookie = Cookies.get(to.query.code); |
| 116 | if (existingCookie && to.query.force_back !== '1') { | 142 | if (existingCookie && to.query.force_back !== '1') { |
| 117 | // TAG: 只能在进入路由之前判断,不然很多组件数据不渲染 | 143 | // TAG: 只能在进入路由之前判断,不然很多组件数据不渲染 |
| ... | @@ -133,15 +159,14 @@ router.beforeEach((to, from, next) => { | ... | @@ -133,15 +159,14 @@ router.beforeEach((to, from, next) => { |
| 133 | next(); | 159 | next(); |
| 134 | } | 160 | } |
| 135 | } else { | 161 | } else { |
| 136 | - next() | 162 | + next(); |
| 137 | } | 163 | } |
| 138 | }).catch(error => { | 164 | }).catch(error => { |
| 139 | console.error('周期选择检查失败:', error); | 165 | console.error('周期选择检查失败:', error); |
| 140 | - // 出错时继续正常流程 | 166 | + // 检查失败时,继续执行表单检查逻辑 |
| 141 | - if (to.query.page_type === 'add' || to.query.page_type === undefined) { // 表单为新增状态, 检查是否有未完成的表单信息 | 167 | + if (to.query.page_type === 'add' || to.query.page_type === undefined) { |
| 142 | const existingCookie = Cookies.get(to.query.code); | 168 | const existingCookie = Cookies.get(to.query.code); |
| 143 | if (existingCookie && to.query.force_back !== '1') { | 169 | if (existingCookie && to.query.force_back !== '1') { |
| 144 | - // TAG: 只能在进入路由之前判断,不然很多组件数据不渲染 | ||
| 145 | showConfirmDialog({ | 170 | showConfirmDialog({ |
| 146 | title: '温馨提示', | 171 | title: '温馨提示', |
| 147 | message: '您还未完成的表单,是否继续?', | 172 | message: '您还未完成的表单,是否继续?', |
| ... | @@ -149,10 +174,10 @@ router.beforeEach((to, from, next) => { | ... | @@ -149,10 +174,10 @@ router.beforeEach((to, from, next) => { |
| 149 | cancelButtonText: '删除', | 174 | cancelButtonText: '删除', |
| 150 | closeOnPopstate: false, | 175 | closeOnPopstate: false, |
| 151 | }) | 176 | }) |
| 152 | - .then(() => { // 通过后把数据绑定上去 | 177 | + .then(() => { |
| 153 | next(); | 178 | next(); |
| 154 | }) | 179 | }) |
| 155 | - .catch(() => { // 删除cookie | 180 | + .catch(() => { |
| 156 | Cookies.remove(to.query.code); | 181 | Cookies.remove(to.query.code); |
| 157 | next(); | 182 | next(); |
| 158 | }); | 183 | }); |
| ... | @@ -160,7 +185,7 @@ router.beforeEach((to, from, next) => { | ... | @@ -160,7 +185,7 @@ router.beforeEach((to, from, next) => { |
| 160 | next(); | 185 | next(); |
| 161 | } | 186 | } |
| 162 | } else { | 187 | } else { |
| 163 | - next() | 188 | + next(); |
| 164 | } | 189 | } |
| 165 | }); | 190 | }); |
| 166 | } | 191 | } | ... | ... |
| ... | @@ -38,6 +38,8 @@ import { ref, onMounted, nextTick } from 'vue'; | ... | @@ -38,6 +38,8 @@ import { ref, onMounted, nextTick } from 'vue'; |
| 38 | import { useRouter, useRoute } from 'vue-router'; | 38 | import { useRouter, useRoute } from 'vue-router'; |
| 39 | import { getCycleListAPI } from '@/api/cycle'; | 39 | import { getCycleListAPI } from '@/api/cycle'; |
| 40 | import { styleColor } from '@/constant.js'; | 40 | import { styleColor } from '@/constant.js'; |
| 41 | +import { showConfirmDialog } from 'vant'; | ||
| 42 | +import Cookies from 'js-cookie'; | ||
| 41 | 43 | ||
| 42 | const $router = useRouter(); | 44 | const $router = useRouter(); |
| 43 | const $route = useRoute(); | 45 | const $route = useRoute(); |
| ... | @@ -94,11 +96,13 @@ const getCycleList = async (form_code) => { | ... | @@ -94,11 +96,13 @@ const getCycleList = async (form_code) => { |
| 94 | // 计算高度 | 96 | // 计算高度 |
| 95 | calculatePopupContentHeight(); | 97 | calculatePopupContentHeight(); |
| 96 | } else { | 98 | } else { |
| 97 | - // 如果不需要周期选择,直接跳转到目标页面 | 99 | + // 如果不需要周期选择,检查未完成表单后跳转到目标页面 |
| 98 | const targetRoute = sessionStorage.getItem('cycle_target_route'); | 100 | const targetRoute = sessionStorage.getItem('cycle_target_route'); |
| 99 | if (targetRoute) { | 101 | if (targetRoute) { |
| 100 | sessionStorage.removeItem('cycle_target_route'); | 102 | sessionStorage.removeItem('cycle_target_route'); |
| 101 | - $router.replace(JSON.parse(targetRoute)); | 103 | + const route = JSON.parse(targetRoute); |
| 104 | + // 检查是否需要显示未完成表单弹框 | ||
| 105 | + checkUnfinishedForm(route); | ||
| 102 | } else { | 106 | } else { |
| 103 | $router.replace('/'); | 107 | $router.replace('/'); |
| 104 | } | 108 | } |
| ... | @@ -125,8 +129,9 @@ const confirmCycleSelection = () => { | ... | @@ -125,8 +129,9 @@ const confirmCycleSelection = () => { |
| 125 | }; | 129 | }; |
| 126 | // 清除临时存储 | 130 | // 清除临时存储 |
| 127 | sessionStorage.removeItem('cycle_target_route'); | 131 | sessionStorage.removeItem('cycle_target_route'); |
| 128 | - // 跳转到目标页面 | 132 | + |
| 129 | - $router.replace(route); | 133 | + // 检查是否需要显示未完成表单弹框 |
| 134 | + checkUnfinishedForm(route); | ||
| 130 | } else { | 135 | } else { |
| 131 | // 如果没有目标路由,跳转到首页 | 136 | // 如果没有目标路由,跳转到首页 |
| 132 | $router.replace({ | 137 | $router.replace({ |
| ... | @@ -140,6 +145,43 @@ const confirmCycleSelection = () => { | ... | @@ -140,6 +145,43 @@ const confirmCycleSelection = () => { |
| 140 | } | 145 | } |
| 141 | }; | 146 | }; |
| 142 | 147 | ||
| 148 | +/** | ||
| 149 | + * 检查未完成的表单信息 | ||
| 150 | + * @param {Object} route 目标路由对象 | ||
| 151 | + */ | ||
| 152 | +const checkUnfinishedForm = (route) => { | ||
| 153 | + // 只在新增状态时检查 | ||
| 154 | + if (route.query.page_type === 'add' || route.query.page_type === undefined) { | ||
| 155 | + console.warn('表单为新增状态, 检查是否有未完成的表单信息'); | ||
| 156 | + const existingCookie = Cookies.get(route.query.code); | ||
| 157 | + if (existingCookie && route.query.force_back !== '1') { | ||
| 158 | + // 显示确认对话框 | ||
| 159 | + showConfirmDialog({ | ||
| 160 | + title: '温馨提示', | ||
| 161 | + message: '您还未完成的表单,是否继续?', | ||
| 162 | + confirmButtonColor: styleColor.baseColor, | ||
| 163 | + cancelButtonText: '删除', | ||
| 164 | + closeOnPopstate: false, | ||
| 165 | + }) | ||
| 166 | + .then(() => { | ||
| 167 | + // 用户选择继续,跳转到目标页面 | ||
| 168 | + $router.replace(route); | ||
| 169 | + }) | ||
| 170 | + .catch(() => { | ||
| 171 | + // 用户选择删除,清除cookie后跳转 | ||
| 172 | + Cookies.remove(route.query.code); | ||
| 173 | + $router.replace(route); | ||
| 174 | + }); | ||
| 175 | + } else { | ||
| 176 | + // 没有未完成的表单,直接跳转 | ||
| 177 | + $router.replace(route); | ||
| 178 | + } | ||
| 179 | + } else { | ||
| 180 | + // 不是新增状态,直接跳转 | ||
| 181 | + $router.replace(route); | ||
| 182 | + } | ||
| 183 | +}; | ||
| 184 | + | ||
| 143 | onMounted(() => { | 185 | onMounted(() => { |
| 144 | const form_code = $route.query.code; | 186 | const form_code = $route.query.code; |
| 145 | if (form_code) { | 187 | if (form_code) { | ... | ... |
-
Please register or login to post a comment