fix(assessment): 移除本地缓存,恢复进行中测评检测

- 移除 localStorage 表单缓存(STORAGE_KEY、saveFormToStorage、restoreFormFromStorage、clearFormStorage、watch、onUnload)
- 恢复 getPendingRecord API 调用和弹窗逻辑
- 恢复继续测评模式(表单自动填充、禁用编辑、按钮文案切换)
- 恢复进行中测评弹窗(重新开始/继续测评)
This commit is contained in:
zpc 2026-02-23 01:21:19 +08:00
parent 0cbd9d4745
commit e33f4ed8f0

View File

@ -10,12 +10,12 @@
* - 进行中测评记录恢复断点续答 * - 进行中测评记录恢复断点续答
*/ */
import { ref, computed, watch } from 'vue' import { ref, computed } from 'vue'
import { onLoad, onUnload } from '@dcloudio/uni-app' import { onLoad } from '@dcloudio/uni-app'
import { useUserStore } from '@/store/user.js' import { useUserStore } from '@/store/user.js'
import { useAuth } from '@/composables/useAuth.js' import { useAuth } from '@/composables/useAuth.js'
import { usePayment } from '@/composables/usePayment.js' import { usePayment } from '@/composables/usePayment.js'
import { getIntro, verifyInviteCode } from '@/api/assessment.js' import { getIntro, verifyInviteCode, getPendingRecord } from '@/api/assessment.js'
import { createOrder } from '@/api/order.js' import { createOrder } from '@/api/order.js'
import { isPhone } from '@/utils/validate.js' import { isPhone } from '@/utils/validate.js'
import Navbar from '@/components/Navbar/index.vue' import Navbar from '@/components/Navbar/index.vue'
@ -80,68 +80,79 @@ const inviteLoading = ref(false)
// //
const pageLoading = ref(true) const pageLoading = ref(true)
// key //
const STORAGE_KEY = 'assessment_info_form' const pendingRecord = ref(null)
const showPendingPopup = ref(false)
/** /**
* 保存表单数据到本地 * 是否为继续测评模式
*/ */
function saveFormToStorage() { const isContinueMode = computed(() => !!pendingRecord.value)
const data = {
...formData.value, /**
genderIndex: genderIndex.value, * 性别数值转文本
ageIndex: ageIndex.value, */
educationIndex: educationIndex.value, function getGenderLabel(val) {
regionValue: regionValue.value return val === 1 ? '男' : val === 2 ? '女' : ''
} }
/**
* 学业阶段数值转文本
*/
function getEducationStageLabel(val) {
const map = { 1: '小学及以下', 2: '初中', 3: '高中', 4: '大专' }
return map[val] || ''
}
/**
* 检查是否有进行中的测评记录
*/
async function checkPendingRecord() {
try { try {
uni.setStorageSync(STORAGE_KEY, JSON.stringify(data)) const res = await getPendingRecord(typeId.value)
if (res && res.code === 0 && res.data) {
pendingRecord.value = res.data
showPendingPopup.value = true
}
} catch (e) { } catch (e) {
console.error('保存表单数据失败:', e) console.error('检查进行中测评失败:', e)
} }
} }
/** /**
* 从本地还原表单数据 * 继续进行中的测评
*/ */
function restoreFormFromStorage() { function handleContinuePending() {
try { if (!pendingRecord.value) return
const raw = uni.getStorageSync(STORAGE_KEY) const r = pendingRecord.value
if (!raw) return
const data = JSON.parse(raw) //
formData.value.name = data.name || '' formData.value.name = r.name || ''
formData.value.phone = data.phone || '' formData.value.phone = r.phone || ''
formData.value.gender = data.gender || '' formData.value.gender = getGenderLabel(r.gender)
formData.value.age = data.age || '' formData.value.age = r.age ? `${r.age}` : ''
formData.value.educationStage = data.educationStage || '' formData.value.educationStage = getEducationStageLabel(r.educationStage)
formData.value.province = data.province || '' formData.value.province = r.province || ''
formData.value.city = data.city || '' formData.value.city = r.city || ''
formData.value.district = data.district || '' formData.value.district = r.district || ''
genderIndex.value = data.genderIndex ?? -1
ageIndex.value = data.ageIndex ?? -1 //
educationIndex.value = data.educationIndex ?? -1 genderIndex.value = r.gender === 1 ? 0 : r.gender === 2 ? 1 : -1
regionValue.value = data.regionValue || [] ageIndex.value = r.age ? r.age - 10 : -1
} catch (e) { educationIndex.value = educationOptions.indexOf(getEducationStageLabel(r.educationStage))
console.error('还原表单数据失败:', e) regionValue.value = [r.province || '', r.city || '', r.district || '']
}
showPendingPopup.value = false
} }
/** /**
* 提交成功后清除缓存 * 放弃进行中的测评重新开始
*/ */
function clearFormStorage() { function handleDismissPending() {
try { pendingRecord.value = null
uni.removeStorageSync(STORAGE_KEY) showPendingPopup.value = false
} catch (e) {
// ignore
}
} }
//
watch(formData, () => {
saveFormToStorage()
}, { deep: true })
/** /**
* 表单是否填写完整 * 表单是否填写完整
*/ */
@ -162,6 +173,7 @@ const isFormComplete = computed(() => {
* 底部按钮文案 * 底部按钮文案
*/ */
const payBtnText = computed(() => { const payBtnText = computed(() => {
if (isContinueMode.value) return '继续测评'
return `支付¥${introData.value.price || 20}元开始测评` return `支付¥${introData.value.price || 20}元开始测评`
}) })
@ -262,6 +274,15 @@ function buildAssessmentInfo() {
/** 支付测评 */ /** 支付测评 */
async function handlePayAssessment() { async function handlePayAssessment() {
if (!checkLogin()) return if (!checkLogin()) return
//
if (isContinueMode.value && pendingRecord.value) {
uni.redirectTo({
url: `/pages/assessment/questions/index?typeId=${typeId.value}&recordId=${pendingRecord.value.recordId}`
})
return
}
if (!validateForm()) return if (!validateForm()) return
try { try {
@ -274,7 +295,6 @@ async function handlePayAssessment() {
uni.hideLoading() uni.hideLoading()
if (result.success) { if (result.success) {
clearFormStorage()
// createOrder assessmentRecordId // createOrder assessmentRecordId
const recordId = result.assessmentRecordId || '' const recordId = result.assessmentRecordId || ''
uni.redirectTo({ uni.redirectTo({
@ -342,7 +362,6 @@ async function submitInviteCode() {
if (orderRes && orderRes.code === 0 && orderRes.data) { if (orderRes && orderRes.code === 0 && orderRes.data) {
closeInvitePopup() closeInvitePopup()
clearFormStorage()
const recordId = orderRes.data.assessmentRecordId || '' const recordId = orderRes.data.assessmentRecordId || ''
uni.redirectTo({ uni.redirectTo({
url: `/pages/assessment/questions/index?typeId=${typeId.value}&recordId=${recordId}` url: `/pages/assessment/questions/index?typeId=${typeId.value}&recordId=${recordId}`
@ -365,20 +384,17 @@ onLoad((options) => {
typeName.value = decodeURIComponent(options.typeName || '') typeName.value = decodeURIComponent(options.typeName || '')
userStore.restoreFromStorage() userStore.restoreFromStorage()
//
restoreFormFromStorage()
// //
if (userStore.isLoggedIn && userStore.phone && !formData.value.phone) { if (userStore.isLoggedIn && userStore.phone && !formData.value.phone) {
formData.value.phone = userStore.phone formData.value.phone = userStore.phone
} }
loadIntro() loadIntro()
})
/** 页面卸载时保存 */ //
onUnload(() => { if (userStore.isLoggedIn) {
saveFormToStorage() checkPendingRecord()
}
}) })
</script> </script>
@ -403,7 +419,7 @@ onUnload(() => {
<!-- 表单卡片 --> <!-- 表单卡片 -->
<view class="form-card"> <view class="form-card">
<view class="form-tip"> <view class="form-tip">
正式测评前请先填写您的基本信息 {{ isContinueMode ? '您有一份进行中的测评,信息已自动填充' : '正式测评前,请先填写您的基本信息' }}
</view> </view>
<!-- 姓名 --> <!-- 姓名 -->
@ -416,6 +432,7 @@ onUnload(() => {
placeholder-class="input-placeholder" placeholder-class="input-placeholder"
v-model="formData.name" v-model="formData.name"
maxlength="20" maxlength="20"
:disabled="isContinueMode"
/> />
</view> </view>
</view> </view>
@ -430,6 +447,7 @@ onUnload(() => {
placeholder-class="input-placeholder" placeholder-class="input-placeholder"
v-model="formData.phone" v-model="formData.phone"
maxlength="11" maxlength="11"
:disabled="isContinueMode"
/> />
</view> </view>
</view> </view>
@ -437,7 +455,7 @@ onUnload(() => {
<!-- 性别 --> <!-- 性别 -->
<view class="form-item"> <view class="form-item">
<view class="form-label"><text class="required">*</text>性别</view> <view class="form-label"><text class="required">*</text>性别</view>
<picker mode="selector" :range="genderOptions" @change="onGenderChange"> <picker mode="selector" :range="genderOptions" @change="onGenderChange" :disabled="isContinueMode">
<view class="form-select-box"> <view class="form-select-box">
<text :class="formData.gender ? 'select-value' : 'select-placeholder'"> <text :class="formData.gender ? 'select-value' : 'select-placeholder'">
{{ formData.gender || '请选择' }} {{ formData.gender || '请选择' }}
@ -450,7 +468,7 @@ onUnload(() => {
<!-- 年龄 --> <!-- 年龄 -->
<view class="form-item"> <view class="form-item">
<view class="form-label"><text class="required">*</text>年龄</view> <view class="form-label"><text class="required">*</text>年龄</view>
<picker mode="selector" :range="ageOptions" @change="onAgeChange"> <picker mode="selector" :range="ageOptions" @change="onAgeChange" :disabled="isContinueMode">
<view class="form-select-box"> <view class="form-select-box">
<text :class="formData.age ? 'select-value' : 'select-placeholder'"> <text :class="formData.age ? 'select-value' : 'select-placeholder'">
{{ formData.age || '请选择' }} {{ formData.age || '请选择' }}
@ -463,7 +481,7 @@ onUnload(() => {
<!-- 学业阶段 --> <!-- 学业阶段 -->
<view class="form-item"> <view class="form-item">
<view class="form-label"><text class="required">*</text>学业阶段</view> <view class="form-label"><text class="required">*</text>学业阶段</view>
<picker mode="selector" :range="educationOptions" @change="onEducationChange"> <picker mode="selector" :range="educationOptions" @change="onEducationChange" :disabled="isContinueMode">
<view class="form-select-box"> <view class="form-select-box">
<text :class="formData.educationStage ? 'select-value' : 'select-placeholder'"> <text :class="formData.educationStage ? 'select-value' : 'select-placeholder'">
{{ formData.educationStage || '请选择' }} {{ formData.educationStage || '请选择' }}
@ -476,7 +494,7 @@ onUnload(() => {
<!-- 所在城市 --> <!-- 所在城市 -->
<view class="form-item form-item-last"> <view class="form-item form-item-last">
<view class="form-label"><text class="required">*</text>所在城市</view> <view class="form-label"><text class="required">*</text>所在城市</view>
<picker mode="region" @change="onRegionChange"> <picker mode="region" @change="onRegionChange" :disabled="isContinueMode">
<view class="form-region-row"> <view class="form-region-row">
<view class="region-box"> <view class="region-box">
<text :class="formData.province ? 'select-value' : 'select-placeholder'"> <text :class="formData.province ? 'select-value' : 'select-placeholder'">
@ -503,10 +521,10 @@ onUnload(() => {
<!-- 底部按钮 --> <!-- 底部按钮 -->
<view class="btn-group"> <view class="btn-group">
<view class="btn-invite" @click="openInvitePopup"> <view v-if="!isContinueMode" class="btn-invite" @click="openInvitePopup">
<text>邀请码免费测评</text> <text>邀请码免费测评</text>
</view> </view>
<view class="btn-pay" @click="handlePayAssessment"> <view class="btn-pay" :class="{ 'btn-full': isContinueMode }" @click="handlePayAssessment">
<text>{{ payBtnText }}</text> <text>{{ payBtnText }}</text>
</view> </view>
</view> </view>
@ -537,6 +555,31 @@ onUnload(() => {
</view> </view>
</view> </view>
</view> </view>
<!-- 进行中测评弹窗 -->
<view v-if="showPendingPopup" class="popup-mask" @click="handleDismissPending">
<view class="popup-container pending-popup" @click.stop>
<view class="popup-header">
<text class="popup-title">发现进行中的测评</text>
</view>
<view class="popup-body">
<view class="pending-msg">
您有一份未完成的测评记录是否继续
</view>
<view class="pending-info">
<text>姓名{{ pendingRecord?.name }}</text>
<text>手机号{{ pendingRecord?.phone }}</text>
</view>
</view>
<view class="pending-footer">
<view class="popup-btn-outline" @click="handleDismissPending">
<text>重新开始</text>
</view>
<view class="popup-btn" @click="handleContinuePending">
<text>继续测评</text>
</view>
</view>
</view>
</view>
</view> </view>
</template> </template>
@ -750,6 +793,10 @@ onUnload(() => {
&:active { &:active {
opacity: 0.8; opacity: 0.8;
} }
&.btn-full {
flex: 1;
}
} }
// ========== ========== // ========== ==========
@ -855,6 +902,41 @@ onUnload(() => {
} }
} }
// ========== ==========
.pending-popup {
.pending-msg {
font-size: $font-size-md;
color: $text-color;
text-align: center;
margin-bottom: $spacing-lg;
}
.pending-info {
display: flex;
flex-direction: column;
gap: $spacing-sm;
background-color: $bg-gray;
border-radius: $border-radius-md;
padding: $spacing-lg;
text {
font-size: $font-size-sm;
color: $text-secondary;
}
}
}
.pending-footer {
display: flex;
gap: $spacing-md;
padding: 0 $spacing-lg $spacing-xl;
.popup-btn-outline,
.popup-btn {
flex: 1;
}
}
// ========== ========== // ========== ==========
.invite-input { .invite-input {
width: 100%; width: 100%;