乐于分享
好东西不私藏

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

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

卷轴模式系统包含的主要功能:商城,分销,实名认证,活跃度机制,任务模型,农场,锁仓机制,积分机制,交易机制,转赠机制,激励广告,减产机制,级别机制,手续费等等。(系统开发: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 {    @Autowired    private StringRedisTemplate redisTemplate;    @PostMapping("/watchVideo")    public Map<StringObjectwatchVideo(@RequestParamLong uid) {        Map<StringObject> result = new HashMap<>();        // 1. 检查缓存锁        String cacheKey = "cache_purchase_" + uid;        Boolean lock = redisTemplate.opsForValue()                .setIfAbsent(cacheKey, "1"2TimeUnit.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, 11);        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, 112) > 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("领取失败");        }    }}