36 lines
1.1 KiB
TypeScript
36 lines
1.1 KiB
TypeScript
import type { Ref } from 'vue'
|
||
|
||
export function useUnsavedChanges<T>(source: Ref<T | undefined>) {
|
||
const dirty = ref(false)
|
||
let baseline = ''
|
||
|
||
function snapshot() {
|
||
baseline = JSON.stringify(source.value ?? null)
|
||
dirty.value = false
|
||
}
|
||
|
||
watch(source, (value) => {
|
||
if (!baseline) return
|
||
dirty.value = JSON.stringify(value ?? null) !== baseline
|
||
}, { deep: true })
|
||
|
||
function beforeUnload(event: BeforeUnloadEvent) {
|
||
if (!dirty.value) return
|
||
event.preventDefault()
|
||
event.returnValue = ''
|
||
}
|
||
|
||
onMounted(() => window.addEventListener('beforeunload', beforeUnload))
|
||
onBeforeUnmount(() => window.removeEventListener('beforeunload', beforeUnload))
|
||
onBeforeRouteLeave(() => !dirty.value || window.confirm('当前修改尚未保存,确定离开吗?'))
|
||
|
||
return { dirty, markClean: snapshot }
|
||
}
|
||
|
||
export function apiErrorMessage(error: any, fallback: string) {
|
||
const issue = error?.data?.data?.issues?.[0]
|
||
if (!issue) return error?.data?.statusMessage || fallback
|
||
const path = Array.isArray(issue.path) && issue.path.length ? `${issue.path.join('.')}:` : ''
|
||
return `${path}${issue.message || fallback}`
|
||
}
|