如何在Ionic+Angular中实现禁用支出分类的百分比转移逻辑?
优化方案
1. 配置化管理分类与关联规则
先把所有分类的默认占比、关联关系、转移目标用配置对象统一管理,彻底告别硬编码:
// 分类配置接口 interface CategoryConfig { key: string; // 对应用户设置中的字段名(如'home') defaultPercent: number; // 默认占比(小数形式,如0.15) transferTarget?: string; // 禁用时的转移目标分类键 } // 关联组配置:管理一组关联分类的全禁用拆分规则 interface RelationGroup { categories: string[]; // 关联的分类键集合 splitToSavingsRatio: number; // 全禁用时,组总占比中转给储蓄的比例(如20/49≈0.408) } // 初始化所有分类配置 const categoryConfigs: Record<string, CategoryConfig> = { home: { key: 'home', defaultPercent: 0.15, transferTarget: 'shopping' }, shopping: { key: 'shopping', defaultPercent: 0.06, transferTarget: 'home' }, food: { key: 'food', defaultPercent: 0.28, transferTarget: 'shopping' }, others: { key: 'others', defaultPercent: 0.05 }, pets: { key: 'pets', defaultPercent: 0.05, transferTarget: 'others' }, debts: { key: 'debts', defaultPercent: 0.05, transferTarget: 'others' }, subscription: { key: 'subscription', defaultPercent: 0.04, transferTarget: 'others' }, transportation: { key: 'transportation', defaultPercent: 0.08, transferTarget: 'others' }, education: { key: 'education', defaultPercent: 0.05, transferTarget: 'others' }, entertainment: { key: 'entertainment', defaultPercent: 0.05, transferTarget: 'others' }, savings: { key: 'savings', defaultPercent: 0.10 } }; // 初始化关联组(比如家庭、购物、餐饮为一组) const relationGroups: RelationGroup[] = [ { categories: ['home', 'shopping', 'food'], splitToSavingsRatio: 20 / 49 } ];
2. 编写通用计算逻辑
通过遍历配置和用户设置,自动计算各分类的建议金额,无需逐个场景写判断:
calculateSuggestedAmounts(userSettings: any, totalIncome: number): Record<string, string> { // 1. 初始化结果:默认使用各分类的默认占比计算金额 const result: Record<string, string> = {}; Object.keys(categoryConfigs).forEach(key => { // 生成对应属性名(如home → sumaCatHome) const propName = `sumaCat${key.charAt(0).toUpperCase() + key.slice(1)}`; result[propName] = (totalIncome * categoryConfigs[key].defaultPercent).toFixed(2); }); // 2. 处理关联组的转移逻辑 relationGroups.forEach(group => { const enabledCats = group.categories.filter(cat => userSettings[cat]); const disabledCats = group.categories.filter(cat => !userSettings[cat]); const totalDisabledPercent = disabledCats.reduce((sum, cat) => sum + categoryConfigs[cat].defaultPercent, 0); switch (enabledCats.length) { case 2: // 1个分类禁用:转移到配置的目标分类 const disabledCat = disabledCats[0]; const targetCat = categoryConfigs[disabledCat].transferTarget!; const targetProp = `sumaCat${targetCat.charAt(0).toUpperCase() + targetCat.slice(1)}`; result[targetProp] = (parseFloat(result[targetProp]) + totalIncome * categoryConfigs[disabledCat].defaultPercent).toFixed(2); break; case 1: // 2个分类禁用:全部转移到唯一启用的分类 const soleEnabledCat = enabledCats[0]; const soleProp = `sumaCat${soleEnabledCat.charAt(0).toUpperCase() + soleEnabledCat.slice(1)}`; result[soleProp] = (parseFloat(result[soleProp]) + totalIncome * totalDisabledPercent).toFixed(2); break; case 0: // 全禁用:拆分到储蓄和其他 const savingsAdd = totalIncome * totalDisabledPercent * group.splitToSavingsRatio; const othersAdd = totalIncome * totalDisabledPercent * (1 - group.splitToSavingsRatio); result.sumaCatSavings = (parseFloat(result.sumaCatSavings) + savingsAdd).toFixed(2); result.sumaCatOthers = (parseFloat(result.sumaCatOthers) + othersAdd).toFixed(2); break; } }); // 3. 处理非关联组的独立分类(禁用后默认转其他) const independentCats = Object.keys(categoryConfigs).filter(cat => !relationGroups.some(group => group.categories.includes(cat)) && cat !== 'savings' && cat !== 'others' ); independentCats.forEach(cat => { if (!userSettings[cat]) { result.sumaCatOthers = (parseFloat(result.sumaCatOthers) + totalIncome * categoryConfigs[cat].defaultPercent).toFixed(2); } }); return result; }
3. 调用示例
// 从数据库读取的用户设置示例 const userSettings = { home: false, shopping: true, food: true, others: true, pets: true, debts: true, subscription: true, transportation: true, education: true, entertainment: true }; const totalIncome = 1000; // 示例总收入 const suggestedAmounts = this.calculateSuggestedAmounts(userSettings, totalIncome); console.log(suggestedAmounts.sumaCatShopping); // 输出 "210.00"(1000*(0.06+0.15))
方案优势
- 配置化驱动:所有规则、占比、关联关系都在配置中定义,新增或修改分类只需调整配置,无需修改逻辑代码。
- 逻辑复用:通过遍历和计算自动覆盖所有场景,彻底消除海量重复的条件判断。
- 扩展性强:新增关联组、调整转移规则或分类占比时,只需更新配置即可,核心逻辑无需改动。
内容的提问来源于stack exchange,提问作者Setter
相关产品推荐
相关产品推荐

