213 lines
6.5 KiB
JavaScript
213 lines
6.5 KiB
JavaScript
import { reactive, ref, onMounted } from 'vue'
|
||
import {
|
||
getAuthPluginOverviewApi,
|
||
getAuthPluginDetailApi,
|
||
getAuthPluginTokenStrategiesApi,
|
||
getAuthPluginConfigSchemaApi,
|
||
validateAuthPluginConfigApi
|
||
} from '@/apis'
|
||
import { unwrap } from './utils'
|
||
|
||
/**
|
||
* 认证插件 Composable
|
||
*
|
||
* 封装认证插件模块的数据获取与状态管理,覆盖 5 个业务场景:
|
||
* - 总览列表(overview):卡片网格数据源
|
||
* - 详情(detail):详情抽屉基本信息
|
||
* - Token 刷新策略(tokenStrategies):详情抽屉 Token 策略区块
|
||
* - 配置 Schema(detailSchema / schemaDrawer):详情抽屉与 Schema 抽屉独立维护
|
||
* - 校验(validate):校验弹窗提交与结果
|
||
*
|
||
* 错误处理遵循 VNC §12 三层分工:
|
||
* - API 层处理 401/403/500 全局错误
|
||
* - Composable 捕获异常存入 error 字段
|
||
* - 组件层 watch error 显示 message.error() 或内联错误
|
||
*
|
||
* 注意:detailSchema 与 schemaDrawer 分别为详情抽屉、Schema 抽屉独立维护,
|
||
* 避免两个抽屉同时打开时配置 Schema 状态互相覆盖。
|
||
*/
|
||
export function useAuthPlugin() {
|
||
// ===== 总览状态 =====
|
||
const overview = reactive({ data: null, loading: false, error: '' })
|
||
|
||
// ===== 详情抽屉状态 =====
|
||
const detail = reactive({ data: null, loading: false, error: '' })
|
||
const tokenStrategies = reactive({ data: null, loading: false, error: '' })
|
||
const detailSchema = reactive({ data: null, loading: false, error: '' })
|
||
|
||
// ===== Schema 抽屉状态(独立于详情抽屉) =====
|
||
const schemaDrawer = reactive({ data: null, loading: false, error: '' })
|
||
|
||
// ===== 校验状态 =====
|
||
const validating = ref(false)
|
||
const validateResult = ref(null)
|
||
const validateError = ref('')
|
||
|
||
// ===== 请求序列号(防止快速切换适配器上下文导致响应错位) =====
|
||
// 每次 fetch 递增 seq,响应返回时若 seq 不匹配最新值则丢弃,避免旧数据覆盖新数据。
|
||
const detailSeq = ref(0)
|
||
const detailSchemaSeq = ref(0)
|
||
const schemaDrawerSeq = ref(0)
|
||
|
||
// ===== 总览 =====
|
||
const fetchOverview = async () => {
|
||
overview.loading = true
|
||
overview.error = ''
|
||
try {
|
||
overview.data = unwrap(await getAuthPluginOverviewApi())
|
||
} catch (error) {
|
||
overview.error = error.message
|
||
} finally {
|
||
overview.loading = false
|
||
}
|
||
}
|
||
|
||
// ===== 详情 =====
|
||
const fetchDetail = async (authType, adapterType) => {
|
||
const seq = ++detailSeq.value
|
||
detail.loading = true
|
||
detail.error = ''
|
||
try {
|
||
const params = adapterType ? { adapter_type: adapterType } : undefined
|
||
// 丢弃过期响应:用户在请求期间已切换到其他适配器上下文
|
||
if (seq !== detailSeq.value) return
|
||
detail.data = unwrap(await getAuthPluginDetailApi(authType, params))
|
||
} catch (error) {
|
||
if (seq !== detailSeq.value) return
|
||
detail.error = error.message
|
||
} finally {
|
||
if (seq === detailSeq.value) {
|
||
detail.loading = false
|
||
}
|
||
}
|
||
}
|
||
|
||
// ===== Token 刷新策略 =====
|
||
const fetchTokenStrategies = async () => {
|
||
tokenStrategies.loading = true
|
||
tokenStrategies.error = ''
|
||
try {
|
||
tokenStrategies.data = unwrap(await getAuthPluginTokenStrategiesApi())
|
||
} catch (error) {
|
||
tokenStrategies.error = error.message
|
||
} finally {
|
||
tokenStrategies.loading = false
|
||
}
|
||
}
|
||
|
||
// ===== 配置 Schema(详情抽屉) =====
|
||
const fetchDetailSchema = async (authType, adapterType) => {
|
||
const seq = ++detailSchemaSeq.value
|
||
detailSchema.loading = true
|
||
detailSchema.error = ''
|
||
try {
|
||
const params = adapterType ? { adapter_type: adapterType } : undefined
|
||
if (seq !== detailSchemaSeq.value) return
|
||
detailSchema.data = unwrap(await getAuthPluginConfigSchemaApi(authType, params))
|
||
} catch (error) {
|
||
if (seq !== detailSchemaSeq.value) return
|
||
detailSchema.error = error.message
|
||
} finally {
|
||
if (seq === detailSchemaSeq.value) {
|
||
detailSchema.loading = false
|
||
}
|
||
}
|
||
}
|
||
|
||
// ===== 配置 Schema(Schema 抽屉,独立状态) =====
|
||
const fetchSchemaDrawer = async (authType, adapterType) => {
|
||
const seq = ++schemaDrawerSeq.value
|
||
schemaDrawer.loading = true
|
||
schemaDrawer.error = ''
|
||
try {
|
||
const params = adapterType ? { adapter_type: adapterType } : undefined
|
||
if (seq !== schemaDrawerSeq.value) return
|
||
schemaDrawer.data = unwrap(await getAuthPluginConfigSchemaApi(authType, params))
|
||
} catch (error) {
|
||
if (seq !== schemaDrawerSeq.value) return
|
||
schemaDrawer.error = error.message
|
||
} finally {
|
||
if (seq === schemaDrawerSeq.value) {
|
||
schemaDrawer.loading = false
|
||
}
|
||
}
|
||
}
|
||
|
||
// ===== 校验配置 =====
|
||
// 校验端点返回 200 + {valid, errors}(业务校验结果),非 422。
|
||
// 网络异常(401/403/500/连接失败)存入 validateError,业务结果存入 validateResult。
|
||
const validateConfig = async (authType, authConfig, adapterType) => {
|
||
validating.value = true
|
||
validateError.value = ''
|
||
validateResult.value = null
|
||
try {
|
||
const params = adapterType ? { adapter_type: adapterType } : undefined
|
||
validateResult.value = unwrap(
|
||
await validateAuthPluginConfigApi(authType, { auth_config: authConfig }, params)
|
||
)
|
||
} catch (error) {
|
||
validateError.value = error.message
|
||
} finally {
|
||
validating.value = false
|
||
}
|
||
}
|
||
|
||
// ===== 状态重置 =====
|
||
const resetDetail = () => {
|
||
detailSeq.value++ // 使任何在途请求失效
|
||
detail.data = null
|
||
detail.error = ''
|
||
detail.loading = false
|
||
}
|
||
|
||
const resetDetailSchema = () => {
|
||
detailSchemaSeq.value++
|
||
detailSchema.data = null
|
||
detailSchema.error = ''
|
||
detailSchema.loading = false
|
||
}
|
||
|
||
const resetSchemaDrawer = () => {
|
||
schemaDrawerSeq.value++
|
||
schemaDrawer.data = null
|
||
schemaDrawer.error = ''
|
||
schemaDrawer.loading = false
|
||
}
|
||
|
||
const resetValidate = () => {
|
||
validateResult.value = null
|
||
validateError.value = ''
|
||
validating.value = false
|
||
}
|
||
|
||
// ===== 生命周期 =====
|
||
onMounted(() => {
|
||
fetchOverview()
|
||
})
|
||
|
||
return {
|
||
// 总览
|
||
overview,
|
||
fetchOverview,
|
||
// 详情抽屉
|
||
detail,
|
||
tokenStrategies,
|
||
detailSchema,
|
||
fetchDetail,
|
||
fetchTokenStrategies,
|
||
fetchDetailSchema,
|
||
resetDetail,
|
||
resetDetailSchema,
|
||
// Schema 抽屉
|
||
schemaDrawer,
|
||
fetchSchemaDrawer,
|
||
resetSchemaDrawer,
|
||
// 校验
|
||
validating,
|
||
validateResult,
|
||
validateError,
|
||
validateConfig,
|
||
resetValidate
|
||
}
|
||
}
|