轻松聘
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

91 lines
2.8 KiB

/**
* 评分权重设置 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<void>;
}
export function useWeightSettings(): WeightSettingsState {
const fetcher = useCallback(() => fetchWeightSettings(), []);
const { data, loading, error, refresh } = useAsyncData<WeightSettings>(fetcher);
const [localDimensions, setLocalDimensions] = useState<WeightDimension[] | null>(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,
};
}