feat: 重构评估流程为内存状态管理并接入真实提交与报告接口

本次重构将评估草稿改为内存状态管理,移除本地存储草稿,新增评估流程内存状态模块;接入真实的账户资料获取、头像上传接口,新增账户缓存清理逻辑;重构评估提交逻辑,接入真实提交接口并返回评估ID;新增分析页和报告页的真实状态查询、报告获取功能;更新README文档,记录开发进度和接口状态。
This commit is contained in:
hujun
2026-09-24 11:50:07 +08:00
parent dcf12a4471
commit dbfd637388
22 changed files with 1468 additions and 434 deletions
@@ -16,16 +16,23 @@
import AppIcon from '@/components/AppIcon.uvue'
import { usePageLayout } from '@/services/layout.uts'
import { getSession } from '@/services/api.uts'
import { DEFAULT_AVATAR, maskPhone, getAccountProfile, saveAccountProfile, readAvatar } from '@/packages/account/services/account.uts'
import { DEFAULT_AVATAR, maskPhone, getAccountProfile, fetchAccountProfile, saveAccountProfile, uploadAccountAvatar } from '@/packages/account/services/account.uts'
const { pageStyle, contentStyle, bottomStyle } = usePageLayout()
const nickname = ref(''); const avatar = ref(''); const phone = ref(''); const saving = ref(false); const choosing = ref(false); const errorMessage = ref('')
const avatarId = ref('')
let originalName = ''; let originalAvatar = ''; let alive = true
const dirty = (): boolean => nickname.value.trim() != originalName || avatar.value != originalAvatar
onLoad(() => {
if (getSession() == null) { uni.redirectTo({ url: '/packages/account/login/login' }); return }
const profile = getAccountProfile(); nickname.value = profile.nickname; avatar.value = profile.avatar; phone.value = profile.phone
originalName = profile.nickname; originalAvatar = profile.avatar
// 服务端资料优先;请求返回时已开始编辑则不覆盖用户输入。
fetchAccountProfile().then((fresh) => {
if (!alive || dirty()) return
nickname.value = fresh.nickname; avatar.value = fresh.avatar; phone.value = fresh.phone
originalName = fresh.nickname; originalAvatar = fresh.avatar
}).catch((error) => { if (alive) errorMessage.value = error instanceof Error ? error.message : '资料加载失败,请重试' })
})
const dirty = (): boolean => nickname.value.trim() != originalName || avatar.value != originalAvatar
const leave = () => { if (getCurrentPages().length > 1) uni.navigateBack(); else uni.redirectTo({ url: '/packages/account/profile/profile' }) }
const back = () => {
if (saving.value) return
@@ -35,14 +42,17 @@
onBackPress((event): boolean => { if (event.from == 'navigateBack') return false; if (saving.value || dirty()) { back(); return true }; return false })
const loadAvatar = async (path: string) => {
choosing.value = true; errorMessage.value = ''
try { const image = await readAvatar(path); if (alive) avatar.value = image }
try {
const result = await uploadAccountAvatar(path)
if (alive) { avatar.value = result['avatarUrl'] as string; avatarId.value = result['attachmentId'] as string }
}
catch (error) { if (alive) errorMessage.value = error instanceof Error ? error.message : '图片读取失败' }
finally { if (alive) choosing.value = false }
}
const chooseAvatar = () => {
if (saving.value || choosing.value) return
uni.showActionSheet({ itemList: ['从相册选择', '恢复默认头像'], success: (action) => {
if (action.tapIndex == 1) { avatar.value = ''; return }
if (action.tapIndex == 1) { avatar.value = ''; avatarId.value = 'default'; return }
uni.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album'], success: (result) => {
if (result.tempFilePaths.length == 0) return
if (result.tempFiles[0].size > 512000) { errorMessage.value = '请选择 500KB 以内的图片'; return }
@@ -56,7 +66,7 @@
errorMessage.value = ''; saving.value = true
try {
if (getAccountProfile().phone != phone.value) throw new Error('登录状态已变化,请重新进入页面')
await saveAccountProfile(nickname.value, avatar.value)
await saveAccountProfile(nickname.value, avatarId.value)
originalName = nickname.value.trim(); originalAvatar = avatar.value
uni.showToast({ title: '资料已保存', icon: 'success' }); leave()
} catch (error) { errorMessage.value = error instanceof Error ? error.message : '保存失败,请稍后重试' }