feat: 新增大转盘功能模块

This commit is contained in:
陈淳
2024-02-26 18:44:11 +08:00
parent 3532bf54e7
commit 11b94f965c
12 changed files with 308 additions and 6 deletions

View File

@@ -6,9 +6,11 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Application.Services;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Users;
using Yi.Framework.Bbs.Application.Contracts.Dtos.Integral;
using Yi.Framework.Bbs.Domain.Managers;
using Yi.Framework.Bbs.Domain.Shared.Etos;
using Yi.Framework.Rbac.Domain.Authorization;
namespace Yi.Framework.Bbs.Application.Services.Integral
@@ -17,10 +19,12 @@ namespace Yi.Framework.Bbs.Application.Services.Integral
{
private IntegralManager _integralManager;
private ICurrentUser _currentUser;
public IntegralService(IntegralManager integralManager, ICurrentUser currentUser)
private ILocalEventBus _localEventBus;
public IntegralService(IntegralManager integralManager, ICurrentUser currentUser, ILocalEventBus localEventBus)
{
_integralManager = integralManager;
_currentUser = currentUser;
_localEventBus = localEventBus;
}

View File

@@ -0,0 +1,56 @@
using System;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Abp.EventBus.Local;
using Yi.Framework.Bbs.Domain.Shared.Etos;
namespace Yi.Framework.Bbs.Application.Services.Integral
{
public class LuckyService : ApplicationService
{
private ILocalEventBus _localEventBus;
public LuckyService(ILocalEventBus localEventBus) { _localEventBus = localEventBus; }
/// <summary>
/// 大转盘
/// </summary>
/// <returns></returns>
[Authorize]
public async Task<int> PostWheel()
{
int[] values=new int[10] { 0,10,30,50,80,100,150,200,300,666};
var index = GetWheelIndex();
var value = values[index]-50;
//修改钱钱,如果钱钱不足,直接会丢出去,那本次抽奖将无效
await _localEventBus.PublishAsync(new MoneyChangeEventArgs { UserId = CurrentUser.Id!.Value, Number = value }, false);
return index;
}
private int GetWheelIndex()
{
int[] probabilities = { 10, 15, 10, 20, 10, 5, 5, 3, 2, 1 };
int total = 0;
foreach (var prob in probabilities)
{
total += prob;
}
int randomNum = new Random().Next(1, total + 1);
int cumulativeProb = 0;
for (int i = 0; i < probabilities.Length; i++)
{
cumulativeProb += probabilities[i];
if (randomNum <= cumulativeProb)
{
return i;
}
}
var value = probabilities.Length - 1;
return value;
}
}
}

View File

@@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@lucky-canvas/vue": "^0.1.11",
"@microsoft/signalr": "^8.0.0",
"axios": "^1.3.4",
"dayjs": "^1.11.10",
@@ -855,6 +856,51 @@
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
"node_modules/@lucky-canvas/vue": {
"version": "0.1.11",
"resolved": "https://registry.npmmirror.com/@lucky-canvas/vue/-/vue-0.1.11.tgz",
"integrity": "sha512-5vm0txSKRBtMgrE/HZEvw1joSTx9NTdAkc8tBp/aX0LxyhQtiTVBLsRgdYUK/OiURCL8bo+046BTGnV+Q4JFlg==",
"dependencies": {
"@vue/composition-api": "^1.0.0",
"lucky-canvas": "^1.7.23",
"vue-demi": "^0.7.4"
},
"peerDependencies": {
"vue": "^2.0.0 || >=3.0.0-rc.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@lucky-canvas/vue/node_modules/@vue/composition-api": {
"version": "1.7.2",
"resolved": "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz",
"integrity": "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==",
"peerDependencies": {
"vue": ">= 2.5 < 2.7"
}
},
"node_modules/@lucky-canvas/vue/node_modules/vue-demi": {
"version": "0.7.5",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.7.5.tgz",
"integrity": "sha512-eFSQSvbQdY7C9ujOzvM6tn7XxwLjn0VQDXQsiYBLBwf28Na+2nTQR4BBBcomhmdP6mmHlBKAwarq6a0BPG87hQ==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-beta.1",
"vue": "^2.6.0 || >=3.0.0-rc.1"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@microsoft/signalr": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz",
@@ -2673,6 +2719,11 @@
"node": ">=10"
}
},
"node_modules/lucky-canvas": {
"version": "1.7.27",
"resolved": "https://registry.npmmirror.com/lucky-canvas/-/lucky-canvas-1.7.27.tgz",
"integrity": "sha512-Ftz6qD+863bI7xijBmZg3dw3cNEc7odPr70EZQcGA14y3TgTAzH65HPosOCd6kKUlMwhntBaHMx3onoj9MtJRQ=="
},
"node_modules/magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
@@ -4617,6 +4668,30 @@
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
"@lucky-canvas/vue": {
"version": "0.1.11",
"resolved": "https://registry.npmmirror.com/@lucky-canvas/vue/-/vue-0.1.11.tgz",
"integrity": "sha512-5vm0txSKRBtMgrE/HZEvw1joSTx9NTdAkc8tBp/aX0LxyhQtiTVBLsRgdYUK/OiURCL8bo+046BTGnV+Q4JFlg==",
"requires": {
"@vue/composition-api": "^1.0.0",
"lucky-canvas": "^1.7.23",
"vue-demi": "^0.7.4"
},
"dependencies": {
"@vue/composition-api": {
"version": "1.7.2",
"resolved": "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz",
"integrity": "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==",
"requires": {}
},
"vue-demi": {
"version": "0.7.5",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.7.5.tgz",
"integrity": "sha512-eFSQSvbQdY7C9ujOzvM6tn7XxwLjn0VQDXQsiYBLBwf28Na+2nTQR4BBBcomhmdP6mmHlBKAwarq6a0BPG87hQ==",
"requires": {}
}
}
},
"@microsoft/signalr": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz",
@@ -6128,6 +6203,11 @@
"yallist": "^4.0.0"
}
},
"lucky-canvas": {
"version": "1.7.27",
"resolved": "https://registry.npmmirror.com/lucky-canvas/-/lucky-canvas-1.7.27.tgz",
"integrity": "sha512-Ftz6qD+863bI7xijBmZg3dw3cNEc7odPr70EZQcGA14y3TgTAzH65HPosOCd6kKUlMwhntBaHMx3onoj9MtJRQ=="
},
"magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",

