卷轴模式功能模块开发与源码解析

卷轴模式系统包含的主要功能:
商城,分销,实名认证,活跃度机制,任务模型,农场,锁仓机制,积分机制,交易机制,转赠机制,激励广告,减产机制,级别机制,手续费等等。

客户端设计思路:
APP端
设计上开发2个APP。一个是商城购物APP,一个是任务包APP,这样方便业务流程更清晰,产品体验使用上简单易操作。
H5客户端
功能用于分享邀请码推广、注册账户、链接APP下载地址

 

卷轴模式

 

 

 

卷轴模式任务模型命名定义

入门赠送任务,不同等级的任务设置。一般默认设置为5到7个等级任务类型。在不同的电商平台和O2O项目里有不同名称类型。例如做通信类产品的,以流量包任务来呈现。做健康领域产业的以健康包来表示,做农业种植业行业的的以农作物,经济类作物命名,做旅游产业的以为旅行线路套餐来命名。下面我举一些例子让任务包名称更具形象化。

电商购物:初级购物包,中级购物包,进阶购物包,高级购物包,精英购物包

消费积分:初级积分包,中级积分包,进阶积分包,高级积分包,精英积分包,超级积分包,王者积分包

景区任务:新人任务,旅游任务,门票任务,景区任务,酒店任务,渠道任务

消费包:初级,低级,中级,高级,达人,富人

农场系列:苹果树,香蕉树,柿子树,石榴树,荔枝树,芒果树,山竹,车厘子,榴莲树。

 

卷轴任务包模式

 

卷轴模式任务包的实例设计

我们以农场系列的香蕉树来举例:

香蕉树,兑换所需数量(果粒值)10个,初始任务每日可得果粒值为0.4个,起始周期30天,总收益12颗,有效期90天,最多持有任务数量12天,活跃度1个,兑换任务完成后复做任务产出周期增加数量为1天,获得奖励单位是果粒值。其中每日可得果粒值是12个除以30天计算出来的。

 

任务模型参数

任务包,兑换数量,每日可得,起始周期,总收益,兑换任务周期增加时,有效期,最多持有任务数量,活跃度

任务包

任务包名称自定义,任务包一般是多个,在系统配置中心增加修改编辑操作。在任务包产出上模式设置是从低到高的。例如最优先的初级认为默认是免费领取。一般为只要用户实名认证后即可开启最初级的任务。

兑换数量

每个人任务包都会设置一个兑换数量值,任务包从初级到高级设置,那么兑换任务包的积分数量也是从底到高的设置,要不然在系统里也没有逻辑有序性。

每日可得

领去了的这个任务包后,完成平台规定的打卡看广告任务后,程序会自动给这个账户产出积分。

每日收益

是任务包的总收益除以周期天数的值的。

起始周期

兑换的任务包产出总天数设置,当用户每日完成打卡看广告任务后,这个天数也会减1日。例如当前任务包的总产出天数为30天,用户在一周内每天卡完任务,那么就是7天完成,那么还剩余23天的产出时间(30减7=23天)。

总收益

当前任务包在整个起始周期里的总产出数量。

有效期

产出果粒值的有效期,例如香蕉树任务包的有效期为90天,若这个用户在90天内有30天完成了打卡任务,那么他会获得12个果粒值;若这个用户在50天内,打卡了30天,那么同样也能获得12个果粒值,若这个用户在90天里,只打卡了25次,那么整个香蕉树任务周期的果粒值只能获得25天的果粒值数量。

最多持有任务数量

是指当前用户拥有的同类等级的任务包,正在同时执行打卡任务的最大数量额度。这个数量不计算已经完成产出的任务包。

卷轴模式界面

 

活跃度

活跃度是系统中重要的参数变量,它用于计算

每个任务包都有系统设定的活跃度,同时这个活跃度是一个动态拥有值,动态拥有是怎么理解呢?例如香蕉树任务包活跃度是1,并不是你兑换了这个任务包就能获得这个1数量的值,而是今天参加了打卡看视频广告任务,并且设定的视频广告任务数量后,这个活跃值就产生了。若没有完成今天的打卡任务,这个活跃值也不会存在。

卷轴任务包核心源码

任务积分释放代码

