/**
* 评分权重设置页:调整九大评价维度权重,支持套用预设模板。
* 数据通过 useWeightSettings 获取,页面只负责交互与渲染。
*/
import { Ionicons } from '@expo/vector-icons';
import { useRouter } from 'expo-router';
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useWeightSettings } from '../../src/hooks';
import { colors } from '../../src/theme';
const MIN_WEIGHT = 0;
const MAX_WEIGHT = 100;
const STEP = 1;
function Header({ onBack }: { onBack: () => void }) {
return (
评分权重设置
);
}
export default function WeightSettingsScreen() {
const router = useRouter();
const {
settings,
dimensions,
totalWeight,
loading,
error,
saving,
refresh,
updateWeight,
applyTemplate,
save,
} = useWeightSettings();
const isValid = totalWeight === 100;
// 错误态
if (error) {
return (
router.back()} />
加载失败,请重试
重试
);
}
// 加载态
if (loading) {
return (
);
}
return (
router.back()} />
权重总和
{totalWeight}%
{isValid ? '配置合理,可直接保存' : '各维度权重之和需等于 100%'}
预设模板
{(settings?.templates ?? []).map((template) => (
applyTemplate(template.id)}
>
{template.name}
{template.description}
))}
评价维度
{dimensions.map((item, index) => {
const isLast = index === dimensions.length - 1;
return (
{item.name}
{item.isReversed ? (
反向指标
) : null}
{item.weight}%
updateWeight(item.id, Math.max(MIN_WEIGHT, item.weight - STEP))
}
>
updateWeight(item.id, Math.min(MAX_WEIGHT, item.weight + STEP))
}
>
);
})}
{saving ? '保存中…' : '保存设置'}
);
}
const styles = StyleSheet.create({
safeArea: { flex: 1, backgroundColor: colors.pageBg },
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 12,
backgroundColor: colors.surface,
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: colors.borderLight,
},
headerBtn: { width: 32, alignItems: 'center' },
headerTitle: { fontSize: 17, fontWeight: '500', color: colors.textPrimary },
content: { padding: 16, paddingBottom: 24 },
stateWrap: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12 },
stateText: { fontSize: 14, color: colors.textSecondary },
retryBtn: {
paddingHorizontal: 20,
paddingVertical: 8,
borderRadius: 8,
backgroundColor: colors.primaryLight,
},
retryText: { fontSize: 14, color: colors.primaryText },
summaryCard: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
padding: 16,
borderRadius: 8,
backgroundColor: colors.primaryLight,
},
summaryCardWarn: { backgroundColor: colors.dangerLight },
summaryLabel: { fontSize: 12, color: colors.textSecondary, marginBottom: 4 },
summaryValue: { fontSize: 24, fontWeight: '500', color: colors.primaryText },
summaryValueWarn: { color: colors.dangerText },
summaryHint: { flex: 1, textAlign: 'right', fontSize: 12, color: colors.textSecondary },
sectionHeader: { flexDirection: 'row', alignItems: 'center', marginTop: 20, marginBottom: 12 },
sectionBar: {
width: 3,
height: 14,
borderRadius: 2,
backgroundColor: colors.primaryBtn,
marginRight: 8,
},
sectionTitle: { fontSize: 15, fontWeight: '500', color: colors.textPrimary },
templateRow: { gap: 10, paddingRight: 16 },
templateCard: {
width: 140,
padding: 12,
borderRadius: 8,
backgroundColor: colors.surface,
borderWidth: StyleSheet.hairlineWidth,
borderColor: colors.borderLight,
},
templateName: { fontSize: 14, fontWeight: '500', color: colors.textPrimary, marginBottom: 4 },
templateDesc: { fontSize: 11, color: colors.textSecondary },
dimensionCard: {
borderRadius: 8,
backgroundColor: colors.surface,
borderWidth: StyleSheet.hairlineWidth,
borderColor: colors.borderLight,
paddingHorizontal: 14,
},
dimRow: {
paddingVertical: 14,
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: colors.borderLight,
},
dimRowLast: { borderBottomWidth: 0 },
dimHead: { flexDirection: 'row', alignItems: 'center', marginBottom: 8 },
dimName: { fontSize: 14, color: colors.textPrimary, marginRight: 6 },
reversedTag: {
paddingHorizontal: 6,
paddingVertical: 1,
borderRadius: 4,
backgroundColor: colors.infoLight,
marginRight: 6,
},
reversedText: { fontSize: 10, color: colors.infoText },
dimValue: { marginLeft: 'auto', fontSize: 14, fontWeight: '500', color: colors.primaryText },
dimTrack: {
height: 6,
borderRadius: 3,
backgroundColor: colors.borderLight,
overflow: 'hidden',
marginBottom: 10,
},
dimFill: { height: '100%', borderRadius: 3 },
dimActions: { flexDirection: 'row', gap: 8 },
stepBtn: {
width: 28,
height: 28,
borderRadius: 6,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: colors.primaryLight,
},
footer: {
padding: 16,
backgroundColor: colors.surface,
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: colors.borderLight,
},
saveBtn: {
height: 46,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: colors.primaryBtn,
},
saveBtnDisabled: { backgroundColor: colors.border },
saveText: { fontSize: 15, fontWeight: '500', color: colors.white },
});