110 lines
2.7 KiB
TypeScript
110 lines
2.7 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* useLicenseStatus Hook
|
|
*
|
|
* 获取当前许可证状态,提供功能可用性检查
|
|
* 用于在 UI 组件中判断功能是否受限
|
|
*/
|
|
|
|
import { useState, useEffect, useCallback } from 'react'
|
|
import type { FeatureKey, LicenseType } from '@/lib/license/types'
|
|
|
|
interface LicenseData {
|
|
type: LicenseType
|
|
status: 'active' | 'expired' | 'grace'
|
|
expiresAt: string | null
|
|
usage: {
|
|
users: { current: number; max: number }
|
|
materials: { current: number; max: number }
|
|
}
|
|
features: Record<FeatureKey, boolean>
|
|
lastVerified: string
|
|
}
|
|
|
|
interface LicenseStatus {
|
|
/** 许可证类型 */
|
|
type: LicenseType
|
|
/** 是否正在加载 */
|
|
loading: boolean
|
|
/** 错误信息 */
|
|
error: string | null
|
|
/** 完整的许可证数据 */
|
|
data: LicenseData | null
|
|
/** 检查功能是否可用 */
|
|
isFeatureEnabled: (feature: FeatureKey) => boolean
|
|
/** 是否为免费版 */
|
|
isFree: boolean
|
|
/** 刷新许可证状态 */
|
|
refresh: () => Promise<void>
|
|
}
|
|
|
|
/**
|
|
* 获取许可证状态的 Hook
|
|
*/
|
|
export function useLicenseStatus(): LicenseStatus {
|
|
const [data, setData] = useState<LicenseData | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
|
const fetchLicenseStatus = useCallback(async () => {
|
|
try {
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
const response = await fetch('/api/license/info')
|
|
|
|
if (!response.ok) {
|
|
throw new Error('获取许可证信息失败')
|
|
}
|
|
|
|
const licenseData: LicenseData = await response.json()
|
|
setData(licenseData)
|
|
} catch (err) {
|
|
console.error('获取许可证状态失败:', err)
|
|
setError(err instanceof Error ? err.message : '未知错误')
|
|
// 出错时默认为免费版
|
|
setData({
|
|
type: 'FREE',
|
|
status: 'active',
|
|
expiresAt: null,
|
|
usage: {
|
|
users: { current: 0, max: 10 },
|
|
materials: { current: 0, max: 100 },
|
|
},
|
|
features: {
|
|
customTemplates: false,
|
|
systemSettings: false,
|
|
departmentIsolation: false,
|
|
apiAccess: false,
|
|
intranetPenetration: false,
|
|
},
|
|
lastVerified: new Date().toISOString(),
|
|
})
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
fetchLicenseStatus()
|
|
}, [fetchLicenseStatus])
|
|
|
|
const isFeatureEnabled = useCallback((feature: FeatureKey): boolean => {
|
|
if (!data) return false
|
|
return data.features[feature] ?? false
|
|
}, [data])
|
|
|
|
return {
|
|
type: data?.type ?? 'FREE',
|
|
loading,
|
|
error,
|
|
data,
|
|
isFeatureEnabled,
|
|
isFree: data?.type === 'FREE',
|
|
refresh: fetchLicenseStatus,
|
|
}
|
|
}
|
|
|
|
export default useLicenseStatus
|