View File

@@ -10,6 +10,7 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@lucky-canvas/vue": "^0.1.11",
"@microsoft/signalr": "^8.0.0",
"axios": "^1.3.4",
"dayjs": "^1.11.10",

View File

@@ -13,3 +13,10 @@ export function signInRecord() {
method: "get"
});
}
export function luckyWheel() {
return request({
url: "/lucky/wheel",
method: "post"
});
}

View File

@@ -18,7 +18,7 @@
<el-icon><Memo /></el-icon>
<span>任务列表</span>
</el-menu-item>
<el-menu-item index="4" :route="{path:'/activity/sign'}">
<el-menu-item index="4" :route="{path:'/activity/lucky'}">
<el-icon><HelpFilled /></el-icon>
<span>大转盘</span>
</el-menu-item>

View File

@@ -11,6 +11,7 @@ import "@/assets/styles/index.scss"; // global css
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import directive from "./directive"; // directive
import VueLuckyCanvas from '@lucky-canvas/vue'
import "./permission";
@@ -24,6 +25,7 @@ import "./permission";
app.use(pinia);
directive(app);
app.use(router);
app.use(VueLuckyCanvas);
await router.isReady();
app.mount("#app");
})();

View File

@@ -122,6 +122,14 @@ const router = createRouter({
title: "等级",
},
},
{
name: "lucky",
path: "lucky",
component: () => import("../views/lucky/Index.vue"),
meta: {
title: "大转盘",
},
},
],
},
{ path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound },

View File

