You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular13+Laravel多表单折扣规则执行与最大折扣方案问询

后台规则匹配与最大折扣计算方案(Angular13 + Laravel架构)

一、规则存储设计

先把折扣规则结构化存储到数据库,建议新增两张核心表:

  • forms:存储课程报名表单基础信息(表单ID、名称等)
  • form_discount_rules:存储每套表单对应的折扣规则,核心字段包括:
    • form_id:关联表单ID
    • condition_expression:JSON格式的条件表达式,示例:
      {"conditions": [{"field": "A", "operator": "eq", "value": "VIP"}, {"field": "age", "operator": "gte", "value": 25}], "logic": "and"}
      
    • discount_percent:折扣比例(如10表示10%折扣)
    • priority:可选字段,用于折扣率相同时的规则优先级(数值越高优先级越高)

这种JSON结构能灵活支持多字段的and/or组合条件,后续扩展新字段或逻辑也更方便。

二、规则匹配与最大折扣计算流程

用户填写表单时,后端执行以下步骤:

  1. 接收前端传递的表单ID和用户输入的字段数据
  2. 拉取当前表单对应的所有折扣规则(可缓存规则提升性能)
  3. 逐个解析规则的条件表达式,判断用户输入是否满足规则要求
  4. 收集所有满足条件的规则折扣率,取最大值作为最终折扣

三、核心实现代码(Laravel)

下面是可直接复用的折扣计算器类:

namespace App\Services;

use App\Models\FormDiscountRule;

class DiscountCalculator
{
    public function getMaxDiscount(array $userInput, int $formId): float
    {
        // 优先从缓存获取规则,缓存失效时从数据库拉取
        $rules = cache()->remember("form_discount_rules_{$formId}", 3600, function () use ($formId) {
            return FormDiscountRule::where('form_id', $formId)->get();
        });

        $validDiscounts = [];
        foreach ($rules as $rule) {
            $condition = json_decode($rule->condition_expression, true);
            if ($this->checkConditionMatch($userInput, $condition)) {
                $validDiscounts[] = [
                    'percent' => $rule->discount_percent,
                    'priority' => $rule->priority ?? 0
                ];
            }
        }

        if (empty($validDiscounts)) {
            return 0.0;
        }

        // 先按折扣率降序,再按优先级降序排序,取第一个
        usort($validDiscounts, function ($a, $b) {
            if ($a['percent'] !== $b['percent']) {
                return $b['percent'] - $a['percent'];
            }
            return $b['priority'] - $a['priority'];
        });

        return $validDiscounts[0]['percent'] / 100; // 返回小数形式的折扣(如0.1表示10%)
    }

    private function checkConditionMatch(array $userInput, array $condition): bool
    {
        $conditions = $condition['conditions'] ?? [];
        $logic = $condition['logic'] ?? 'and';
        $matchResults = [];

        foreach ($conditions as $cond) {
            $fieldValue = $userInput[$cond['field']] ?? null;
            $matchResults[] = $this->compareValues($fieldValue, $cond['operator'], $cond['value']);
        }

        return $logic === 'and' 
            ? !in_array(false, $matchResults, true) 
            : in_array(true, $matchResults, true);
    }

    private function compareValues($fieldValue, string $operator, $ruleValue): bool
    {
        // 统一类型转换,避免字符串和数字比较的误差
        if (is_numeric($fieldValue) && is_numeric($ruleValue)) {
            $fieldValue = (float)$fieldValue;
            $ruleValue = (float)$ruleValue;
        }

        return match ($operator) {
            'eq' => $fieldValue == $ruleValue,
            'ne' => $fieldValue != $ruleValue,
            'gt' => $fieldValue > $ruleValue,
            'gte' => $fieldValue >= $ruleValue,
            'lt' => $fieldValue < $ruleValue,
            'lte' => $fieldValue <= $ruleValue,
            'in' => in_array($fieldValue, (array)$ruleValue),
            'not_in' => !in_array($fieldValue, (array)$ruleValue),
            default => false,
        };
    }
}

四、优化建议

  • 缓存优化:如果表单规则不会频繁修改,将规则缓存到Redis或Laravel文件缓存中,减少数据库查询次数
  • 前端辅助校验:为提升用户体验,前端可以根据规则做实时预计算,但最终折扣必须以后端计算结果为准,防止前端篡改
  • 规则引擎扩展:如果后续规则复杂度大幅提升(如嵌套条件、自定义函数),可以引入PHP规则引擎库替代自定义解析逻辑,降低维护成本
  • 安全校验:禁止在条件表达式中使用可执行代码,所有条件判断通过预定义的运算符实现,避免注入风险

内容的提问来源于stack exchange,提问作者Rajeev Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 01:10:36