卷轴模式开发功能模块与源码解析
卷轴模式系统包含的主要功能:商城,分销,实名认证,活跃度机制,任务模型,农场,锁仓机制,积分机制,交易机制,转赠机制,激励广告,减产机制,级别机制,手续费等等。(系统开发:15889726201)
客户端设计思路: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数量的值,而是今天参加了打卡看视频广告任务,并且设定的视频广告任务数量后,这个活跃值就产生了。若没有完成今天的打卡任务,这个活跃值也不会存在。
卷轴任务包核心源码
任务积分释放代码
@RestControllerpublic class VideoController {@Autowiredprivate StringRedisTemplate redisTemplate;@PostMapping("/watchVideo")public Map<String, Object> watchVideo(@RequestParamLong 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 {@Autowiredprivate UserTaskNotesMapper userTaskNotesMapper;@Autowiredprivate FudouService fudouService;@Autowiredprivate UserService userService;@Autowiredprivate 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_numboolean res4 = userService.update(uid, Map.of("lj_num", BigDecimal.ZERO));if (res1 && res2 && res3 && res4) {return true;} else {throw new BusinessException("领取失败");}}}

夜雨聆风