实现抽奖接口
This commit is contained in:
parent
bb2d99742c
commit
3bdd960cfa
32
doc/api.md
32
doc/api.md
@ -526,12 +526,15 @@
|
||||
3. Response: JSON
|
||||
|
||||
```js
|
||||
[{
|
||||
"name": '显示名',
|
||||
"reward_type": '奖励物品的id',
|
||||
"reward_count": 100, //奖励物品数量
|
||||
"icon": "item/item_0" // 奖励物品的图片地址, 可能是本地,远程, 如果该字段为空的话, 需要取本地的默认值
|
||||
}]
|
||||
[ // 奖励列表
|
||||
{
|
||||
coupon: '优惠券的id',
|
||||
name: '优惠券名',
|
||||
count: 1, //数量
|
||||
couponUrl: '优惠券详情图的url',
|
||||
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### 14. 抽奖
|
||||
@ -553,12 +556,13 @@
|
||||
3. Response: JSON
|
||||
|
||||
```js
|
||||
{
|
||||
"name": '显示名',
|
||||
"reward_type": '奖励物品的id',
|
||||
"reward_count": 100, //奖励物品数量
|
||||
"icon": "item/item_0" // 奖励物品的图片地址, 可能是本地,远程, 如果该字段为空的话, 需要取本地的默认值
|
||||
}
|
||||
[{ // 本次请求新获得的物品
|
||||
coupon: '优惠券的id',
|
||||
name: '优惠券名',
|
||||
count: 1, //数量
|
||||
couponUrl: '优惠券详情图的url',
|
||||
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
||||
}]
|
||||
```
|
||||
|
||||
|
||||
@ -583,13 +587,13 @@
|
||||
```js
|
||||
{
|
||||
num: 10, // 已邀请人数
|
||||
newget: [ // 本次请求新获得的物品
|
||||
newget: [{ // 本次请求新获得的物品
|
||||
coupon: '优惠券的id',
|
||||
name: '优惠券名',
|
||||
count: 1, //数量
|
||||
couponUrl: '优惠券详情图的url',
|
||||
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
||||
]
|
||||
}]
|
||||
rewards: [ // 奖励列表
|
||||
{
|
||||
coupon: '优惠券的id',
|
||||
|
@ -94,7 +94,7 @@ class GameUserController extends BaseController {
|
||||
throw new ZError(12, '当前店铺未配置相关信息')
|
||||
}
|
||||
if (!cfg.share_cfgs || cfg.share_cfgs.length === 0) {
|
||||
throw new ZError(12, '当前店铺未配置相关信息')
|
||||
throw new ZError(13, '当前店铺未配置相关信息')
|
||||
}
|
||||
let rewardList = []
|
||||
let newItems: any[] = []
|
||||
|
105
src/api/controllers/lottery.controller.ts
Normal file
105
src/api/controllers/lottery.controller.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import BaseController from '../../common/base.controller'
|
||||
import { role, router } from '../../decorators/router'
|
||||
import { ZError } from '../../common/ZError'
|
||||
import { Shop } from '../../models/shop/Shop'
|
||||
import { ShopCfg } from '../../models/shop/ShopCfg'
|
||||
import { Coupon } from '../../models/shop/Coupon'
|
||||
import { getCouponUrl } from '../../services/File'
|
||||
import { UserItem } from '../../models/user/UserItem'
|
||||
import { LOTTERY_TICKET } from '../../constants/BaseConst'
|
||||
import { UserReward } from '../../models/user/UserReward'
|
||||
import { random_prob } from '../../utils/number.util'
|
||||
|
||||
class LotteryController extends BaseController {
|
||||
@role('anon')
|
||||
@router('post /api/:accountId/lottery_info')
|
||||
async info(req: any) {
|
||||
const { accountId, sid, sessionid } = req.params
|
||||
if (!sid) {
|
||||
throw new ZError(10, '缺少必要参数: sid')
|
||||
}
|
||||
const shop = await Shop.fetchByID(sid)
|
||||
if (!shop) {
|
||||
throw new ZError(11, '无法找到对应店铺')
|
||||
}
|
||||
const cfg = await ShopCfg.findOne({ shop: shop.id })
|
||||
if (!cfg) {
|
||||
throw new ZError(12, '当前店铺未配置相关信息')
|
||||
}
|
||||
if (!cfg.lottery_cfgs || cfg.lottery_cfgs.length === 0) {
|
||||
throw new ZError(12, '当前店铺未配置相关信息')
|
||||
}
|
||||
let rewardList = []
|
||||
let couponMap: Map<string, any> = new Map()
|
||||
for (let reward of cfg.lottery_cfgs) {
|
||||
let name = '抽奖券'
|
||||
let couponUrl = reward.icon
|
||||
if (reward.rewardType === 0) {
|
||||
if (!couponMap.has(reward.coupon)) {
|
||||
let coupon = await Coupon.findById(reward.coupon)
|
||||
couponMap.set(coupon.id, coupon)
|
||||
}
|
||||
name = couponMap.get(reward.coupon).name
|
||||
couponUrl = reward.icon || getCouponUrl(shop.id, reward.coupon)
|
||||
}
|
||||
rewardList.push({
|
||||
coupon: reward.coupon,
|
||||
name,
|
||||
count: reward.count,
|
||||
couponUrl,
|
||||
rewardType: reward.rewardType,
|
||||
})
|
||||
}
|
||||
return rewardList
|
||||
}
|
||||
|
||||
@role('anon')
|
||||
@router('post /api/:accountId/lottery')
|
||||
async draw(req: any) {
|
||||
const { accountId, sid, sessionid } = req.params
|
||||
if (!sid) {
|
||||
throw new ZError(10, '缺少必要参数: sid')
|
||||
}
|
||||
const shop = await Shop.fetchByID(sid)
|
||||
if (!shop) {
|
||||
throw new ZError(11, '无法找到对应店铺')
|
||||
}
|
||||
const cfg = await ShopCfg.findOne({ shop: shop.id })
|
||||
if (!cfg) {
|
||||
throw new ZError(12, '当前店铺未配置相关信息')
|
||||
}
|
||||
if (!cfg.lottery_cfgs || cfg.lottery_cfgs.length === 0) {
|
||||
throw new ZError(13, '当前店铺未配置相关信息')
|
||||
}
|
||||
const count = await UserItem.fetchCount({ accountId, shop: shop.id, item: LOTTERY_TICKET })
|
||||
if (count < 1) {
|
||||
throw new ZError(14, '券不够了')
|
||||
}
|
||||
await UserItem.addOne({
|
||||
accountId,
|
||||
shop: shop.id,
|
||||
item: LOTTERY_TICKET,
|
||||
count: -1,
|
||||
reason: 'lottery',
|
||||
params: {},
|
||||
})
|
||||
let arr = []
|
||||
for (let data of cfg.lottery_cfgs) {
|
||||
arr.push(data.rank)
|
||||
}
|
||||
let idx = random_prob(arr)
|
||||
const reward = cfg.lottery_cfgs[idx]
|
||||
let obj = await UserReward.saveOneRecord({
|
||||
accountId,
|
||||
shop: shop.id,
|
||||
itemId: reward.coupon,
|
||||
count: reward.count,
|
||||
rewardId: reward._id + '',
|
||||
activityId: 'lottery',
|
||||
source: 'lottery',
|
||||
})
|
||||
let rewardList = []
|
||||
rewardList.push(obj)
|
||||
return rewardList
|
||||
}
|
||||
}
|
@ -30,6 +30,12 @@ export class ShareCfgClass extends Base {
|
||||
}
|
||||
|
||||
export class LotteryCfgClass extends Base {
|
||||
/**
|
||||
* 获取概率
|
||||
* @type {number}
|
||||
*/
|
||||
@prop()
|
||||
public rank: number
|
||||
@prop()
|
||||
public name: string
|
||||
|
||||
|
@ -8,3 +8,27 @@ export function getRandom(max: number, min?: number): number {
|
||||
min = min || 0
|
||||
return Math.floor(Math.random() * (max - min) + min)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据概率数组获取随机index
|
||||
* @since 1.0.0
|
||||
* @param prob_array 概率数组
|
||||
*/
|
||||
export function random_prob(prob_array: number[]): number {
|
||||
let total = 0
|
||||
for (let _d of prob_array) {
|
||||
total += _d
|
||||
}
|
||||
prob_array = prob_array.map(o => o / total)
|
||||
// 获取随机数
|
||||
let r = Math.random()
|
||||
// 对概率数组的处理
|
||||
let s = prob_array
|
||||
.map((v, index) => {
|
||||
return { index: index, prob: v }
|
||||
})
|
||||
.sort((a, b) => a.prob - b.prob)
|
||||
// 判断随机位置
|
||||
let result = s.find(v => (r -= v.prob) <= 0)
|
||||
return result ? result.index : s.length - 1
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user