ForcePilot/web/src/composables/external-systems/useAuthPlugin.js
Kris f2b21c27b6 feat(external-systems): 新增外部系统集成模块完整功能
新增23个API模块、路由、状态管理与通用组件,重构重复代码,完成外部系统集成全功能搭建
2026-06-20 22:21:34 +08:00

213 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}