@RestController
public class VideoController {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @PostMapping("/watchVideo")
    public Map<String, Object> watchVideo(@RequestParam Long uid) {
        Map<String, Object> result = new HashMap<>();
        
        // 1. 检查缓存锁
        String cacheKey = "cache_purchase_" + uid;
        Boolean lock = redisTemplate.opsForValue()
                .setIfAbsent(cacheKey, "1", 2, TimeUnit.SECONDS);
        
        if (Boolean.FALSE.equals(lock)) {
            result.put("code", 500054);
            result.put("msg", "操作过于频繁");
            return result;
        }
        
        try {
            // 2. 获取用户信息(这里简化,实际需要从数据库查询)
            User user = getUserFromDatabase(uid);
            
            // 3. 检查任务次数
            if (user.getTask() >= 5) {
                result.put("code", 200);
                result.put("msg", "任务已完成");
                return result;
            }
            
            // 4. 更新任务次数
            int newTaskCount = user.getTask() + 1;
            updateUserTask(uid, newTaskCount);
            
            // 5. 如果达到5次,发放奖励
            if (newTaskCount == 5) {
                sendReward(uid);
            }
            
            result.put("code", 200);
            result.put("msg", "成功");
            return result;
            
        } catch (Exception e) {
            result.put("code", 500);
            result.put("msg", "系统错误");
            return result;
        }
    }
    
    private User getUserFromDatabase(Long uid) {
        // 从数据库查询用户
        // 实现数据库查询逻辑
        return new User(); // 示例
    }
    
    private void updateUserTask(Long uid, int newTaskCount) {
        // 更新数据库中的任务次数
        // 实现数据库更新逻辑
    }
    
    private void sendReward(Long uid) {
        // 发放奖励逻辑
    }
}

任务领取代码

@Service
@Transactional(rollbackFor = Exception.class)
public class TaskService {
    
    @Autowired
    private UserTaskNotesMapper userTaskNotesMapper;
    
    @Autowired
    private FudouService fudouService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private UserMapper userMapper;
    
    /**
     * 获取累积笔记(积分释放)
     * @param uid 用户ID
     * @return 操作结果
     */
    public boolean getLjNotes(Long uid) {
        return TransactionSynchronizationManager.isActualTransactionActive() 
            ? executeInTransaction(uid) 
            : executeWithNewTransaction(uid);
    }
    
    /**
     * 在现有事务中执行
     */
    private boolean executeInTransaction(Long uid) {
        try {
            return processLjNotes(uid);
        } catch (Exception e) {
            throw new BusinessException("领取失败", e);
        }
    }
    
    /**
     * 开启新事务执行
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public boolean executeWithNewTransaction(Long uid) {
        try {
            return processLjNotes(uid);
        } catch (Exception e) {
            throw new BusinessException("领取失败", e);
        }
    }
    
    /**
     * 处理累积笔记的核心逻辑
     */
    private boolean processLjNotes(Long uid) {
        // 1. 获取该释放的所有积分
        BigDecimal allJifen = userTaskNotesMapper.sumNumByCondition(uid, 1, 1);
        if (allJifen == null || allJifen.compareTo(BigDecimal.ZERO) <= 0) {
            return false;
        }
        
        // 2. 增加用户fudou余额
        boolean res1 = userService.bcInc(uid, "fudou", allJifen, 4);
        
        // 3. 创建fudou记录
        Fudou fudou = new Fudou();
        fudou.setUid(uid);
        fudou.setType(5);
        fudou.setNum(allJifen);
        fudou.setPm(1);
        fudou.setLinkId(0L);
        fudou.setAddTime(LocalDateTime.now());
        fudou.setLevel(66);
        boolean res2 = fudouService.save(fudou);
        
        // 4. 更新记录为释放状态
        boolean res3 = userTaskNotesMapper.updateStatusByCondition(uid, 1, 1, 2) > 0;
        
        // 5. 重置用户lj_num
        boolean res4 = userService.update(uid, Map.of("lj_num", BigDecimal.ZERO));
        
        if (res1 && res2 && res3 && res4) {
            return true;
        } else {
            throw new BusinessException("领取失败");
        }
    }
}
 

 

 

posted @ 2026-04-24 18:24  15889726201  阅读(3)  评论(0)    收藏  举报