254 lines
6.5 KiB
TypeScript
254 lines
6.5 KiB
TypeScript
"use client";
|
||
|
||
import { useState, useCallback } from 'react';
|
||
import { useQuery, useMutation } from '@apollo/client';
|
||
import {
|
||
GET_SITE_OPS_CONFIG,
|
||
GET_CONFIGS,
|
||
GET_SITE_CONFIG,
|
||
GET_NOTICE_MAINTENANCE_CONFIG,
|
||
GET_DOCS_SUPPORT_CONFIG,
|
||
GET_OPS_CONFIG,
|
||
VALIDATE_CONFIG,
|
||
UPDATE_SETTING,
|
||
UPDATE_SETTINGS
|
||
} from '@/lib/config-queries';
|
||
import {
|
||
SiteOpsConfigType,
|
||
SiteConfigType,
|
||
NoticeMaintenanceType,
|
||
DocsSupportType,
|
||
OpsConfigType,
|
||
ConfigValidationResultType,
|
||
ConfigUpdateInput,
|
||
ConfigUpdateResult
|
||
} from '@/types/site-config';
|
||
|
||
// 使用完整的站点运营配置
|
||
export function useSiteOpsConfig() {
|
||
const { data, loading, error, refetch } = useQuery<{ siteOpsConfig: SiteOpsConfigType }>(
|
||
GET_SITE_OPS_CONFIG,
|
||
{
|
||
errorPolicy: 'all',
|
||
notifyOnNetworkStatusChange: true
|
||
}
|
||
);
|
||
|
||
return {
|
||
config: data?.siteOpsConfig,
|
||
loading,
|
||
error,
|
||
refetch
|
||
};
|
||
}
|
||
|
||
// 使用通用配置列表(KV)
|
||
export interface ConfigItemType {
|
||
id: string;
|
||
key: string;
|
||
value?: string | null;
|
||
valueType: string;
|
||
description?: string | null;
|
||
}
|
||
|
||
export function useConfigs() {
|
||
const { data, loading, error, refetch } = useQuery<{ configs: ConfigItemType[] }>(
|
||
GET_CONFIGS,
|
||
{
|
||
errorPolicy: 'all',
|
||
notifyOnNetworkStatusChange: true
|
||
}
|
||
);
|
||
|
||
return {
|
||
configs: data?.configs || [],
|
||
loading,
|
||
error,
|
||
refetch
|
||
};
|
||
}
|
||
|
||
// 使用站点配置
|
||
export function useSiteConfig() {
|
||
const { data, loading, error, refetch } = useQuery<{ siteConfig: SiteConfigType }>(
|
||
GET_SITE_CONFIG,
|
||
{
|
||
errorPolicy: 'all'
|
||
}
|
||
);
|
||
|
||
return {
|
||
config: data?.siteConfig,
|
||
loading,
|
||
error,
|
||
refetch
|
||
};
|
||
}
|
||
|
||
// 使用公告维护配置
|
||
export function useNoticeMaintenanceConfig() {
|
||
const { data, loading, error, refetch } = useQuery<{ noticeMaintenanceConfig: NoticeMaintenanceType }>(
|
||
GET_NOTICE_MAINTENANCE_CONFIG,
|
||
{
|
||
errorPolicy: 'all'
|
||
}
|
||
);
|
||
|
||
return {
|
||
config: data?.noticeMaintenanceConfig,
|
||
loading,
|
||
error,
|
||
refetch
|
||
};
|
||
}
|
||
|
||
// 使用文档支持配置
|
||
export function useDocsSupportConfig() {
|
||
const { data, loading, error, refetch } = useQuery<{ docsSupportConfig: DocsSupportType }>(
|
||
GET_DOCS_SUPPORT_CONFIG,
|
||
{
|
||
errorPolicy: 'all'
|
||
}
|
||
);
|
||
|
||
return {
|
||
config: data?.docsSupportConfig,
|
||
loading,
|
||
error,
|
||
refetch
|
||
};
|
||
}
|
||
|
||
// 使用运营配置
|
||
export function useOpsConfig() {
|
||
const { data, loading, error, refetch } = useQuery<{ opsConfig: OpsConfigType }>(
|
||
GET_OPS_CONFIG,
|
||
{
|
||
errorPolicy: 'all'
|
||
}
|
||
);
|
||
|
||
return {
|
||
config: data?.opsConfig,
|
||
loading,
|
||
error,
|
||
refetch
|
||
};
|
||
}
|
||
|
||
// 使用配置验证
|
||
export function useConfigValidation() {
|
||
const { data, loading, error, refetch } = useQuery<{ validateConfig: ConfigValidationResultType }>(
|
||
VALIDATE_CONFIG,
|
||
{
|
||
errorPolicy: 'all'
|
||
}
|
||
);
|
||
|
||
return {
|
||
validation: data?.validateConfig,
|
||
loading,
|
||
error,
|
||
refetch
|
||
};
|
||
}
|
||
|
||
// 配置更新hook
|
||
export function useConfigUpdater() {
|
||
const [updateSetting] = useMutation<
|
||
{ updateSetting: ConfigUpdateResult },
|
||
{ key: string; value: string }
|
||
>(UPDATE_SETTING);
|
||
|
||
const [updateSettings] = useMutation<
|
||
{ updateSettings: ConfigUpdateResult & { failedKeys?: string[] } },
|
||
{ settings: ConfigUpdateInput[] }
|
||
>(UPDATE_SETTINGS);
|
||
|
||
const [updating, setUpdating] = useState(false);
|
||
|
||
// 更新单个配置
|
||
const updateConfig = useCallback(async (key: string, value: any): Promise<ConfigUpdateResult> => {
|
||
setUpdating(true);
|
||
try {
|
||
const valueStr = typeof value === 'object' ? JSON.stringify(value) : String(value);
|
||
const result = await updateSetting({
|
||
variables: { key, value: valueStr }
|
||
});
|
||
|
||
return result.data?.updateSetting || { success: false, message: '更新失败' };
|
||
} catch (error) {
|
||
console.error('Update config error:', error);
|
||
return { success: false, message: error instanceof Error ? error.message : '更新失败' };
|
||
} finally {
|
||
setUpdating(false);
|
||
}
|
||
}, [updateSetting]);
|
||
|
||
// 批量更新配置
|
||
const updateConfigs = useCallback(async (configs: ConfigUpdateInput[]): Promise<ConfigUpdateResult & { failedKeys?: string[] }> => {
|
||
setUpdating(true);
|
||
try {
|
||
const result = await updateSettings({
|
||
variables: { settings: configs }
|
||
});
|
||
|
||
return result.data?.updateSettings || { success: false, message: '批量更新失败' };
|
||
} catch (error) {
|
||
console.error('Update configs error:', error);
|
||
return { success: false, message: error instanceof Error ? error.message : '批量更新失败' };
|
||
} finally {
|
||
setUpdating(false);
|
||
}
|
||
}, [updateSettings]);
|
||
|
||
return {
|
||
updateConfig,
|
||
updateConfigs,
|
||
updating
|
||
};
|
||
}
|
||
|
||
// 将嵌套配置对象转换为平铺的键值对
|
||
export function flattenConfigObject(obj: any, prefix = ''): ConfigUpdateInput[] {
|
||
const result: ConfigUpdateInput[] = [];
|
||
|
||
for (const [key, value] of Object.entries(obj)) {
|
||
const fullKey = prefix ? `${prefix}.${key}` : key;
|
||
|
||
if (value && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {
|
||
// 递归处理嵌套对象
|
||
result.push(...flattenConfigObject(value, fullKey));
|
||
} else {
|
||
// 处理基本类型、数组和日期
|
||
result.push({
|
||
key: fullKey,
|
||
value: value as string | number | boolean | object
|
||
});
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 从平铺的配置重建嵌套对象
|
||
export function unflattenConfigObject(configs: { key: string; value: any }[]): any {
|
||
const result: any = {};
|
||
|
||
for (const config of configs) {
|
||
const keys = config.key.split('.');
|
||
let current = result;
|
||
|
||
for (let i = 0; i < keys.length - 1; i++) {
|
||
const key = keys[i];
|
||
if (!(key in current)) {
|
||
current[key] = {};
|
||
}
|
||
current = current[key];
|
||
}
|
||
|
||
current[keys[keys.length - 1]] = config.value;
|
||
}
|
||
|
||
return result;
|
||
} |