/** * 评分权重设置 hook:拉取维度与预设模板,提供权重调整、模板应用与保存能力。 * 业务规则(权重总和校验)放在 api 层,本层只负责本地编辑态与远端数据的合并。 */ import { useCallback, useMemo, useState } from 'react'; import { fetchWeightSettings, saveWeightSettings } from '../api'; import type { WeightDimension, WeightSettings } from '../types'; import { useAsyncData } from './useAsyncData'; export interface WeightSettingsState { /** 远端原始设置(含预设模板) */ settings: WeightSettings | null; /** 当前生效的维度列表(本地编辑态优先,未编辑时回退远端) */ dimensions: WeightDimension[]; /** 各维度权重总和,正常应为 100 */ totalWeight: number; loading: boolean; error: Error | null; saving: boolean; refresh: () => void; /** 调整单个维度权重 */ updateWeight: (id: string, weight: number) => void; /** 应用预设模板(按维度名称匹配权重) */ applyTemplate: (templateId: string) => void; /** 保存当前维度列表 */ save: () => Promise; } export function useWeightSettings(): WeightSettingsState { const fetcher = useCallback(() => fetchWeightSettings(), []); const { data, loading, error, refresh } = useAsyncData(fetcher); const [localDimensions, setLocalDimensions] = useState(null); const [saving, setSaving] = useState(false); const remoteDimensions = data?.dimensions ?? []; const dimensions = localDimensions ?? remoteDimensions; const totalWeight = useMemo( () => dimensions.reduce((sum, item) => sum + item.weight, 0), [dimensions], ); const updateWeight = useCallback( (id: string, weight: number) => { setLocalDimensions((prev) => { const base = prev ?? remoteDimensions; return base.map((item) => (item.id === id ? { ...item, weight } : item)); }); }, [remoteDimensions], ); const applyTemplate = useCallback( (templateId: string) => { const template = data?.templates.find((item) => item.id === templateId); if (!template) return; setLocalDimensions((prev) => { const base = prev ?? remoteDimensions; return base.map((item) => ({ ...item, weight: template.weights[item.name] ?? item.weight, })); }); }, [data, remoteDimensions], ); const save = useCallback(async () => { setSaving(true); try { const saved = await saveWeightSettings(dimensions); setLocalDimensions(saved); } finally { setSaving(false); } }, [dimensions]); return { settings: data ?? null, dimensions, totalWeight, loading, error, saving, refresh, updateWeight, applyTemplate, save, }; }