ForcePilot/web/src/composables/external-systems/useAuthPlugin.js

213 lines
6.5 KiB
JavaScript
Raw Normal View History

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 策略区块
* - 配置 SchemadetailSchema / 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
}
}
}
// ===== 配置 SchemaSchema 抽屉,独立状态) =====
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
}
}