71 lines
2.6 KiB
TypeScript
71 lines
2.6 KiB
TypeScript
import { computed, onScopeDispose, ref, watch } from 'vue'
|
|
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
|
import type { PlatformTenantPage, PlatformTenantQuery, PlatformTenantResource } from './api/platformIam'
|
|
|
|
export function useActiveCustomerOptions(selectedId: () => string | null | undefined, loadPage: (query: PlatformTenantQuery) => Promise<PlatformTenantPage>) {
|
|
const records = ref<PlatformTenantResource[]>([])
|
|
const selected = ref<PlatformTenantResource | null>(null)
|
|
const loading = ref(false)
|
|
const error = ref<ApiErrorDetails | null>(null)
|
|
const keyword = ref('')
|
|
const page = ref(0)
|
|
const hasMore = ref(false)
|
|
let sequence = 0
|
|
let disposed = false
|
|
|
|
watch(selectedId, id => {
|
|
selected.value = id ? records.value.find(row => String(row.id) === id) || (String(selected.value?.id) === id ? selected.value : null) : null
|
|
}, { flush: 'sync' })
|
|
|
|
const customers = computed(() => {
|
|
const current = selected.value
|
|
if (!current || records.value.some(row => String(row.id) === String(current.id))) return records.value
|
|
return [current, ...records.value]
|
|
})
|
|
|
|
async function fetchPage(nextPage: number, append: boolean) {
|
|
if (disposed) return
|
|
const request = ++sequence
|
|
loading.value = true
|
|
error.value = null
|
|
try {
|
|
const result = await loadPage({ page: nextPage, size: 50, status: 'ACTIVE', ...(keyword.value ? { keyword: keyword.value } : {}) })
|
|
if (request !== sequence || disposed) return
|
|
const rows = [...(append ? records.value : []), ...result.records.filter(row => row.status === 'ACTIVE')]
|
|
records.value = [...new Map(rows.map(row => [String(row.id), row])).values()]
|
|
page.value = nextPage
|
|
hasMore.value = nextPage < result.pages
|
|
} catch (cause) {
|
|
if (request === sequence && !disposed) error.value = getApiErrorDetails(cause, '客户选项加载失败,请重试')
|
|
} finally {
|
|
if (request === sequence && !disposed) loading.value = false
|
|
}
|
|
}
|
|
|
|
function search(value = '') {
|
|
if (disposed) return
|
|
keyword.value = value.trim()
|
|
records.value = []
|
|
page.value = 0
|
|
hasMore.value = false
|
|
return fetchPage(1, false)
|
|
}
|
|
|
|
function loadMore() {
|
|
if (loading.value || error.value || !hasMore.value) return
|
|
return fetchPage(page.value + 1, true)
|
|
}
|
|
|
|
function endReached(direction: string) {
|
|
if (direction === 'bottom') return loadMore()
|
|
}
|
|
|
|
function retry() {
|
|
if (loading.value) return
|
|
return fetchPage(page.value + 1, page.value > 0)
|
|
}
|
|
|
|
onScopeDispose(() => { disposed = true; sequence++ })
|
|
return { customers, loading, error, search, endReached, retry }
|
|
}
|