Springboot+Vue服务器盲盒活动
本项目是基于Springboot+Vue2.x开发的虚拟机活动系统,前端UI设计使用了ElementUI,后端数据库采用MySQL、整合了MybatisPlus、JWT。该系统大体上分为登录模块、抽奖模块、奖券操作模块、实例操作模块。
文章目录
一、项目要求
- G:\s_-project01_zy\Springboot_Vue\SpringBoot_Second\Spring_Project_SecondBack 包含Springboot
展示Spring_Project_SecondBack
- G:\s_-project01_zy\Springboot_Vue\vue 包含Vue
展示G:\s_-project01_zy\Springboot_Vue\vue
姓名拼音+学号(zhanyong)
随机获取2,3字符串random()
2,3,3,2
盲盒系统(虚拟机)
加入随机的数字
这是没有加入本身内容的,即没有中奖,中奖内容如下:
- 打折扣
- 升降级(vm升级,指定cpu,内存,单向指定哪一台进行升级)可拆分5中策略
- 对购买时长的升级
- 送一台虚拟机
这五种自动生产或者指定生成
- 一个月最多三次,充中不能再抽中
- 虚拟机列表
- 随机组合(五种)
命名规则类似阿里云服务器的命名
【下图是阿里云的命名】
二、说明文档
1、用户抽奖主页/raffle
2、多种奖品链接
{ id: 1, selected: false, prize: false, prizeContent: "奖品1:打折扣" },
{ id: 2, selected: false, prize: false, prizeContent: "奖品2:cpu升级" },
{ id: 3, selected: false, prize: false, prizeContent: "奖品3:内存升级" },
{ id: 4, selected: false, prize: false, prizeContent: "奖品4:增加时长" },
{ id: 5, selected: false, prize: false, prizeContent: "奖品5:送服务器" },
{ id: 6, selected: false, prize: false, prizeContent: "奖品6:配置升级" },
1、奖品1 discont /discount
2、奖品2 CPU upgrade /cpu
3、奖品3 Memory upgrade /memory
4、奖品4 Increase duration /duration
5、奖品5 Send to server /server
6、奖品6 Configuration upgrade /upgrade
3、后台侧边栏/instance
1、商品兑换 Product exchange /exchange
2、中奖说明 Information /information
3、容器实例 Instance /instance
4、订单中心 Order/order
5、设置 Setting/setting
三、前端
1、用户主页
a、主体框架
使用elementUI
控件
<template>
<div>
<el-container>
<el-header>
云服务器抽奖系统
<el-dropdown style="width: 150px; cursor: pointer; text-align: right">
<div style="display: inline-block">
<img :src="userImage" alt=""
style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px">
<span>{{username}}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
</div>
<el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/prize" style="text-decoration: none">查看奖品</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/instance" style="text-decoration: none">虚拟机实例</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<span style="text-decoration: none" @click="logout">退出</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<div class="container">
<div v-for="box in boxes" :key="box.id">
<div
v-if="box.selected"
class="box box--selected"
>
{{ box.prize ? box.prizeContent : '未中奖' }}
</div>
<div
v-else
class="box"
@click="checkPrize(box)"
>
盲盒{{ box.id }}
</div>
</div>
</div>
</el-main>
<el-footer>rj201 zy</el-footer>
</el-container>
</div>
</template>
<script>
export default {
name: "RaffleLogin",
data() {
return {
boxes: [
{ id: 1, selected: false, prize: false, prizeContent: "奖品1:打折扣" },
{ id: 2, selected: false, prize: false, prizeContent: "奖品2:cpu升级" },
{ id: 3, selected: false, prize: false, prizeContent: "奖品3:内存升级" },
{ id: 4, selected: false, prize: false, prizeContent: "奖品4:增加时长" },
{ id: 5, selected: false, prize: false, prizeContent: "奖品5:送虚拟机" },
{ id: 6, selected: false, prize: false, prizeContent: "奖品6:配置升级" },
// 添加更多方框...
],
username:"zy",
userImage:"https://daetz-image.oss-cn-hangzhou.aliyuncs.com/img/202306031111027.png"
};
},
methods: {
checkPrize(box) {
// 模拟随机抽奖逻辑
if (box.selected) {
return; // 已经点击过的盒子不再处理点击事件
}
box.selected = true;
box.prize = Math.random() < 0.5; // 假设中奖概率为 50%
if (box.prize) {
this.$message.success(`恭喜你中奖了!${box.prizeContent}`);
} else {
this.$message.info("很遗憾,未中奖。");
}
},
logout() {
this.$store.commit("logout")
this.$message.success("退出成功")
}
}
};
</script>
<style scoped>
.el-header,
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-main {
background-color: #e9eef3;
color: #333;
text-align: center;
line-height: 160px;
}
.container {
display: flex;
flex-wrap: wrap;
}
.user-icon {
margin-left: auto;
}
.box {
width: 100px;
height: 100px;
margin: 10px;
background-color: gray;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.box--selected {
background-color: green;
cursor: not-allowed;
}
</style>
b、右上角用户展示
- 查看奖品
- 虚拟机实例
- 退出
2、后台根据奖品挑选内容
3、登录页面
<template>
<div class="wrapper">
<div
style="margin: 100px auto; background-color: #fff; width: 350px; height: 280px; padding: 20px; border-radius: 10px">
<div style="margin: 20px 0; text-align: center; font-size: 24px">云服务器选购用户登录</div>
<el-form :model="user" :rules="rules" ref="userForm">
<el-form-item prop="username">
<el-input size="medium" prefix-icon="el-icon-user" v-model="user.username"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input size="medium" prefix-icon="el-icon-lock" show-password
v-model="user.password"></el-input>
</el-form-item>
<el-form-item style="margin: 10px 0; text-align: right">
<el-button type="primary" size="small" autocomplete="off" @click="login">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "Login",
data() {
return {
user: {},
rules: {
username: [
{required: true, message: '请输入用户名', trigger: 'blur'},
{min: 3, max: 10, message: '长度在 3 到 5 个字符', trigger: 'blur'}
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'},
{min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur'}
],
}
}
},
methods: {
login() {
this.$refs['userForm'].validate((valid) => {
if (valid) { // 表单校验合法
request.post("/user/login", this.user).then(res => {
if (res.data.code === '200') {
localStorage.setItem("user", JSON.stringify(res.data.data)); // 存储用户信息到浏览器
this.$message.success("登录成功");
this.$router.push("/raffle");
}else {
this.$message.error(res.msg);
}
}).catch(error => {
console.log(error);
// 错误处理逻辑
});
}
});
}
}
}
</script>
<style scoped>
.wrapper {
height: 100vh;
background-image: linear-gradient(to bottom right, #D1D1D1, #BBBBBB);
overflow: hidden;
background-size: cover;
background-repeat: no-repeat;
}
</style>
4、实现右上角点击事件,查看奖品
5、设置后台最外层的页面包括header和aside
<template>
<div>
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1', '2']">
<el-submenu index="1" class="my-menu">
<template slot="title"><i class="el-icon-present"></i>奖品中心</template>
<el-menu-item-group >
<el-menu-item index="1-1">商品兑换</el-menu-item>
<el-menu-item index="1-1">中奖说明</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="2" class="my-menu">
<template slot="title"><i class="el-icon-user"></i>用户中心</template>
<el-menu-item-group >
<el-menu-item index="2-1">容器实例</el-menu-item>
<el-menu-item index="2-2">订单中心</el-menu-item>
<el-menu-item index="2-3">设置</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header>
云服务器抽奖系统后台
<el-dropdown style="width: 150px; cursor: pointer; text-align: right">
<div style="display: inline-block">
<img :src="userImage" alt=""
style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px">
<span>{{username}}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
</div>
<el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/exchange" style="text-decoration: none">查看奖品</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/instance" style="text-decoration: none">虚拟机实例</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<span style="text-decoration: none" @click="logout">退出</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
data(){
return{
username:'',
userImage:"https://daetz-image.oss-cn-hangzhou.aliyuncs.com/img/202306031111027.png",
}
},
created() {
const storedUser = localStorage.getItem('user');
const user = JSON.parse(storedUser);
this.username=user.username
}
}
</script>
<style scoped>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
.my-menu .el-submenu__title,
.my-menu .el-menu-item__title,
.my-menu .el-menu-item-group__title {
padding-left: 0 !important;
}
</style>
6、绑定侧边栏的点击事件跳转功能
使用push改变路径
<el-menu :default-openeds="['1', '2']">
<el-submenu index="1" class="my-menu">
<template slot="title"><i class="el-icon-present"></i>奖品中心</template>
<el-menu-item-group>
<el-menu-item index="1-1" @click="goToProductExchange">商品兑换</el-menu-item>
<el-menu-item index="1-2" @click="goToInformation">中奖说明</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="2" class="my-menu">
<template slot="title"><i class="el-icon-user"></i>用户中心</template>
<el-menu-item-group>
<el-menu-item index="2-1" @click="goToInstance">容器实例</el-menu-item>
<el-menu-item index="2-2" @click="goToOrder">订单中心</el-menu-item>
<el-menu-item index="2-3" @click="goToSetting">设置</el-menu-item>
</el-menu-item-group>
</el-submenu>
methods: {
goToProductExchange() {
this.$router.push('/back/exchange');
},
goToInformation() {
this.$router.push('/back/information');
},
goToInstance() {
this.$router.push('/back/instance');
},
goToOrder() {
this.$router.push('/back/order');
},
goToSetting() {
this.$router.push('/back/setting');
},
logout() {
this.$store.commit("logout")
this.$message.success("退出成功")
}
// 其他菜单项的跳转方法...
},
7、商品兑换数据传输分页查询
<template>
<div>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="name"
label="中奖用户"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="description"
label="中奖描述"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="priceTime"
label="中奖时间"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
style="flex-grow: 1;">
<template slot-scope="scope">
<el-button @click="edit(scope.row)" type="text" size="small">修改</el-button>
<el-button type="text" size="small" @click="deleteUser(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "ProductExchange",
data(){
return{
total:null,
tableData:null,
}
},
methods:{
deleteUser(row){
const _this=this
request.delete('/admin/delete/'+row.id).then(function (resp){
//console.log(resp)
alert("删除成功")
window.location.reload();
})
},
edit(row) {
this.$router.push({
path:'/update',
query:{
id:row.id
}
})
//row.id<点击的id>
},
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/findAward/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
})
}
},
created() { //alert 初始化操作
const _this=this
request.get('/findAward/1/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
console.log(resp.data)
console.log(resp.data.data)
})
},
}
</script>
<style scoped>
</style>
8、商品兑换根据类型处理可操作范围
1、通过query携带参数,通过params获取内容
<template>
<div>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="name"
label="中奖用户"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="description"
label="中奖描述"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="priceTime"
label="中奖时间"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
style="flex-grow: 1;">
<template slot-scope="scope">
<el-button @click="use(scope.row)" type="text" size="small">使用</el-button>
<el-button type="text" size="small" @click="deleteUser(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "ProductExchange",
data(){
return{
total:null,
tableData:null,
}
},
methods:{
deleteUser(row){
const _this=this
request.delete('/admin/delete/'+row.id).then(function (resp){
//console.log(resp)
alert("删除成功")
window.location.reload();
})
},
use(row) {
// 获取点击的 priceType
const priceType = row.priceType;
// 根据不同的 priceType 进行跳转
switch (priceType) {
case 'discount':
// 跳转到 discount 页面,传递选择的基本信息
this.$router.push({
path: 'discount',
query: {
award_id:row.id,
award_type: row.priceType,
// 其他选择的基本信息
}
});
break;
case 'cpu':
// 跳转到 cpu 页面,传递选择的基本信息
this.$router.push({
path: '/cpu',
query: {
award_id:row.id,
award_type: row.priceType,
// 其他选择的基本信息
}
});
break;
case 'memory':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: '/memory',
query: {
award_id:row.id,
award_type: row.priceType,
}
});
break;
case 'duration':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: '/duration',
query: {
award_id:row.id,
award_type: row.priceType,
}
});
break;
case 'sever':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: '/sever',
query: {
award_id:row.id,
award_type: row.priceType,
}
});
break;
case 'upgrade':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: '/upgrade',
query: {
award_id:row.id,
award_type: row.priceType,
}
});
break;
default:
//无默认内容
break;
}
},
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/findAward/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
})
}
},
created() { //alert 初始化操作
const _this=this
request.get('/findAward/1/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
//console.log(resp.data)
//console.log(resp.data.data)
//console.log(_this.tableData[0].priceType)//discount
})
},
}
</script>
<style scoped>
</style>
1、写入
switch (priceType) {
case 'discount':
// 跳转到 discount 页面,传递选择的基本信息
this.$router.push({
path: 'discount',
query: {
award_id:row.id,
award_type: row.priceType,
// 其他选择的基本信息
}
});
break;
2、接收
export default {
mounted() {
const awardId = this.$route.query.award_id;
const awardType = this.$route.query.award_type;
// 使用获取到的参数进行后续操作
console.log(awardId);
console.log(awardType);
}
}
2、处理使用中奖卷对服务的选择界面
<template>
<div>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePublicIp"
label="公网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePrivateIp"
label="私网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceName"
label="实例名称"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceDurationTime"
label="购买时长(月)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceSecurityGroupPorts"
label="端口号"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="instanceUpgradeCpu"
label="核数"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceUpgradeMemory"
label="内存(G)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceUpgradeDisk"
label="磁盘(G)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="instanceUpgradeBandwitdth"
label="计费模式"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="createdTime"
label="创建时间"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
style="flex-grow: 1;">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name:'ChooseInstance',
data() {
return {
total:null,
tableData:null,
awardId:null,
awardType:null,
}
},
methods: {
handleClick(row) {
//console.log(row);
},
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/findAward/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
})
}
},
created() { //alert 初始化操作
const _this=this
const awardType = this.awardType; // 访问实例属性awardType
request.get('/findAllInstance/1/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
if(_this.total>=1){
_this.$message.success('你可将'+_this.awardType+'中奖券使用在下面的服务器上!');
}else {
_this.$message.error('先去购买服务器吧!')
}
})
},
mounted() {
const awardId = this.$route.query.award_id;
const awardType = this.$route.query.award_type;
this.awardType=awardType;
}
}
</script>
3、右侧的使用按钮的点击事件
<template>
<div>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePublicIp"
label="公网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePrivateIp"
label="私网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceName"
label="实例名称"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceDurationTime"
label="购买时长(月)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceSecurityGroupPorts"
label="端口号"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="instanceUpgradeCpu"
label="核数"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceUpgradeMemory"
label="内存(G)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceUpgradeDisk"
label="磁盘(G)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="instanceUpgradeBandwitdth"
label="计费模式"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="createdTime"
label="创建时间"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
style="flex-grow: 1;">
<template slot-scope="scope">
<el-button @click="use(scope.row)" type="text" size="small">修改配置</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name:'ChooseInstance',
data() {
return {
total:null,
tableData:null,
awardId:null,
awardType:null,
sum:null,
}
},
mounted() {
const awardId = this.$route.query.award_id;
const awardType = this.$route.query.award_type;
const sum=this.$route.query.award_sum;
this.awardType=awardType;
this.awardId=awardId;
this.sum=sum;
},
methods: {
use(row) {
console.log(this.awardType)
console.log(this.awardId)
// 根据不同的 priceType 进行跳转
switch (this.awardType) {
case 'discount':
// 跳转到 discount 页面,传递选择的基本信息
this.$router.push({
path: 'discount',
query: {
award_id:this.awardId,
instance_id:row.id,
sum:this.sum,
// 其他选择的基本信息
}
});
break;
case 'cpu':
// 跳转到 cpu 页面,传递选择的基本信息
this.$router.push({
path: 'cpu',
query: {
award_id:this.awardId,
instance_id:row.id,
sum:this.sum,
// 其他选择的基本信息
}
});
break;
case 'memory':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: 'memory',
query: {
award_id:this.awardId,
instance_id:row.id,
sum:this.sum,
}
});
break;
case 'duration':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: 'duration',
query: {
award_id:this.awardId,
instance_id:row.id,
sum:this.sum,
}
});
break;
case 'sever':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: 'server',
query: {
award_id:this.awardId,
instance_id:row.id,
sum:this.sum,
}
});
break;
case 'upgrade':
// 跳转到 memory 页面,传递选择的基本信息
this.$router.push({
path: 'upgrade',
query: {
award_id:this.awardId,
instance_id:row.id,
sum:this.sum,
}
});
break;
default:
//无默认内容
break;
}
},
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/findAward/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
})
}
},
created() { //alert 初始化操作
const _this=this
const awardType = this.awardType; // 访问实例属性awardType
request.get('/findAllInstance/1/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
if(_this.total>=1){
_this.$message.success('你可将'+_this.awardType+'中奖券使用在下面的服务器上!');
}else {
_this.$message.error('先去购买服务器吧!')
}
})
},
}
</script>
四、后端
1、数据库设计
新增数据库
2、登录实现
大部分代码与之前权限部分的代码
唯一区别在与删除了权限目录简化开发过程,此外基本保持一致
a、使用用户密码登录成功
b、登录时数据写入本地成功
3、根据用户登录后自动补全左上角信息
<template>
<div>
<el-container>
<el-header>
云服务器抽奖系统
<el-dropdown style="width: 150px; cursor: pointer; text-align: right">
<div style="display: inline-block">
<img :src="userImage" alt=""
style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px">
<span>{{username}}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
</div>
<el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/prize" style="text-decoration: none">查看奖品</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/instance" style="text-decoration: none">虚拟机实例</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<span style="text-decoration: none" @click="logout">退出</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<div class="container">
<div v-for="box in boxes" :key="box.id">
<div
v-if="box.selected"
class="box box--selected"
>
{{ box.prize ? box.prizeContent : '未中奖' }}
</div>
<div
v-else
class="box"
@click="checkPrize(box)"
>
盲盒{{ box.id }}
</div>
</div>
</div>
</el-main>
<el-footer>rj201 zy</el-footer>
</el-container>
</div>
</template>
<script>
export default {
name: "RaffleLogin",
data() {
return {
username:'',
userImage:"https://daetz-image.oss-cn-hangzhou.aliyuncs.com/img/202306031111027.png",
boxes: [
{ id: 1, selected: false, prize: false, prizeContent: "奖品1:打折扣" },
{ id: 2, selected: false, prize: false, prizeContent: "奖品2:cpu升级" },
{ id: 3, selected: false, prize: false, prizeContent: "奖品3:内存升级" },
{ id: 4, selected: false, prize: false, prizeContent: "奖品4:增加时长" },
{ id: 5, selected: false, prize: false, prizeContent: "奖品5:送服务器" },
{ id: 6, selected: false, prize: false, prizeContent: "奖品6:配置升级" },
// 添加更多方框...
],
};
},
methods: {
checkPrize(box) {
// 模拟随机抽奖逻辑
if (box.selected) {
return; // 已经点击过的盒子不再处理点击事件
}
box.selected = true;
box.prize = Math.random() < 0.5; // 假设中奖概率为 50%
if (box.prize) {
this.$message.success(`恭喜你中奖了!${box.prizeContent}`);
} else {
this.$message.info("很遗憾,未中奖。");
}
},
logout() {
this.$store.commit("logout")
this.$message.success("退出成功")
}
},
created() {
const storedUser = localStorage.getItem('user');
const user = JSON.parse(storedUser);
console.log(user);
console.log(user.username)
this.username=user.username
}
};
</script>
<style scoped>
.el-header,
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-main {
background-color: #e9eef3;
color: #333;
text-align: center;
line-height: 160px;
}
.container {
display: flex;
flex-wrap: wrap;
}
.user-icon {
margin-left: auto;
}
.box {
width: 100px;
height: 100px;
margin: 10px;
background-color: gray;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.box--selected {
background-color: green;
cursor: not-allowed;
}
</style>
4、点击盲盒,显示中奖后将用户和奖品类型存入award表
/**
* @author daetz
* @creat 2023/6/3
**/
@RestController
public class AwardSaveOrUpdate {
@Resource
private AwardService awardService;
@PostMapping("/award")
public ResultDataDTO SaveAward(@RequestBody Award award){
Date currentTime = new Date();
award.setPriceTime(currentTime);
boolean save = awardService.saveOrUpdate(award);
return ResultDataDTO.success(save);
}
}
const data = {
name: this.username,
priceType: box.type,
description:box.prizeContent,
};
this.request.post('/award', data)
.then(response => {
// 处理成功响应
console.log(response.data);
})
.catch(error => {
// 处理错误
console.log(error);
});
实现成功
5、实现右上角点击事件,查看奖品
6、商品兑换数据传输分页查询
注意使用之前写过的分页查询,忽略了MybatisConfig
@Autowired
private AwardMapper awardMapper;
/**
* 在exchange查询中奖信息
* @param PageNum
* @param size
* @return
*/
@RequestMapping("/findAward/{PageNum}/{size}")
public ResultDataDTO findPage(@PathVariable("PageNum") Integer PageNum, @PathVariable("size") Integer size){
Page<Award> page =new Page<>(PageNum,size);
Page<Award> result = awardMapper.selectPage(page, null);
return ResultDataDTO.success(result);
}
7、处理使用中奖卷对服务的选择界面
1、使用分页查询返回用户的虚拟机列表
五、注意事项
1、路由的相对位置和绝对位置
path: 'exchange', // 在子路由的路径前不加斜杠,表示相对路径
2、注意数据库的类型统一
3、同路径刷新页面重复导航
2vue-router.esm.js:2046 Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/back/instance".
使用location.reload();即可
4、同时传入两个id用来判断价格是否需要改变
类似于下面,但是需要传入两个参数
created() {
const _this = this;
request
.get("/instance/findById/" + this.$route.query.instance_id)
.then(resp => {
_this.ruleForm = resp.data.data;
_this.initialData = { ...resp.data.data };
})
.catch(error => {
console.log(error);
});
}
分别是instance_id
和award_id
后端如何接收
5、空指针异常
忘记了先进行查询
之前使用saveorupdate没设置id
忘记了修改内容后会立即删除原来的记录,导致id为null
交换一下位置即可解决
还是不行
必须要等待上面的结束再删除
6、忘记设计主键自增
7、公网私网空值
写了两个一样的值
数据与数据库不一致
JDBC Connection [HikariProxyConnection@995076997 wrapping com.mysql.cj.jdbc.ConnectionImpl@39eeb7ad] will be managed by Spring
==> Preparing: INSERT INTO used_award ( award_id, instance_id, price_type, description, instance_public_ip, instance_private_ip, instance_name, used_time, receive_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 22(Integer), 23(Integer), duration(String), 奖品4:增加时长(一年)(String), 192.168.220.121(String), 192.168.220.121(String), 华北二区(String), 2023-06-05 21:46:51.835(Timestamp), 2023-06-04 00:00:00.0(Timestamp)
<== Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@101e8811]
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@101e8811]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@101e8811]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@101e8811]
<== Row: 1, 64, 23, upgrade, 奖品6:配置升级, null, 192.168.220.121, 华北二区, 2023-06-05 19:09:24, 2023-06-05 19:04:43
忘记保存数据库了
8、关闭程序后,Database需要重新连接
9、全局设置展示时间
参考链接:vue全局修改$message的显示时间
官方地址:https://element.eleme.cn/#/zh-CN/component/message#fang-fa
import Vue from 'vue'
import axios from "axios";
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import request from "@/utils/request";
import 'element-ui/lib/theme-chalk/index.css';
import './style/main.css';
Vue.config.productionTip = false
import { Message } from 'element-ui';
Vue.use(ElementUI);
Vue.prototype.$message = function(msg) {
return Message({
message: msg,
duration: 1000
});
};
// 分别对success、warning和error等样式进行设置
Vue.prototype.$message.success = function(msg) {
return Message.success({
message: msg,
duration: 1000
});
};
Vue.prototype.$message.info = function(msg) {
return Message.info({
message: msg,
duration: 1000
});
};
Vue.prototype.$message.error = function(msg) {
return Message.error({
message: msg,
duration: 1000
});
};
Vue.prototype.request=request
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
10、登录错误返回500
六、重点问题解决
1、ChooseInstance
1、前端
根据第三点的8-1-2以此传入两个表的id
使用switch根据类型判断下一步跳转的路由
<template>
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<!-- id主键自增 -->
<el-form-item label="id" prop="id">
<el-input v-model="ruleForm.id" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="公网IP" prop="instancePublicIp">
<el-input v-model="ruleForm.instancePublicIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="私网IP" prop="instancePrivateIp">
<el-input v-model="ruleForm.instancePrivateIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="实例名称" prop="instanceName">
<el-input v-model="ruleForm.instanceName" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="购买时长(月)" prop="instanceDurationTime">
<el-input v-model="ruleForm.instanceDurationTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="端口号" prop="instanceSecurityGroupPorts">
<el-input v-model="ruleForm.instanceSecurityGroupPorts" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="核数" prop="instanceUpgradeCpu">
<el-input v-model="ruleForm.instanceUpgradeCpu"></el-input>
</el-form-item>
<el-form-item label="内存(G)" prop="instanceUpgradeMemory">
<el-input v-model="ruleForm.instanceUpgradeMemory" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="磁盘(G)" prop="instanceUpgradeDisk">
<el-input v-model="ruleForm.instanceUpgradeDisk" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="计费模式" prop="instanceUpgradeBandwitdth">
<el-input v-model="ruleForm.instanceUpgradeBandwitdth" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-input v-model="ruleForm.createdTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">修改</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "CPUpgrade",
data() {
return {
ruleForm: {
id: "",
instancePublicIp: "",
instancePrivateIp: "",
instanceName: "",
instanceDurationTime: "",
instanceSecurityGroupPorts: "",
instanceUpgradeCpu: "",
instanceUpgradeMemory: "",
instanceUpgradeDisk: "",
instanceUpgradeBandwitdth: "",
createdTime: ""
},
rules: {
instanceUpgradeCpu: [
{
required: true,
message: "请输入核数",
trigger: "blur"
},
{
validator: this.checkUpgradeCpu,
trigger: "blur"
}
]
}
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate(valid => {
if (valid) {
const formData = {
id: this.ruleForm.id,
instanceUpgradeCpu: this.ruleForm.instanceUpgradeCpu
};
request
.post("/instance/saveOrUpdate", formData)
.then(resp => {
console.log(resp.data)
if (resp.data.code === "200") {
this.$message.success("用户修改成功");
request.post("/award/deleteById/"+this.$route.query.award_id).then(resp=>{
if (resp.data.code === "200") {
this.$message.success("奖券" +
this.$route.query.award_id+"使用成功");
this.$router.push({
path: 'exchange',});
}else{
this.$message.error("奖券使用失败");
}
})
} else {
this.$message.error("用户修改失败");
}
})
.catch(error => {
console.log(error);
});
} else {
console.log("Form validation failed");
}
});
},
resetForm(formName) {
this.ruleForm.instanceUpgradeCpu = null;
},
checkUpgradeCpu(rule, value, callback) {
const sum = parseInt(this.$route.query.sum);
const cpu = parseInt(value);
if (isNaN(cpu) || cpu <= sum) {
callback();
} else {
callback(new Error("核数不能超过" + sum));
}
}
},
created() {
const _this = this;
request
.get("/instance/findById/" + this.$route.query.instance_id)
.then(resp => {
_this.ruleForm = resp.data.data;
_this.initialData = { ...resp.data.data };
})
.catch(error => {
console.log(error);
});
}
};
</script>
<style scoped>
.el-form {
text-align: left;
}
</style>
2、CPUpgrade
1、前端
分别将两个表写入路径中,加上sum限制最大的范围
修改成功后返回exchange页面,并给出提示
<template>
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<!-- id主键自增 -->
<el-form-item label="id" prop="id">
<el-input v-model="ruleForm.id" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="公网IP" prop="instancePublicIp">
<el-input v-model="ruleForm.instancePublicIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="私网IP" prop="instancePrivateIp">
<el-input v-model="ruleForm.instancePrivateIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="实例名称" prop="instanceName">
<el-input v-model="ruleForm.instanceName" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="购买时长(月)" prop="instanceDurationTime">
<el-input v-model="ruleForm.instanceDurationTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="端口号" prop="instanceSecurityGroupPorts">
<el-input v-model="ruleForm.instanceSecurityGroupPorts" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="核数" prop="instanceUpgradeCpu">
<el-input v-model="ruleForm.instanceUpgradeCpu"></el-input>
</el-form-item>
<el-form-item label="内存(G)" prop="instanceUpgradeMemory">
<el-input v-model="ruleForm.instanceUpgradeMemory" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="磁盘(G)" prop="instanceUpgradeDisk">
<el-input v-model="ruleForm.instanceUpgradeDisk" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="计费模式" prop="instanceUpgradeBandwitdth">
<el-input v-model="ruleForm.instanceUpgradeBandwitdth" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-input v-model="ruleForm.createdTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">修改</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "CPUpgrade",
data() {
return {
ruleForm: {
id: "",
instancePublicIp: "",
instancePrivateIp: "",
instanceName: "",
instanceDurationTime: "",
instanceSecurityGroupPorts: "",
instanceUpgradeCpu: "",
instanceUpgradeMemory: "",
instanceUpgradeDisk: "",
instanceUpgradeBandwitdth: "",
createdTime: ""
},
rules: {
instanceUpgradeCpu: [
{
required: true,
message: "请输入核数",
trigger: "blur"
},
{
validator: this.checkUpgradeCpu,
trigger: "blur"
}
]
}
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate(valid => {
if (valid) {
const formData = {
id: this.ruleForm.id,
instanceUpgradeCpu: this.ruleForm.instanceUpgradeCpu
};
request
.post("/instance/saveOrUpdate", formData)
.then(resp => {
console.log(resp.data)
if (resp.data.code === "200") {
this.$message.success("用户修改成功");
request.post("/award/deleteById/"+this.$route.query.award_id).then(resp=>{
if (resp.data.code === "200") {
this.$message.success("奖券" +
this.$route.query.award_id+"使用成功");
this.$router.push({
path: 'exchange',});
}else{
this.$message.error("奖券使用失败");
}
})
} else {
this.$message.error("用户修改失败");
}
})
.catch(error => {
console.log(error);
});
} else {
console.log("Form validation failed");
}
});
},
resetForm(formName) {
this.ruleForm.instanceUpgradeCpu = null;
},
checkUpgradeCpu(rule, value, callback) {
const sum = parseInt(this.$route.query.sum);
const cpu = parseInt(value);
if (isNaN(cpu) || cpu <= sum) {
callback();
} else {
callback(new Error("核数不能超过" + sum));
}
}
},
created() {
const _this = this;
request
.get("/instance/findById/" + this.$route.query.instance_id)
.then(resp => {
_this.ruleForm = resp.data.data;
_this.initialData = { ...resp.data.data };
})
.catch(error => {
console.log(error);
});
}
};
</script>
<style scoped>
.el-form {
text-align: left;
}
</style>
2、后端
根据奖券内容修改
/**
* 根据奖券修改内容
* @param allInstance
* @return
* @throws Exception
*/
@PostMapping("/saveOrUpdate")
public ResultDataDTO saveALLInstance(@RequestBody AllInstance allInstance) throws Exception {
boolean result = allInstanceService.saveOrUpdate(allInstance);
return ResultDataDTO.success(result);
}
修改表信息成功后,删除奖券的id
package com.demo.controller;
import com.demo.DTO.ResultDataDTO;
import com.demo.service.AwardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author daetz
* @creat 2023/6/4
**/
@RestController
@RequestMapping("/award")
public class AwardController {
@Autowired
private AwardService awardService;
@RequestMapping("deleteById/{id}")
public ResultDataDTO deleteById(@PathVariable Integer id){
boolean result = awardService.removeById(id);
return ResultDataDTO.success(result);
}
}
3、IncreaseDuration
1、前端
与之前类似,不在进行赘述
<template>
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<!-- id主键自增 -->
<el-form-item label="id" prop="id">
<el-input v-model="ruleForm.id" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="公网IP" prop="instancePublicIp">
<el-input v-model="ruleForm.instancePublicIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="私网IP" prop="instancePrivateIp">
<el-input v-model="ruleForm.instancePrivateIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="实例名称" prop="instanceName">
<el-input v-model="ruleForm.instanceName" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="购买时长(月)" prop="instanceDurationTime">
<el-input v-model="ruleForm.instanceDurationTime"></el-input>
</el-form-item>
<el-form-item label="端口号" prop="instanceSecurityGroupPorts">
<el-input v-model="ruleForm.instanceSecurityGroupPorts" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="核数" prop="instanceUpgradeCpu">
<el-input v-model="ruleForm.instanceUpgradeCpu" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="内存(G)" prop="instanceUpgradeMemory">
<el-input v-model="ruleForm.instanceUpgradeMemory" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="磁盘(G)" prop="instanceUpgradeDisk">
<el-input v-model="ruleForm.instanceUpgradeDisk" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="计费模式" prop="instanceUpgradeBandwitdth">
<el-input v-model="ruleForm.instanceUpgradeBandwitdth" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-input v-model="ruleForm.createdTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">修改</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "IncreaseDuration",
data() {
return {
ruleForm: {
id: "",
instancePublicIp: "",
instancePrivateIp: "",
instanceName: "",
instanceDurationTime: "",
instanceSecurityGroupPorts: "",
instanceUpgradeCpu: "",
instanceUpgradeMemory: "",
instanceUpgradeDisk: "",
instanceUpgradeBandwitdth: "",
createdTime: ""
},
initialDuration: 0, // 存储初始时长
rules: {
instanceDurationTime: [
{
required: true,
message: "请输入扩增时间",
trigger: "blur"
},
{
validator: this.checkUpgradeDuration,
trigger: "blur"
}
]
}
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate(valid => {
if (valid) {
const formData = {
id: this.ruleForm.id,
instanceDurationTime: this.ruleForm.instanceDurationTime
};
request
.post("/instance/saveOrUpdate", formData)
.then(resp => {
console.log(resp.data)
if (resp.data.code === "200") {
this.$message.success("用户修改成功");
request.post("/award/deleteById/"+this.$route.query.award_id).then(resp=>{
if (resp.data.code === "200") {
this.$message.success("奖券" +
this.$route.query.award_id+"使用成功");
this.$router.push({
path: 'exchange',});
}else{
this.$message.error("奖券使用失败");
}
})
} else {
this.$message.error("用户修改失败");
}
})
.catch(error => {
console.log(error);
});
} else {
console.log("Form validation failed");
}
});
},
resetForm(formName) {
this.ruleForm.instanceDurationTime = null;
},
checkUpgradeDuration(rule, value, callback) {
const originalDuration = this.initialDuration;
const duration = parseInt(value);
const sum = parseInt(this.$route.query.sum);
if (isNaN(duration) || duration <= originalDuration + sum) {
callback();
} else {
callback(new Error("最长时间不能超过: " + (originalDuration + sum)));
}
}
},
created() {
const _this = this;
request
.get("/instance/findById/" + this.$route.query.instance_id)
.then(resp => {
_this.ruleForm = resp.data.data;
_this.initialData = { ...resp.data.data };
_this.initialDuration = parseInt(resp.data.data.instanceDurationTime);
})
.catch(error => {
console.log(error);
});
}
};
</script>
<style scoped>
.el-form {
text-align: left;
}
</style>
4、MemoryUpgrade
1、前端
<template>
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<!-- id主键自增 -->
<el-form-item label="id" prop="id">
<el-input v-model="ruleForm.id" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="公网IP" prop="instancePublicIp">
<el-input v-model="ruleForm.instancePublicIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="私网IP" prop="instancePrivateIp">
<el-input v-model="ruleForm.instancePrivateIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="实例名称" prop="instanceName">
<el-input v-model="ruleForm.instanceName" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="购买时长(月)" prop="instanceDurationTime">
<el-input v-model="ruleForm.instanceDurationTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="端口号" prop="instanceSecurityGroupPorts">
<el-input v-model="ruleForm.instanceSecurityGroupPorts" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="核数" prop="instanceUpgradeCpu">
<el-input v-model="ruleForm.instanceUpgradeCpu" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="内存(G)" prop="instanceUpgradeMemory">
<el-input v-model="ruleForm.instanceUpgradeMemory" ></el-input>
</el-form-item>
<el-form-item label="磁盘(G)" prop="instanceUpgradeDisk">
<el-input v-model="ruleForm.instanceUpgradeDisk" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="计费模式" prop="instanceUpgradeBandwitdth">
<el-input v-model="ruleForm.instanceUpgradeBandwitdth" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-input v-model="ruleForm.createdTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">修改</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "MemoryUpgrade",
data() {
return {
ruleForm: {
id: "",
instancePublicIp: "",
instancePrivateIp: "",
instanceName: "",
instanceDurationTime: "",
instanceSecurityGroupPorts: "",
instanceUpgradeCpu: "",
instanceUpgradeMemory: "",
instanceUpgradeDisk: "",
instanceUpgradeBandwitdth: "",
createdTime: ""
},
rules: {
instanceUpgradeMemory: [
{
required: true,
message: "请输入内存大小",
trigger: "blur"
},
{
validator: this.checkUpgradeMemory,
trigger: "blur"
}
]
}
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate(valid => {
if (valid) {
const formData = {
id: this.ruleForm.id,
instanceUpgradeMemory: this.ruleForm.instanceUpgradeMemory
};
request
.post("/instance/saveOrUpdate", formData)
.then(resp => {
console.log(resp.data)
if (resp.data.code === "200") {
this.$message.success("用户修改成功");
request.post("/award/deleteById/"+this.$route.query.award_id).then(resp=>{
if (resp.data.code === "200") {
this.$message.success("奖券" +
this.$route.query.award_id+"使用成功");
this.$router.push({
path: 'exchange',});
}else{
this.$message.error("奖券使用失败");
}
})
} else {
this.$message.error("用户修改失败");
}
})
.catch(error => {
console.log(error);
});
} else {
console.log("Form validation failed");
}
});
},
resetForm(formName) {
this.ruleForm.instanceUpgradeMemory = null;
},
checkUpgradeMemory(rule, value, callback) {
const sum = parseInt(this.$route.query.sum);
const memory = parseInt(value);
if (isNaN(memory) || memory <= sum) {
callback();
} else {
callback(new Error("内存不能超过" + sum));
}
}
},
created() {
const _this = this;
request
.get("/instance/findById/" + this.$route.query.instance_id)
.then(resp => {
_this.ruleForm = resp.data.data;
_this.initialData = { ...resp.data.data };
})
.catch(error => {
console.log(error);
});
}
};
</script>
<style scoped>
.el-form {
text-align: left;
}
</style>
5、ConfigurationUpgrade
1、前端
<template>
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<!-- id主键自增 -->
<el-form-item label="id" prop="id">
<el-input v-model="ruleForm.id" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="公网IP" prop="instancePublicIp">
<el-input v-model="ruleForm.instancePublicIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="私网IP" prop="instancePrivateIp">
<el-input v-model="ruleForm.instancePrivateIp" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="实例名称" prop="instanceName">
<el-input v-model="ruleForm.instanceName" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="购买时长(月)" prop="instanceDurationTime">
<el-input v-model="ruleForm.instanceDurationTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="端口号" prop="instanceSecurityGroupPorts">
<el-input v-model="ruleForm.instanceSecurityGroupPorts" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="核数" prop="instanceUpgradeCpu">
<el-input v-model="ruleForm.instanceUpgradeCpu" ></el-input>
</el-form-item>
<el-form-item label="内存(G)" prop="instanceUpgradeMemory">
<el-input v-model="ruleForm.instanceUpgradeMemory" ></el-input>
</el-form-item>
<el-form-item label="磁盘(G)" prop="instanceUpgradeDisk">
<el-input v-model="ruleForm.instanceUpgradeDisk" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="计费模式" prop="instanceUpgradeBandwitdth">
<el-input v-model="ruleForm.instanceUpgradeBandwitdth" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-input v-model="ruleForm.createdTime" :disabled="true"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">修改</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "ConfigurationUpgrade",
data() {
return {
ruleForm: {
id: "",
instancePublicIp: "",
instancePrivateIp: "",
instanceName: "",
instanceDurationTime: "",
instanceSecurityGroupPorts: "",
instanceUpgradeCpu: "",
instanceUpgradeMemory: "",
instanceUpgradeDisk: "",
instanceUpgradeBandwitdth: "",
createdTime: ""
},
rules: {
instanceUpgradeCpu: [
{
required: true,
message: "请输入核数",
trigger: "blur"
},
{
validator: this.checkUpgradeCpu,
trigger: "blur"
}
],
instanceUpgradeMemory: [
{
required: true,
message: "请输入内存大小",
trigger: "blur"
},
{
validator: this.checkUpgradeMemory,
trigger: "blur"
}
]
}
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate(valid => {
if (valid) {
const formData = {
id: this.ruleForm.id,
instanceUpgradeCpu: this.ruleForm.instanceUpgradeCpu,
instanceUpgradeMemory: this.ruleForm.instanceUpgradeMemory,
};
request
.post("/instance/saveOrUpdate", formData)
.then(resp => {
console.log(resp.data)
if (resp.data.code === "200") {
this.$message.success("用户修改成功");
request.post("/award/deleteById/"+this.$route.query.award_id).then(resp=>{
if (resp.data.code === "200") {
this.$message.success("奖券" +
this.$route.query.award_id+"使用成功");
this.$router.push({
path: 'exchange',});
}else{
this.$message.error("奖券使用失败");
}
})
} else {
this.$message.error("用户修改失败");
}
})
.catch(error => {
console.log(error);
});
} else {
console.log("Form validation failed");
}
});
},
resetForm(formName) {
this.ruleForm.instanceUpgradeMemory = null;
this.ruleForm.instanceUpgradeCpu = null;
},
checkUpgradeCpu(rule, value, callback) {
const sum = 32;
const cpu = parseInt(value);
if (isNaN(cpu) || cpu <= sum) {
callback();
} else {
callback(new Error("核数不能超过" + sum));
}
},
checkUpgradeMemory(rule, value, callback) {
const sum = 200;
const memory = parseInt(value);
if (isNaN(memory) || memory <= sum) {
callback();
} else {
callback(new Error("内存不能超过" + sum));
}
},
},
created() {
const _this = this;
request
.get("/instance/findById/" + this.$route.query.instance_id)
.then(resp => {
_this.ruleForm = resp.data.data;
_this.initialData = { ...resp.data.data };
})
.catch(error => {
console.log(error);
});
}
};
</script>
<style scoped>
.el-form {
text-align: left;
}
</style>
6、SendServer
获取服务器的列表,插入相同的配置
1、前端
7、/back/instance
用户可以删除虚拟机或者新增虚拟机
1、前端
<template>
<div>
<div class="demo-input-suffix">
<el-input
placeholder="按照日期查找"
suffix-icon="el-icon-date"
v-model="input1"
style="width: 150px;float: left;margin:5px" >
</el-input>
<el-input
placeholder="按照姓名查找"
prefix-icon="el-icon-search"
v-model="input2"
style="width: 150px;float: left;margin:5px">
</el-input>
<el-button style="width: 70px;float: left;margin:5px" @click="search">查询</el-button>
<el-button style="width: 70px;float: left;margin:5px" @click="resetForm">重置</el-button>
</div>
<div>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePublicIp"
label="公网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePrivateIp"
label="私网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceName"
label="实例名称"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceDurationTime"
label="购买时长(月)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceSecurityGroupPorts"
label="端口号"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="instanceUpgradeCpu"
label="核数"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceUpgradeMemory"
label="内存(G)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceUpgradeDisk"
label="磁盘(G)"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="instanceUpgradeBandwitdth"
label="计费模式"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="createdTime"
label="创建时间"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
style="flex-grow: 1;">
<template slot-scope="scope">
<el-button @click="addUser(scope.row)" type="text" size="small">新增</el-button>
<el-button type="text" size="small" @click="deleteUser(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name:'Instance',
data() {
return {
total:null,
tableData:null,
input1:'',
input2:''
}
},
methods: {
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/findAllInstance/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
})
},
deleteUser(row){
const _this=this
request.delete('/instance/delete/'+row.id).then(function (resp){
//console.log(resp)
alert("删除成功")
window.location.reload();
})
},
addUser(row){
this.$router.push({
path: '/addInstance',
query: {
id: row.id
}
})
},
// edit(row) {
// this.$router.push({
// path:'/update',
// query:{
// id:row.id
// }
// })
// }
},
created() { //alert 初始化操作
const _this=this
const awardType = this.awardType; // 访问实例属性awardType
request.get('/findAllInstance/1/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
if(_this.total>=1){
_this.$message.info('您拥有'+ _this.total+'台服务器');
}else {
_this.$message.info('还没有服务器,先去购买服务器吧!')
}
})
},
}
</script>
<template>
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<!-- id主键自增 -->
<!-- <el-form-item label="id" prop="id">-->
<!-- <el-input v-model="ruleForm.id" ></el-input>-->
<!-- </el-form-item>-->
<el-form-item label="公网IP" prop="instancePublicIp">
<el-input v-model="ruleForm.instancePublicIp" ></el-input>
</el-form-item>
<el-form-item label="私网IP" prop="instancePrivateIp">
<el-input v-model="ruleForm.instancePrivateIp" ></el-input>
</el-form-item>
<el-form-item label="实例名称" prop="instanceName">
<el-input v-model="ruleForm.instanceName" ></el-input>
</el-form-item>
<el-form-item label="购买时长(月)" prop="instanceDurationTime">
<el-input v-model="ruleForm.instanceDurationTime" ></el-input>
</el-form-item>
<el-form-item label="端口号" prop="instanceSecurityGroupPorts">
<el-input v-model="ruleForm.instanceSecurityGroupPorts" ></el-input>
</el-form-item>
<el-form-item label="核数" prop="instanceUpgradeCpu">
<el-input v-model="ruleForm.instanceUpgradeCpu" ></el-input>
</el-form-item>
<el-form-item label="内存(G)" prop="instanceUpgradeMemory">
<el-input v-model="ruleForm.instanceUpgradeMemory" ></el-input>
</el-form-item>
<el-form-item label="磁盘(G)" prop="instanceUpgradeDisk">
<el-input v-model="ruleForm.instanceUpgradeDisk"></el-input>
</el-form-item>
<el-form-item label="计费模式" prop="instanceUpgradeBandwitdth">
<el-input v-model="ruleForm.instanceUpgradeBandwitdth" ></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="createdTime">
<el-input v-model="ruleForm.createdTime" ></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">新增</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "AddInstance",
data() {
return {
ruleForm: {
id: "",
instancePublicIp: "",
instancePrivateIp: "",
instanceName: "",
instanceDurationTime: "",
instanceSecurityGroupPorts: "",
instanceUpgradeCpu: "",
instanceUpgradeMemory: "",
instanceUpgradeDisk: "",
instanceUpgradeBandwitdth: "",
createdTime: ""
},
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate(valid => {
if (valid) {
const formData = {
instanceUpgradeCpu: this.ruleForm.instanceUpgradeCpu,
instancePublicIp: this.ruleForm.instancePrivateIp,
instancePrivateIp: this.ruleForm.instancePrivateIp,
instanceName: this.ruleForm.instanceName,
instanceDurationTime: this.ruleForm.instanceDurationTime,
instanceSecurityGroupPorts: this.ruleForm.instanceSecurityGroupPorts,
instanceUpgradeMemory: this.ruleForm.instanceUpgradeMemory,
instanceUpgradeDisk: this.ruleForm.instanceUpgradeDisk,
instanceUpgradeBandwitdth: this.ruleForm.instanceUpgradeBandwitdth,
};
request
.post("/instance/saveOrUpdate", formData)
.then(resp => {
console.log(resp.data)
if (resp.data.code === "200") {
this.$message.success("新增服务器成功");
this.$router.push('/back/instance');
} else {
this.$message.error("用户修改失败");
}
})
.catch(error => {
console.log(error);
});
} else {
console.log("Form validation failed");
}
});
},
resetForm(formName) {
//写入置空代码
this.$refs[formName].resetFields();
},
},
created() {
const _this = this;
request
.get("/instance/findById/" + this.$route.query.id)
.then(resp => {
_this.ruleForm = resp.data.data;
//_this.initialData = { ...resp.data.data };
})
.catch(error => {
console.log(error);
});
}
};
</script>
<style scoped>
.el-form {
text-align: left;
}
</style>
新增和删除
deleteInstance(row) {
request.delete('/instance/deleteById/' + row.id).then((resp) => {
console.log(resp.data.code)
if (resp.data.code === "200") {
this.$message.success("删除服务器成功");
this.$router.push('/back/instance');
} else {
this.$message.error("服务器修改失败");
}
});
},
addUser(row){
this.$router.push({
path: '/addInstance',
query: {
id: row.id
}
})
},
},
2、后端
/**
* 删除选定的实例
* @param id
* @return
*/
@RequestMapping("deleteById/{id}")
public ResultDataDTO deleteById(@PathVariable Integer id){
boolean result = allInstanceService.removeById(id);
return ResultDataDTO.success(result);
}
七、新建used_award表
1、新建used_award
2、前端设计
<template>
<div>
<div>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="awardId"
label="奖券id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceId"
label="实例id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="description"
label="中奖描述"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceName"
label="实例名称"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="usedTime"
label="创建时间"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
style="flex-grow: 1;">
<template slot-scope="scope">
<el-button type="text" size="small" @click="deleteInstance(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name:'UsedAward',
data() {
return {
total:null,
tableData:null,
input1:'',
input2:''
}
},
methods: {
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/used/findUsedAward/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
})
},
deleteInstance(row) {
request.delete('/used/deleteById/' + row.id).then((resp) => {
console.log(resp.data.code)
if (resp.data.code === "200") {
this.$message.success("删除服务器成功");
//this.$router.replace('/back/instance');
location.reload();
} else {
this.$message.error("服务器修改失败");
}
});
},
},
created() { //alert 初始化操作
const _this=this
const awardType = this.awardType; // 访问实例属性awardType
request.get('/used/findUsedAward/1/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
if(_this.total>=1){
_this.$message.info('您拥有'+ _this.total+'条记录');
}else {
_this.$message.info('您还没有记录,先去使用奖券吧!')
}
})
},
}
</script>
3、后端设计
只涉及了查询和删除的功能
package com.demo.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.DTO.ResultDataDTO;
import com.demo.domain.UsedAward;
import com.demo.mapper.UsedAwardMapper;
import com.demo.service.impl.UsedAwardServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author daetz
* @creat 2023/6/5
**/
@RestController
@RequestMapping("/used")
public class UsedAwardController {
@Autowired
private UsedAwardServiceImpl usedAwardService;
@Autowired
private UsedAwardMapper usedAwardMapper;
/**
* 删除记录
* @param id
* @return
*/
@RequestMapping("deleteById/{id}")
public ResultDataDTO deleteById(@PathVariable Integer id){
boolean result = usedAwardService.removeById(id);
return ResultDataDTO.success(result);
}
/**
* 查询已使用的信息
* @param PageNum
* @param size
* @return
*/
@RequestMapping("/findUsedAward/{PageNum}/{size}")
public ResultDataDTO findPage(@PathVariable("PageNum") Integer PageNum, @PathVariable("size") Integer size){
Page<UsedAward> page =new Page<>(PageNum,size);
Page<UsedAward> result = usedAwardMapper.selectPage(page, null);
return ResultDataDTO.success(result);
}
}
八、新增price字段,计算价格
1、数据库设计
2、前端
微调,仅增加一个字段即可
<el-table-column
prop="price"
label="价格"
style="flex-grow: 1;">
</el-table-column>
3、后端
更新数据表
根据
/**
* 购买时长
*/
@TableField(value = "instance_duration_time")
private Integer instanceDurationTime;
/**
* CPU
*/
@TableField(value = "instance_upgrade_cpu")
private Integer instanceUpgradeCpu;
/**
* 内存
*/
@TableField(value = "instance_upgrade_memory")
private Integer instanceUpgradeMemory;
/**
* 磁盘
*/
@TableField(value = "instance_upgrade_disk")
private Integer instanceUpgradeDisk;
给出自动计算价格的公式
/**
* 虚拟机价格
*/
@TableField(value = "price")
private BigDecimal price;
/**
* 根据奖券修改内容
* @param allInstance
* @return
* @throws Exception
*/
@PostMapping("/saveOrUpdate")
public ResultDataDTO saveALLInstance(@RequestBody AllInstance allInstance) throws Exception {
Date currentTime = new Date();
allInstance.setCreatedTime(currentTime);
Integer instanceDurationTime = allInstance.getInstanceDurationTime();
Integer instanceUpgradeCpu = allInstance.getInstanceUpgradeCpu();
Integer instanceUpgradeMemory = allInstance.getInstanceUpgradeMemory();
Integer instanceUpgradeDisk = allInstance.getInstanceUpgradeDisk();
Integer price = instanceDurationTime * instanceUpgradeCpu + instanceUpgradeMemory + instanceUpgradeDisk;
BigDecimal convertedPrice = new BigDecimal(price);
allInstance.setPrice(convertedPrice);
boolean result = allInstanceService.saveOrUpdate(allInstance);
return ResultDataDTO.success(result);
}
九、新增订单表
1、数据库设计
2、前端
<template>
<div>
<template>
<el-button type="text" @click="calculateTotal">点击计算所有订单的金额</el-button>
</template>
<div>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="id"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePublicIp"
label="公网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instancePrivateIp"
label="私网IP"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed
prop="instanceName"
label="实例名称"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="price"
label="价格"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
prop="createdTime"
label="创建时间"
style="flex-grow: 1;">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
style="flex-grow: 1;">
<template slot-scope="scope">
<el-button type="text" size="small" @click="deleteInstance(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name:'Order',
data() {
return {
total:null,
tableData:null,
input1:'',
input2:''
}
},
methods: {
calculateTotal(){
let totalPrice = 0;
this.tableData.forEach(item => {
totalPrice += item.price;
});
this.$message({
type: 'info',
message: `总金额: ${totalPrice}`
});
},
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/findAllInstance/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
})
},
deleteInstance(row) {
request.delete('/instance/deleteById/' + row.id).then((resp) => {
console.log(resp.data.code)
if (resp.data.code === "200") {
this.$message.success("删除订单成功");
//this.$router.replace('/back/instance');
location.reload();
} else {
this.$message.error("服务器修改失败");
}
});
},
},
created() { //alert 初始化操作
const _this=this
const awardType = this.awardType; // 访问实例属性awardType
request.get('/findAllInstance/1/3').then(function (resp){
_this.tableData=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
if(_this.total>=1){
_this.$message.info('您拥有'+ _this.total+'条订单');
}else {
_this.$message.info('还没有订单,先去购买服务器吧!')
}
})
},
}
</script>
3、后端
调用instance的后端
十、新增中奖编码
根据用户的登录信息,获取用户名和密码
1、前端
username:'',
password:'',
const storedUser = localStorage.getItem('user');
const user = JSON.parse(storedUser);
//console.log(user);
//console.log(user.username)
this.username=user.username
this.password=user.password
将用户名和密码拼接起来
每次从左到右随机取两个或者三个数据,存入type中
<template>
<div>
<el-container>
<el-header>
云服务器抽奖系统
<el-dropdown style="width: 150px; cursor: pointer; text-align: right">
<div style="display: inline-block">
<img :src="userImage" alt=""
style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px">
<span>{{username}}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
</div>
<el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/exchange" style="text-decoration: none">查看奖品</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/instance" style="text-decoration: none">虚拟机实例</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<span style="text-decoration: none" @click="logout">退出</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<div class="container">
<div v-for="box in boxes" :key="box.id">
<div v-if="box.selected" class="box box--selected">
<div class="message-container">
{{ box.prize ? box.Content : '未中奖' }}
</div>
</div>
<div v-else class="box" @click="checkPrize(box)">
<div class="message-container">
盲盒{{ box.id }}
</div>
</div>
</div>
</div>
</el-main>
<el-footer>rj201 zy</el-footer>
</el-container>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "RaffleLogin",
data() {
return {
username:'',
password:'',
userImage:"https://daetz-image.oss-cn-hangzhou.aliyuncs.com/img/202306031111027.png",
boxes: [
{ id: 1, selected: false, prize: false,Content: "奖品1:打折扣", prizeContent: "奖品1:打折扣(6折)",type:'discount',variable:6},
{ id: 2, selected: false, prize: false,Content: "奖品2:升级cpu", prizeContent: "奖品2:cpu升级(32核)",type:'cpu',variable:32 },
{ id: 3, selected: false, prize: false,Content: "奖品3:升级内存", prizeContent: "奖品3:内存升级(64G)",type: 'memory',variable:64},
{ id: 4, selected: false, prize: false,Content: "奖品4:加赠时长", prizeContent: "奖品4:增加时长(20月)", type: 'duration',variable:20},
{ id: 5, selected: false, prize: false,Content: "奖品5:送服务器", prizeContent: "奖品5:送服务器",type: 'sever',variable:null },
{ id: 6, selected: false, prize: false,Content: "奖品6:配置升级", prizeContent: "奖品6:配置升级",type: 'upgrade',variable:null},
// 添加更多方框...
],
};
},
methods: {
checkPrize(box) {
// 模拟随机抽奖逻辑
if (box.selected) {
return; // 已经点击过的盒子不再处理点击事件
}
box.selected = true;
box.prize = Math.random() < 0.5; // 假设中奖概率为 50%
if (box.prize) {
this.$message.success(`恭喜你中奖了!${box.prizeContent}`);
const concatenatedData = this.username + this.password;
const randomSplit = this.randomSplitString(concatenatedData); // 随机划分字符串
const randomIdentity = randomSplit[Math.floor(Math.random() * randomSplit.length)]; // 随机选择一个划分结果
const data = {
name: this.username,
priceType: box.type,
description:box.prizeContent,
sum:box.variable,
identity:randomIdentity,
};
console.log(data)
this.request.post('/award', data)
.then(response => {
// 处理成功响应
console.log(response.data);
})
.catch(error => {
// 处理错误
console.log(error);
});
} else {
this.$message.info("很遗憾,未中奖。");
}
},
randomSplitString(str) {
const result = [];
let remaining = str;
while (remaining.length > 0) {
const splitLength = Math.floor(Math.random() * 2) + 2;
//Math.random()函数会返回一个 0 和 1 之间的浮点数
//Math.floor()函数会将一个浮点数向下取整为最接近的整数
result.push(remaining.slice(0, splitLength));
//remaining.slice(0, splitLength)表示对 这个字符串,
//从索引 0 开始,切割出长度为 的子字符串,并且返回这个子字符串;
remaining = remaining.slice(splitLength);
}
return result;
},
logout() {
this.$store.commit("logout")
this.$message.success("退出成功")
}
},
created() {
const storedUser = localStorage.getItem('user');
const user = JSON.parse(storedUser);
//console.log(user);
//console.log(user.username)
this.username=user.username
this.password=user.password
const concatenatedData = this.username + this.password;
}
};
</script>
<style scoped>
.el-header,
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-main {
background-color: #e9eef3;
color: #333;
text-align: center;
line-height: 160px;
}
.container {
display: flex;
flex-wrap: wrap;
}
.user-icon {
margin-left: auto;
}
.box {
width: 100px;
height: 100px;
margin: 10px;
background-color: gray;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.box--selected {
background-color: green;
cursor: not-allowed;
}
.message-container {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
word-wrap: break-word;
overflow-wrap: break-word;
}
</style>
2、数据库
award
表中新增字段identity
3、后端
新增字段
/**
* 在exchange查询中奖信息
* @param PageNum
* @param size
* @return
*/
@RequestMapping("/findAward/{PageNum}/{size}")
public ResultDataDTO findPage(@PathVariable("PageNum") Integer PageNum, @PathVariable("size") Integer size){
Page<Award> page =new Page<>(PageNum,size);
Page<Award> result = awardMapper.selectPage(page, null);
return ResultDataDTO.success(result);
}
4、identity字段为空
忘记删去之前的记录
十一、增加Redis
后端config
后端controller
@RequestMapping("findById/{id}")
public ResultDataDTO findById(@PathVariable Integer id){
// AllInstance result = allInstanceService.getById(id);
// return ResultDataDTO.success(result);
String cacheKey = "instance:" + id; // 设置缓存的键
// 从Redis缓存中尝试获取数据
AllInstance result = (AllInstance) redisTemplate.opsForValue().get(cacheKey);
if (result == null) {
// 如果缓存中不存在数据,则从数据库中获取数据
result = allInstanceService.getById(id);
if (result != null) {
// 将数据存储到Redis缓存中
redisTemplate.opsForValue().set(cacheKey, result);
}
}
return ResultDataDTO.success(result);
}
未将数据写入redis
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@22b27e9f] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@745903289 wrapping com.mysql.cj.jdbc.ConnectionImpl@23b07769] will not be managed by Spring
这个错误信息表明,你正在尝试使用Spring管理一个JDBC连接,但是这个连接没有被注册到Spring的事务管理中。
在Spring中,你需要将你的数据源(DataSource)或者JdbcTemplate等与Spring的事务管理进行关联,这样Spring才能自动管理这些资源的事务。
如果你使用的是Spring Boot,那么你可以在配置文件(如application.properties或application.yml)中设置数据源和事务管理的相关配置。
package com.demo.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.DTO.ResultDataDTO;
import com.demo.domain.AllInstance;
import com.demo.mapper.AllInstanceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author daetz
* @creat 2023/5/17
**/
@RestController
public class ContentShowByPage {
@Autowired
private AllInstanceMapper allInstanceMapper;
@Autowired
private RedisTemplate<String, String> redisTemplate; // 注入RedisTemplate
@RequestMapping("/findAllInstance/{pageNum}/{size}")
public ResultDataDTO findPage(@PathVariable("pageNum") Integer pageNum, @PathVariable("size") Integer size) {
// 设置当前页码和每页数量
Page<AllInstance> page = new Page<>(pageNum, size);
// 分页查询
Page<AllInstance> result = allInstanceMapper.selectPage(page, null);
// 将内容存储在Redis中
for (AllInstance instance : result.getRecords()) {
String key = String.valueOf(instance.getId());
String value = instance.getInstanceName();
redisTemplate.opsForValue().set(key, value);
}
return ResultDataDTO.success(result);
}
}
更多推荐
所有评论(0)