feat: 优化账户切换时的页面状态一致性,增加登录回跳校验和课程阅读新逻辑

- 增加账户状态监听定时器,页面切换时自动校验账户归属,避免跨账户操作
- 新增登录回跳路径校验函数,限制仅允许指定页面回跳,防止非法跳转
- 课程页改为整篇连续阅读,底部仅一次标记已读,兼容历史记录
- 完善助手、对比页、资料填写页等多处的账户状态校验逻辑,防止错版数据提交
- 优化账户资料请求逻辑,增加版本校验,避免旧请求覆盖新数据
This commit is contained in:
hujun
2026-10-07 10:01:05 +08:00
parent 1723363b7e
commit 71b3c25695
37 changed files with 1389 additions and 323 deletions
+26 -4
View File
@@ -18,6 +18,7 @@
<script setup lang="uts">
import { wanAmountValid } from '@/services/money.uts'
import { getSession } from '@/services/api.uts'
import { usePageLayout } from '@/services/layout.uts'
import AppHeader from '@/components/AppHeader.uvue'
import { submitAssessment } from '@/packages/finance/services/api.uts'
@@ -30,6 +31,17 @@
const assessmentType = ref('personal')
const sections = ref<InfoSection[]>([])
const payload = ref<UTSJSONObject>({ source: 'mobile', confirmed: false })
let visible = false; let generation = 0; let ownerToken = ''; let accountTimer = 0
const stopAccountTimer = () => { if (accountTimer != 0) clearInterval(accountTimer); accountTimer = 0 }
const clearView = () => { hasInput.value = false; sections.value = []; payload.value = { source: 'mobile', confirmed: false }; submitting.value = false }
const sameOwner = (): boolean => {
if (!visible) return false
if (ownerToken.length > 0 && getSession()?.getString('token') == ownerToken) return true
generation++; clearView(); clearAssessmentFlow(); stopAccountTimer()
if (getSession() == null) uni.redirectTo({ url: '/packages/account/login/login' })
else uni.showToast({ title: '账户已变化,请重新填写。', icon: 'none' })
return false
}
const mask = (value: string, left: number, right: number): string => { if (value.length <= left + right) return value; return value.substring(0, left) + '****' + value.substring(value.length - right) }
const displayValue = (saved: UTSJSONObject, key: string): string => { const value = draftText(saved, key); return value.length > 0 ? value : '未填写' }
const appendRow = (rows: InfoRow[], label: string, value: string) => { const row: InfoRow = { label, value }; rows.push(row) }
@@ -37,7 +49,7 @@
const loadInput = () => {
assessmentType.value = activeAssessmentType()
const saved = getAssessmentInput(assessmentType.value)
if (saved == null) { hasInput.value = false; sections.value = []; return }
if (saved == null) { clearView(); return }
hasInput.value = true
const enterprise = assessmentType.value == 'enterprise'
const basicRows: InfoRow[] = []
@@ -79,12 +91,19 @@
]
payload.value = { ...saved, source: 'mobile', confirmed: true }
}
onShow(() => loadInput())
onShow(() => {
visible = true; generation++; ownerToken = getSession()?.getString('token') ?? ''
loadInput(); stopAccountTimer()
if (sameOwner()) accountTimer = setInterval(() => { sameOwner() }, 1000)
})
onHide(() => { visible = false; generation++; stopAccountTimer(); clearView() })
onUnload(() => {
visible = false; generation++; stopAccountTimer(); clearView()
const pages = getCurrentPages()
if (!pages.some((page): boolean => page.route == 'packages/finance/assessment/assessment')) clearAssessmentFlow()
})
const edit = (step: number) => {
if (!sameOwner()) return
const input = getAssessmentInput(assessmentType.value)
if (input != null) input['step'] = step
const pages = getCurrentPages()
@@ -92,6 +111,7 @@
else uni.navigateTo({ url: '/packages/finance/assessment/assessment?type=' + assessmentType.value })
}
const submit = async () => {
if (!sameOwner()) return
if (!hasInput.value) { edit(0); return }
if (submitting.value) return
const saved = payload.value
@@ -105,14 +125,16 @@
const assetError = assetValidationMessage(formFromInput(saved))
if (assetError.length > 0) { uni.showToast({ title: assetError, icon: 'none' }); edit(2); return }
submitting.value = true
const request = ++generation
try {
const id = await submitAssessment(payload.value)
if (request != generation || !sameOwner()) return
clearAssessmentFlow()
// 清空本次填写流程和页面栈;修改须重新读取最新版本,防止返回旧表单重复提交。
uni.reLaunch({ url: '/packages/finance/analyzing/analyzing?assessmentId=' + encodeURIComponent(id) })
}
catch (error) { uni.showToast({ title: error instanceof Error ? error.message : '提交失败,请重试', icon: 'none' }) }
finally { submitting.value = false }
catch (error) { if (request == generation && sameOwner()) uni.showToast({ title: error instanceof Error ? error.message : '提交失败,请重试', icon: 'none' }) }
finally { if (request == generation && visible) submitting.value = false }
}
</script>