fix: 401 强退重置 authStore + dictStore 支持 force 刷新

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
liuyun 2026-10-11 16:43:31 +08:00
parent 42b0a6a479
commit ed1a1e115c
4 changed files with 26 additions and 7 deletions

View File

@ -8,6 +8,7 @@ import { installAssets } from '@/plugins/assets'
import { Env } from '@/utils/env.ts' import { Env } from '@/utils/env.ts'
import { installI18n } from '@/i18n' import { installI18n } from '@/i18n'
import { setAuthExpiredHandler } from '@/api/http' import { setAuthExpiredHandler } from '@/api/http'
import { useAuthStore } from '@/stores/modules/auth'
import { useMenuStore } from '@/stores/modules/menu' import { useMenuStore } from '@/stores/modules/menu'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import { usePermissionStore } from '@/stores/modules/permission' import { usePermissionStore } from '@/stores/modules/permission'
@ -23,6 +24,7 @@ installStore(app)
// 会话过期(401 刷新失败)时:清状态 + 跳登录 // 会话过期(401 刷新失败)时:清状态 + 跳登录
setAuthExpiredHandler(() => { setAuthExpiredHandler(() => {
useAuthStore(pinia).reset()
useMenuStore(pinia).reset() useMenuStore(pinia).reset()
useDictStore(pinia).reset() useDictStore(pinia).reset()
usePermissionStore(pinia).reset() usePermissionStore(pinia).reset()

View File

@ -70,6 +70,7 @@ import TyForm from '@/components/ty-form.vue'
import { showDialog } from '@/utils/dialog' import { showDialog } from '@/utils/dialog'
import { useRequest } from '@/composables/useRequest' import { useRequest } from '@/composables/useRequest'
import { useDict } from '@/composables/useDict' import { useDict } from '@/composables/useDict'
import { useDictStore } from '@/stores/modules/dict'
import { import {
createDictItem, createDictItem,
createDictType, createDictType,
@ -83,6 +84,7 @@ import {
} from '@/api/dict' } from '@/api/dict'
const { tagMap: commonStatusMap } = useDict('common_status') const { tagMap: commonStatusMap } = useDict('common_status')
const dictStore = useDictStore()
/** 标签色中文名(UI 调色板,非业务字典)。 */ /** 标签色中文名(UI 调色板,非业务字典)。 */
const COLOR_LABELS: Record<string, string> = { const COLOR_LABELS: Record<string, string> = {
@ -149,6 +151,7 @@ async function openTypeCreate(): Promise<void> {
await createDictType({ code: data.code, name: data.name, remark: data.remark }) await createDictType({ code: data.code, name: data.name, remark: data.remark })
ElMessage.success('新增成功') ElMessage.success('新增成功')
await refreshTypes() await refreshTypes()
await dictStore.fetch(true)
selectedType.value = types.value.find((t) => t.code === data.code) ?? selectedType.value selectedType.value = types.value.find((t) => t.code === data.code) ?? selectedType.value
} }
@ -163,6 +166,7 @@ async function openTypeEdit(t: DictType): Promise<void> {
await updateDictType(t.id, { name: data.name, status: data.status, remark: data.remark }) await updateDictType(t.id, { name: data.name, status: data.status, remark: data.remark })
ElMessage.success('更新成功') ElMessage.success('更新成功')
await refreshTypes() await refreshTypes()
await dictStore.fetch(true)
} }
async function removeType(t: DictType): Promise<void> { async function removeType(t: DictType): Promise<void> {
@ -170,6 +174,7 @@ async function removeType(t: DictType): Promise<void> {
await deleteDictType(t.id) await deleteDictType(t.id)
ElMessage.success('删除成功') ElMessage.success('删除成功')
await refreshTypes() await refreshTypes()
await dictStore.fetch(true)
} }
// ---- 字典项(右) ---- // ---- 字典项(右) ----
@ -233,23 +238,27 @@ const listItems = async (query: PageQuery, signal?: AbortSignal) => {
} }
} }
const createItem = (data: Record<string, any>) => const createItem = async (data: Record<string, any>) => {
createDictItem({ await createDictItem({
dictTypeCode: selectedType.value?.code ?? '', dictTypeCode: selectedType.value?.code ?? '',
label: data.label, label: data.label,
value: data.value, value: data.value,
sort: data.sort ?? 0, sort: data.sort ?? 0,
colorType: data.colorType || undefined, colorType: data.colorType || undefined,
}) })
await dictStore.fetch(true)
}
const updateItem = (id: string, data: Record<string, any>) => const updateItem = async (id: string, data: Record<string, any>) => {
updateDictItem(id, { await updateDictItem(id, {
label: data.label, label: data.label,
value: data.value, value: data.value,
sort: data.sort ?? 0, sort: data.sort ?? 0,
status: data.status, status: data.status,
colorType: data.colorType || undefined, colorType: data.colorType || undefined,
}) })
await dictStore.fetch(true)
}
const removeItem = (id: string) => deleteDictItem(id) const removeItem = (id: string) => deleteDictItem(id)
@ -265,6 +274,7 @@ async function removeWithConfirm(row: Record<string, any>): Promise<void> {
await deleteDictItem(String(row.id)) await deleteDictItem(String(row.id))
ElMessage.success('删除成功') ElMessage.success('删除成功')
itemCrudRef.value?.reload() itemCrudRef.value?.reload()
await dictStore.fetch(true)
} }
</script> </script>

View File

@ -34,5 +34,12 @@ export const useAuthStore = defineStore('authStore', () => {
refreshToken.value = null; refreshToken.value = null;
} }
return { accessToken, refreshToken, isAuthenticated, login, logout }; /** 本地清空会话状态(不调用登出接口,供 401 强退使用)。 */
function reset(): void {
clearTokens();
accessToken.value = null;
refreshToken.value = null;
}
return { accessToken, refreshToken, isAuthenticated, login, logout, reset };
}); });

View File

@ -8,8 +8,8 @@ export const useDictStore = defineStore('dictStore', () => {
const loaded = ref(false) const loaded = ref(false)
const loading = ref(false) const loading = ref(false)
async function fetch(): Promise<void> { async function fetch(force = false): Promise<void> {
if (loaded.value || loading.value) return if (!force && (loaded.value || loading.value)) return
loading.value = true loading.value = true
try { try {
const res = await listDicts() const res = await listDicts()