refactor: 租户切换器useTenantOptions收拢三页

新建 composables/useTenantOptions.ts:会话/配置/统计三页各自的
tenants/tenantsLoading/tenantsError/loadTenants 拷贝收拢为单一
composable。两种形态:
- 默认(会话/配置页):loadTenants 成功选中首个租户 +
  bootstrapTenantContext()(原两页 onMounted 公共体:超管拉列表/
  租户管理员固定自己/无 slug 防御不动),选中后的 watch 仍留各页
  (重置逻辑页面各异);
- selectFirst: false(统计页):纯下拉数据源,activeSlug 以
  tenantFilter 别名解构('' = 全部租户合并视图),模板零改动。

dashboard 控制台是租户卡片墙(非下拉切换),不在此列。
composable 显式 import vue API——vitest 不跑 unplugin-auto-import。
新增 8 个 composable 测试(mock api/auth store,不装 pinia)。

vitest 164 passed(156+8);build 通过;dts 行尾漂移已还原。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-14 10:36:30 +08:00
parent a50ed866ed
commit b02326036f
5 changed files with 245 additions and 77 deletions
+11 -18
View File
@@ -198,7 +198,7 @@
import type { EChartsOption } from '@/plugins/echarts'
import { useAuthStore } from '@/store/modules/auth'
import { fetchPlatformStats, fetchTenantStats, type StatsResponse } from '@/api/stats'
import { fetchTenantList, type TenantListItem } from '@/api/tenants'
import { useTenantOptions } from '@/composables/useTenantOptions'
import { conversationSourceLabel } from '@/api/conversations'
import { STATS_RANGE_OPTIONS, resolveStatsRange, type StatsRangeFilter } from '@/utils/statsRange'
import {
@@ -215,7 +215,6 @@
defineOptions({ name: 'StatsOverview' })
const authStore = useAuthStore()
const isSuper = computed(() => authStore.role === 'super')
// ---- 筛选:时间档 + 自定义区间 + 租户(超管) --------------------------------------
@@ -224,22 +223,16 @@
/** 当前筛选 → 查询参数;null = 自定义区间不完整(不发请求,保留上一份数据) */
const params = computed(() => resolveStatsRange(rangeFilter.value, customRange.value))
const tenantFilter = ref('') // '' = 全部租户合并视图
const tenants = ref<TenantListItem[]>([])
const tenantsLoading = ref(false)
const tenantsError = ref('')
async function loadTenants(): Promise<void> {
tenantsLoading.value = true
tenantsError.value = ''
try {
tenants.value = (await fetchTenantList()).items
} catch (error) {
tenantsError.value = error instanceof Error ? error.message : '租户列表加载失败'
} finally {
tenantsLoading.value = false
}
}
// 纯下拉数据源(selectFirst: false):tenantFilter = activeSlug 改名,
// '' = 全部租户合并视图,切换只进 reload 的查询参数——useTenantOptions 收拢
const {
tenants,
tenantsLoading,
tenantsError,
loadTenants,
isSuper,
activeSlug: tenantFilter
} = useTenantOptions({ selectFirst: false })
// ---- 统计取数(epoch 防筛选快速切换的过期响应竞写) --------------------------------