fix: 消除业务重复loading并取消已关闭抽屉的查询

This commit is contained in:
Yvan
2026-11-05 12:39:50 +08:00
parent d4233c7139
commit 5f6e893457
28 changed files with 270 additions and 112 deletions
+8 -4
View File
@@ -27,7 +27,8 @@
</el-drawer>
</template>
<script setup>
import { computed, reactive, ref, watch } from 'vue'
import { computed, onBeforeUnmount, onDeactivated, reactive, ref, watch } from 'vue'
import { createLatestRequest } from '@/utils/latestRequest'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getGoals, saveGoal } from '@/api/performance'
import { performanceMetrics as metrics, currentMonth, monthOffset, displayMetric, displayTarget } from '../performance-display'
@@ -35,15 +36,18 @@ const props = defineProps({ modelValue: Boolean, target: Object }), emit = defin
const visible = computed({ get: () => props.modelValue, set: v => emit('update:modelValue', v) })
const loading = ref(false), saving = ref(false), error = ref(''), data = ref(null), tab = ref('settings'), month = ref(currentMonth())
const form = reactive({ open: '', effective: '', amount: '' })
let version = 0
const requests = createLatestRequest()
const selected = computed(() => data.value?.months.find(m => m.month === month.value)), previous = computed(() => data.value?.months.find(m => m.month === monthOffset(month.value, -1)))
const history = computed(() => (data.value?.months || []).filter(m => m.month <= currentMonth()).slice(0, 6))
const monthChoices = computed(() => [...new Set([month.value, ...[-1, 0, 1].map(n => monthOffset(currentMonth(), n))])].sort())
const statuses = { unset: '未设目标', ongoing: '进行中', future: '未开始', achieved: '达成', unavailable: '未接入' }
const statusType = status => ({ achieved: 'success', missing: 'danger', ongoing: 'primary' }[status] || 'info')
const fill = () => { for (const key of Object.keys(form)) form[key] = selected.value?.goal?.[key] == null ? '' : String(selected.value.goal[key]) }
const load = async () => { const current = ++version; loading.value = true; error.value = ''; try { const res = await getGoals({ kind: props.target.kind, targetId: props.target.id }); if (current !== version) return; if (res.code !== 0) { error.value = res.msg || '目标读取失败'; return } data.value = res.data; fill() } catch { if (current === version) error.value = '目标读取失败,请重试' } finally { if (current === version) loading.value = false } }
watch(visible, v => { if (v) { data.value = null; tab.value = 'settings'; month.value = currentMonth(); load() } else version++ })
const load = async () => { if (!visible.value || !props.target) return; const request = requests.start(); loading.value = true; error.value = ''; try { const res = await getGoals({ kind: props.target.kind, targetId: props.target.id }, { signal: request.signal }); if (!request.isCurrent()) return; if (res.code !== 0) { error.value = res.msg || '目标读取失败'; return } data.value = res.data; fill() } catch { if (request.isCurrent()) error.value = '目标读取失败,请重试' } finally { if (request.isCurrent()) loading.value = false } }
const cancel = () => { requests.cancel(); loading.value = false }
watch(() => [props.modelValue, props.target], ([open]) => { if (open) { data.value = null; tab.value = 'settings'; month.value = currentMonth(); load() } else cancel() }, { flush: 'sync' })
onBeforeUnmount(cancel)
onDeactivated(() => { visible.value = false; cancel() })
const editMonth = value => { month.value = value; fill(); tab.value = 'settings' }
const persist = async values => { saving.value = true; error.value = ''; try { const res = await saveGoal({ kind: props.target.kind, targetId: props.target.id, month: month.value, ...values }); if (res.code !== 0) { error.value = res.msg || '目标保存失败'; return } ElMessage.success('目标已保存'); emit('saved'); await load() } catch { error.value = '目标保存失败,请重试' } finally { saving.value = false } }
const save = async () => { if (saving.value) return; const values = {}; for (const [key, raw] of Object.entries(form)) { if (raw.trim() === '') { values[key] = null; continue } if (!/^\d+$/.test(raw.trim()) || !Number.isSafeInteger(Number(raw))) { ElMessage.warning('目标须为非负整数,或留空'); return } values[key] = Number(raw) } await persist(values) }