feat: 优化账户切换时的页面状态一致性,增加登录回跳校验和课程阅读新逻辑
- 增加账户状态监听定时器,页面切换时自动校验账户归属,避免跨账户操作 - 新增登录回跳路径校验函数,限制仅允许指定页面回跳,防止非法跳转 - 课程页改为整篇连续阅读,底部仅一次标记已读,兼容历史记录 - 完善助手、对比页、资料填写页等多处的账户状态校验逻辑,防止错版数据提交 - 优化账户资料请求逻辑,增加版本校验,避免旧请求覆盖新数据
This commit is contained in:
@@ -80,7 +80,7 @@
|
||||
const loading = ref(false); const error = ref(''); const listError = ref(''); const listLoading = ref(false); const hasMore = ref(false)
|
||||
const completeness = ref<number | null>(null); const completenessFailed = ref(false)
|
||||
const completenessMessage = ref('提交评估后,查看对应报告的资料完整度。')
|
||||
let cursor = ''; let generation = 0; let reportRequest = 0; let visible = false; let routeError = ''; let routeId = ''; let owner = ''
|
||||
let cursor = ''; let generation = 0; let reportRequest = 0; let visible = false; let routeError = ''; let routeId = ''; let owner = ''; let accountTimer = 0
|
||||
const sections = computed((): ArchiveSection[] => detail.value != null ? detail.value!.sections : [
|
||||
{ id: 'basic', icon: 'file-text', title: '基本信息', note: type.value == 'enterprise' ? '企业与联系人信息' : '身份与联系方式', fields: [], provided: 0 },
|
||||
{ id: 'income', icon: 'income', title: type.value == 'enterprise' ? '经营信息' : '职业与收入', note: type.value == 'enterprise' ? '经营行业、月数与营收' : '职业、收入与缴纳情况', fields: [], provided: 0 },
|
||||
@@ -98,14 +98,25 @@
|
||||
completenessMessage.value = '提交评估后,查看对应报告的资料完整度。'
|
||||
error.value = ''; listError.value = ''; listLoading.value = false
|
||||
}
|
||||
const stopAccountTimer = () => { if (accountTimer != 0) clearInterval(accountTimer); accountTimer = 0 }
|
||||
const invalidateAccount = () => {
|
||||
const session = getSession()
|
||||
generation++; clearView(); loading.value = false; selectedId.value = routeId; historyOpen.value = false; owner = session?.getString('token') ?? ''; stopAccountTimer()
|
||||
if (session == null) uni.redirectTo({ url: '/packages/account/login/login' })
|
||||
else error.value = '登录状态已变化,请重新加载档案。'
|
||||
}
|
||||
const startAccountTimer = () => {
|
||||
stopAccountTimer()
|
||||
if (owner.length > 0) accountTimer = setInterval(() => {
|
||||
if (visible && (getSession()?.getString('token') ?? '') != owner) invalidateAccount()
|
||||
}, 1000)
|
||||
}
|
||||
const active = (request: number, token: string): boolean => {
|
||||
if (!visible || request != generation) return false
|
||||
const session = getSession()
|
||||
if (session?.getString('token') == token) return true
|
||||
// 包括报告/历史分页返回401的情况:立即移除已显示资料,不只忽略迟到响应。
|
||||
generation++; clearView(); loading.value = false; selectedId.value = routeId
|
||||
if (session == null) uni.redirectTo({ url: '/packages/account/login/login' })
|
||||
else error.value = '登录状态已变化,请重新加载档案。'
|
||||
invalidateAccount()
|
||||
return false
|
||||
}
|
||||
const readCompleteness = async (id: string, request: number, token: string) => {
|
||||
@@ -140,14 +151,14 @@
|
||||
} catch (err) { if (active(request, token)) versionsError.value = err instanceof Error ? err.message : '版本历史读取失败' }
|
||||
finally { if (active(request, token)) versionsLoading.value = false }
|
||||
}
|
||||
const moreVersions = () => { if (!versionsLoading.value) readVersions(versions.value.length > 0, generation, owner) }
|
||||
const chooseVersion = (id: string) => { uni.redirectTo({ url: '/packages/finance/archive/archive?assessmentId=' + selectedId.value + '&revisionId=' + id }) }
|
||||
const editAssessment = () => { if (detail.value != null) uni.navigateTo({ url: '/packages/finance/assessment/assessment?editId=' + selectedId.value }) }
|
||||
const moreVersions = () => { if (active(generation, owner) && !versionsLoading.value) readVersions(versions.value.length > 0, generation, owner) }
|
||||
const chooseVersion = (id: string) => { if (active(generation, owner) && detail.value != null) uni.redirectTo({ url: '/packages/finance/archive/archive?assessmentId=' + selectedId.value + '&revisionId=' + id }) }
|
||||
const editAssessment = () => { if (active(generation, owner) && detail.value != null) uni.navigateTo({ url: '/packages/finance/assessment/assessment?editId=' + selectedId.value }) }
|
||||
const refresh = async () => {
|
||||
const request = ++generation; clearView(); loading.value = true
|
||||
const session = getSession()
|
||||
if (session == null) { loading.value = false; uni.redirectTo({ url: '/packages/account/login/login' }); return }
|
||||
const token = session.getString('token') ?? ''; owner = token
|
||||
const token = session.getString('token') ?? ''; owner = token; startAccountTimer()
|
||||
if (routeError.length > 0) { error.value = routeError; loading.value = false; completenessMessage.value = '请先选择有效的评估记录。'; return }
|
||||
try {
|
||||
// 显式ID先校验本人详情;失败不能自动切到最新记录,掩盖越权或已删除状态。
|
||||
@@ -172,6 +183,7 @@
|
||||
loading.value = false
|
||||
if (detail.value != null) {
|
||||
await readVersions(false, request, token)
|
||||
if (!active(request, token) || detail.value == null) return
|
||||
if (detail.value!.record.status == 'succeeded') await readCompleteness(detail.value!.record.id, request, token)
|
||||
else completenessMessage.value = detail.value!.record.status == 'failed' ? '本次分析未完成,暂没有报告完整度;已提交资料已保留。' : '本次分析尚未完成,报告生成后可查看完整度。'
|
||||
}
|
||||
@@ -179,18 +191,18 @@
|
||||
if (active(request, token)) { error.value = err instanceof Error ? err.message : '档案读取失败,请重试'; completenessMessage.value = '档案暂不可读取,请重新加载或选择其他记录。' }
|
||||
} finally { if (active(request, token)) loading.value = false }
|
||||
}
|
||||
const retryList = () => { if (!listLoading.value) readList(false, generation, owner) }
|
||||
const loadMore = () => { if (!listLoading.value && hasMore.value) readList(true, generation, owner) }
|
||||
const retryCompleteness = () => { if (detail.value != null && detail.value!.record.status == 'succeeded') readCompleteness(detail.value!.record.id, generation, owner) }
|
||||
const toggleSection = (id: string) => { if (detail.value != null) expanded.value = expanded.value == id ? '' : id }
|
||||
const retryList = () => { if (active(generation, owner) && !listLoading.value) readList(false, generation, owner) }
|
||||
const loadMore = () => { if (active(generation, owner) && !listLoading.value && hasMore.value) readList(true, generation, owner) }
|
||||
const retryCompleteness = () => { if (active(generation, owner) && detail.value != null && detail.value!.record.status == 'succeeded') readCompleteness(detail.value!.record.id, generation, owner) }
|
||||
const toggleSection = (id: string) => { if (active(generation, owner) && detail.value != null) expanded.value = expanded.value == id ? '' : id }
|
||||
// 类型与显式历史选择留在路由里,刷新重新鉴权后仍查看同一记录;不保存草稿或资料缓存。
|
||||
const switchType = (next: string) => { if (next != type.value) uni.redirectTo({ url: '/packages/finance/archive/archive?type=' + next }) }
|
||||
const chooseRecord = (id: string) => { if (id == selectedId.value) { historyOpen.value = false; return }; uni.redirectTo({ url: '/packages/finance/archive/archive?type=' + type.value + '&assessmentId=' + encodeURIComponent(id) }) }
|
||||
const chooseRecord = (id: string) => { if (!active(generation, owner)) return; if (id == selectedId.value) { historyOpen.value = false; return }; uni.redirectTo({ url: '/packages/finance/archive/archive?type=' + type.value + '&assessmentId=' + encodeURIComponent(id) }) }
|
||||
const showLatest = () => { uni.redirectTo({ url: '/packages/finance/archive/archive?type=' + type.value }) }
|
||||
const start = () => { clearAssessmentFlow(); uni.navigateTo({ url: '/packages/finance/assessment/assessment?type=' + type.value }) }
|
||||
const openPreviousReport = () => { if (detail.value != null) uni.navigateTo({ url: '/packages/finance/report/report?assessmentId=' + selectedId.value + '&revisionId=' + detail.value!.record.publishedRevisionId }) }
|
||||
const openPreviousReport = () => { if (active(generation, owner) && detail.value != null) uni.navigateTo({ url: '/packages/finance/report/report?assessmentId=' + selectedId.value + '&revisionId=' + detail.value!.record.publishedRevisionId }) }
|
||||
const openAnalysis = () => {
|
||||
if (detail.value == null) return
|
||||
if (!active(generation, owner) || detail.value == null) return
|
||||
const page = detail.value!.record.status == 'succeeded' ? 'report/report' : 'analyzing/analyzing'
|
||||
uni.navigateTo({ url: '/packages/finance/' + page + '?assessmentId=' + encodeURIComponent(detail.value!.record.id) + (page == 'report/report' ? '&revisionId=' + detail.value!.record.revisionId : '') })
|
||||
}
|
||||
@@ -202,13 +214,13 @@
|
||||
if (options?.['assessmentId'] != null && !/^[1-9][0-9]{0,9}$/.test(routeId)) routeError = '评估编号无效,请重新选择历史记录。'
|
||||
})
|
||||
onShow(() => {
|
||||
visible = true
|
||||
visible = true; stopAccountTimer()
|
||||
if (getSession()?.getString('token') != owner) { selectedId.value = routeId; historyOpen.value = false }
|
||||
refresh()
|
||||
})
|
||||
// 离开即清空敏感内容;账户切换、快速换档和迟到响应均不能恢复旧账户资料。
|
||||
onHide(() => { visible = false; generation++; clearView(); loading.value = false })
|
||||
onUnload(() => { visible = false; generation++; clearView() })
|
||||
onHide(() => { visible = false; stopAccountTimer(); generation++; clearView(); loading.value = false })
|
||||
onUnload(() => { visible = false; stopAccountTimer(); generation++; clearView() })
|
||||
</script>
|
||||
<style>
|
||||
.archive-content { padding: 26rpx 30rpx 70rpx; }
|
||||
|
||||
Reference in New Issue
Block a user