@@ -39,9 +39,10 @@ import {getList,upgrade} from '@/apis/levelApi.js'
import {getBbsUserProfile} from '@/apis/userApi.js'
import { ref,onMounted, reactive,computed } from 'vue'
import useAuths from '@/hooks/useAuths.js';
const { isLogin,currentUserInfo } = useAuths();
import useUserStore from "@/stores/user";
const { isLogin } = useAuths();
const userInfo=ref({});
const currentUserInfo=useUserStore();
const levelData =ref([]);
const moneyNum=ref(1);
@@ -73,7 +74,7 @@ const loadLevelData= async () => {
const loadUserInfoData=async()=>{
if(isLogin)
{
const {data}= await getBbsUserProfile(currentUserInfo.value.id);
const {data}= await getBbsUserProfile(currentUserInfo.id);
userInfo.value=data;
}
}

View File

@@ -0,0 +1,118 @@
<template>
<div>
<h2>谨记人生赌博不如理性规划</h2>
<h3>50钱钱一次,我的钱钱:{{ userInfo?.money ?? '未登录' }}</h3>
<LuckyWheel class="wheel" ref="myLucky" width="500px" height="500px" :prizes="prizes" :blocks="blocks"
:buttons="buttons" @start="startCallback" @end="endCallback" />
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import useAuths from '@/hooks/useAuths.js';
const { isLogin } = useAuths();
import { getBbsUserProfile } from '@/apis/userApi.js'
import { luckyWheel } from '@/apis/integralApi.js'
import useUserStore from "@/stores/user";
const userInfo = ref({});
const currentUserInfo=useUserStore();
onMounted(async () => {
await loadUserInfoData();
})
const loadUserInfoData = async () => {
if (isLogin) {
const { data } = await getBbsUserProfile(currentUserInfo.id);
userInfo.value = data;
}
}
const blocks = [{ padding: '13px', background: '#617df2' }];
const prizes = [
{ fonts: [{ text: '啥也没有', top: '10%' }], background: '#e9e8fe' },
{ fonts: [{ text: '10', top: '10%' }], background: '#b8c5f2' },
{ fonts: [{ text: '30', top: '10%' }], background: '#e9e8fe' },
{ fonts: [{ text: '50', top: '10%' }], background: '#b8c5f2' },
{ fonts: [{ text: '80', top: '10%' }], background: '#e9e8fe' },
{ fonts: [{ text: '100', top: '10%' }], background: '#b8c5f2' },
{ fonts: [{ text: '150', top: '10%' }], background: '#e9e8fe' },
{ fonts: [{ text: '200', top: '10%' }], background: '#b8c5f2' },
{ fonts: [{ text: '300', top: '10%' }], background: '#e9e8fe' },
{ fonts: [{ text: '666', top: '10%' }], background: '#FAD400' }
];
const buttons = [{
radius: '35%',
background: '#8a9bf3',
pointer: true,
fonts: [{ text: '启动', top: '-10px' }]
}];
const myLucky = ref(null);
// 点击抽奖按钮会触发star回调
const startCallback = () => {
var index =0;
// 调用抽奖组件的play方法开始游戏
if (!isLogin) {
ElMessage({
message: '请登录后启动!',
type: 'warning',
})
return;
}
ElMessageBox.confirm(
'每次启动需要消耗50钱钱确定要启动吗?',
'警告',
{
confirmButtonText: '启动',
cancelButtonText: '放弃',
type: 'warning',
}
)
.then(async () => {
myLucky.value.play()
//等待3秒
// 模拟调用接口异步抽奖
setTimeout(() => {
// 假设后端返回的中奖索引是0
// 调用stop停止旋转并传递中奖索引
}, 3000)
index= (await luckyWheel()).data;
myLucky.value.stop(index)
})
.catch(() => {
ElMessage({
type: 'info',
message: '成功克制',
})
})
};
// 抽奖结束会触发end回调
const endCallback = async (prize) => {
ElMessage({
type: 'success',
message: `恭喜你抽中了[${prize.fonts[0].text}]`,
})
await loadUserInfoData();
}
</script>
<style scoped>
.wheel {
margin: auto;
margin-top: 10%;
}
h2 {
text-align: center;
}
h3 {
text-align: center;
}
</style>

View File

@@ -34,6 +34,7 @@
import { onMounted, ref, reactive, computed, nextTick, watch } from "vue";
import { signIn, signInRecord } from "@/apis/integralApi.js";
import useAuths from "@/hooks/useAuths";
const { isLogin } = useAuths();
const number=ref(0);
const signInData=ref([]);

View File

@@ -286,6 +286,15 @@
"@jridgewell/resolve-uri" "3.1.0"
"@jridgewell/sourcemap-codec" "1.4.14"
"@lucky-canvas/vue@^0.1.11":
"integrity" "sha512-5vm0txSKRBtMgrE/HZEvw1joSTx9NTdAkc8tBp/aX0LxyhQtiTVBLsRgdYUK/OiURCL8bo+046BTGnV+Q4JFlg=="
"resolved" "https://registry.npmmirror.com/@lucky-canvas/vue/-/vue-0.1.11.tgz"
"version" "0.1.11"
dependencies:
"@vue/composition-api" "^1.0.0"
"lucky-canvas" "^1.7.23"
"vue-demi" "^0.7.4"
"@microsoft/signalr@^8.0.0":
"integrity" "sha512-K/wS/VmzRWePCGqGh8MU8OWbS1Zvu7DG7LSJS62fBB8rJUXwwj4axQtqrAAwKGUZHQF6CuteuQR9xMsVpM2JNA=="
"resolved" "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz"
@@ -475,6 +484,11 @@
"@vue/compiler-dom" "3.2.47"
"@vue/shared" "3.2.47"
"@vue/composition-api@^1.0.0", "@vue/composition-api@^1.0.0-beta.1":
"integrity" "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw=="
"resolved" "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz"
"version" "1.7.2"
"@vue/devtools-api@^6.4.5", "@vue/devtools-api@^6.5.0":
"integrity" "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
"resolved" "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz"
@@ -1499,6 +1513,11 @@
dependencies:
"yallist" "^4.0.0"
"lucky-canvas@^1.7.23":
"integrity" "sha512-Ftz6qD+863bI7xijBmZg3dw3cNEc7odPr70EZQcGA14y3TgTAzH65HPosOCd6kKUlMwhntBaHMx3onoj9MtJRQ=="
"resolved" "https://registry.npmmirror.com/lucky-canvas/-/lucky-canvas-1.7.27.tgz"
"version" "1.7.27"
"magic-string@^0.25.7":
"integrity" "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="
"resolved" "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz"
@@ -2239,6 +2258,11 @@
"resolved" "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz"
"version" "0.13.11"
"vue-demi@^0.7.4":
"integrity" "sha512-eFSQSvbQdY7C9ujOzvM6tn7XxwLjn0VQDXQsiYBLBwf28Na+2nTQR4BBBcomhmdP6mmHlBKAwarq6a0BPG87hQ=="
"resolved" "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.7.5.tgz"
"version" "0.7.5"
"vue-router@^4.1.6":
"integrity" "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ=="
"resolved" "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz"
@@ -2246,7 +2270,7 @@
dependencies:
"@vue/devtools-api" "^6.4.5"
"vue@^2.6.14 || ^3.2.0", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.2.0", "vue@^3.2.23", "vue@^3.2.25", "vue@^3.2.47", "vue@2 || 3", "vue@3.2.47":
"vue@^2.0.0 || >=3.0.0-rc.0", "vue@^2.6.0 || >=3.0.0-rc.1", "vue@^2.6.14 || ^3.2.0", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.2.0", "vue@^3.2.23", "vue@^3.2.25", "vue@^3.2.47", "vue@>= 2.5 < 2.7", "vue@2 || 3", "vue@3.2.47":
"integrity" "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ=="
"resolved" "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz"
"version" "3.2.47"