mosaicmap/hooks/use-site-config.ts
2025-08-14 21:34:16 +08:00

254 lines
6.5 KiB
TypeScript
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.

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