实现抽奖接口
This commit is contained in:
parent
bb2d99742c
commit
3bdd960cfa
32
doc/api.md
32
doc/api.md
@ -526,12 +526,15 @@
|
|||||||
3. Response: JSON
|
3. Response: JSON
|
||||||
|
|
||||||
```js
|
```js
|
||||||
[{
|
[ // 奖励列表
|
||||||
"name": '显示名',
|
{
|
||||||
"reward_type": '奖励物品的id',
|
coupon: '优惠券的id',
|
||||||
"reward_count": 100, //奖励物品数量
|
name: '优惠券名',
|
||||||
"icon": "item/item_0" // 奖励物品的图片地址, 可能是本地,远程, 如果该字段为空的话, 需要取本地的默认值
|
count: 1, //数量
|
||||||
}]
|
couponUrl: '优惠券详情图的url',
|
||||||
|
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
||||||
|
}
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 14. 抽奖
|
### 14. 抽奖
|
||||||
@ -553,12 +556,13 @@
|
|||||||
3. Response: JSON
|
3. Response: JSON
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
[{ // 本次请求新获得的物品
|
||||||
"name": '显示名',
|
coupon: '优惠券的id',
|
||||||
"reward_type": '奖励物品的id',
|
name: '优惠券名',
|
||||||
"reward_count": 100, //奖励物品数量
|
count: 1, //数量
|
||||||
"icon": "item/item_0" // 奖励物品的图片地址, 可能是本地,远程, 如果该字段为空的话, 需要取本地的默认值
|
couponUrl: '优惠券详情图的url',
|
||||||
}
|
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
||||||
|
}]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -583,13 +587,13 @@
|
|||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
num: 10, // 已邀请人数
|
num: 10, // 已邀请人数
|
||||||
newget: [ // 本次请求新获得的物品
|
newget: [{ // 本次请求新获得的物品
|
||||||
coupon: '优惠券的id',
|
coupon: '优惠券的id',
|
||||||
name: '优惠券名',
|
name: '优惠券名',
|
||||||
count: 1, //数量
|
count: 1, //数量
|
||||||
couponUrl: '优惠券详情图的url',
|
couponUrl: '优惠券详情图的url',
|
||||||
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
||||||
]
|
}]
|
||||||
rewards: [ // 奖励列表
|
rewards: [ // 奖励列表
|
||||||
{
|
{
|
||||||
coupon: '优惠券的id',
|
coupon: '优惠券的id',
|
||||||
|
@ -94,7 +94,7 @@ class GameUserController extends BaseController {
|
|||||||
throw new ZError(12, '当前店铺未配置相关信息')
|
throw new ZError(12, '当前店铺未配置相关信息')
|
||||||
}
|
}
|
||||||
if (!cfg.share_cfgs || cfg.share_cfgs.length === 0) {
|
if (!cfg.share_cfgs || cfg.share_cfgs.length === 0) {
|
||||||
throw new ZError(12, '当前店铺未配置相关信息')
|
throw new ZError(13, '当前店铺未配置相关信息')
|
||||||
}
|
}
|
||||||
let rewardList = []
|
let rewardList = []
|
||||||
let newItems: any[] = []
|
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 {
|
export class LotteryCfgClass extends Base {
|
||||||
|
/**
|
||||||
|
* 获取概率
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
@prop()
|
||||||
|
public rank: number
|
||||||
@prop()
|
@prop()
|
||||||
public name: string
|
public name: string
|
||||||
|
|
||||||
|
@ -8,3 +8,27 @@ export function getRandom(max: number, min?: number): number {
|
|||||||
min = min || 0
|
min = min || 0
|
||||||
return Math.floor(Math.random() * (max - min) + min)
|
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