Springboot+Vue服务器盲盒活动

文章目录

一、项目要求

  • 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中策略
  • 对购买时长的升级
  • 送一台虚拟机

这五种自动生产或者指定生成

  • 一个月最多三次,充中不能再抽中
  • 虚拟机列表
  • 随机组合(五种)

image-20230603122717665

image-20230603125511194

命名规则类似阿里云服务器的命名

【下图是阿里云的命名】

image-20230607085221320

二、说明文档

1、用户抽奖主页/raffle

image-20230603102813694

image-20230603103238193

image-20230603105752811

image-20230603105816290

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

image-20230603120907715

1、商品兑换 Product exchange /exchange
2、中奖说明 Information /information
3、容器实例 Instance /instance
4、订单中心 Order/order
5、设置 Setting/setting

三、前端

1、用户主页

a、主体框架

使用elementUI控件

image-20230603102903260

<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、右上角用户展示
  • 查看奖品
  • 虚拟机实例
  • 退出

image-20230603113551603

2、后台根据奖品挑选内容

3、登录页面

image-20230603193938203

<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

image-20230604103321646

<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、绑定侧边栏的点击事件跳转功能

image-20230604105122898

使用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、商品兑换数据传输分页查询

image-20230604112435632

<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获取内容

image-20230604114844906

image-20230604115734208

<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、处理使用中奖卷对服务的选择界面

image-20230604145112392

<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、右侧的使用按钮的点击事件

image-20230604163942703

<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、数据库设计

新增数据库

image-20230603184841384

2、登录实现

大部分代码与之前权限部分的代码

唯一区别在与删除了权限目录简化开发过程,此外基本保持一致

image-20230603194936206

a、使用用户密码登录成功

image-20230603194903481

b、登录时数据写入本地成功

image-20230603195114982

3、根据用户登录后自动补全左上角信息

image-20230603200954339

<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);
		}
}

image-20230603212327067

 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);
            });

image-20230603212307676

实现成功

image-20230603212053450

5、实现右上角点击事件,查看奖品

image-20230603213459769

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',  // 在子路由的路径前不加斜杠,表示相对路径

image-20230604102142638

2、注意数据库的类型统一

image-20230604184419317

3、同路径刷新页面重复导航

2vue-router.esm.js:2046 Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/back/instance".

image-20230604213422464

使用location.reload();即可

image-20230604213817091

4、同时传入两个id用来判断价格是否需要改变

image-20230605142514925

类似于下面,但是需要传入两个参数

  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、空指针异常

image-20230605171113211

忘记了先进行查询

image-20230605174826406

之前使用saveorupdate没设置id

image-20230605175335367

image-20230605175341094

忘记了修改内容后会立即删除原来的记录,导致id为null

image-20230605185627760

image-20230605185741496

交换一下位置即可解决

image-20230605185939316

还是不行

image-20230605190239505

必须要等待上面的结束再删除

6、忘记设计主键自增

image-20230605190734112

7、公网私网空值

image-20230605212948692

写了两个一样的值

image-20230605213202950

数据与数据库不一致


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

image-20230605215156743

image-20230605215215982

忘记保存数据库了

8、关闭程序后,Database需要重新连接

image-20230607081410982

9、全局设置展示时间

参考链接:vue全局修改$message的显示时间

官方地址:https://element.eleme.cn/#/zh-CN/component/message#fang-fa

image-20230607083943423

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

image-20230607091408794

image-20230607091503083

六、重点问题解决

1、ChooseInstance

1、前端

根据第三点的8-1-2以此传入两个表的id

image-20230604170252279

使用switch根据类型判断下一步跳转的路由

image-20230604170510643

<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限制最大的范围

image-20230604170703892

image-20230604170839782

修改成功后返回exchange页面,并给出提示

image-20230604170941757

<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、前端

image-20230604185037611

7、/back/instance

用户可以删除虚拟机或者新增虚拟机

1、前端

image-20230604210420798

<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

image-20230605134442468

2、前端设计

image-20230605140901107

<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、数据库设计

image-20230605141545401

2、前端

微调,仅增加一个字段即可

            <el-table-column
                    prop="price"
                    label="价格"
                    style="flex-grow: 1;">
            </el-table-column>

image-20230605155405824

image-20230605155331914

3、后端

更新数据表

image-20230605142005874

根据

    /**
     * 购买时长
     */
    @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、数据库设计

image-20230605215829459

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>

image-20230605223247090

3、后端

调用instance的后端

十、新增中奖编码

根据用户的登录信息,获取用户名和密码

1、前端

image-20230606094157534

      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>

image-20230606103914302

image-20230606104252247

2、数据库

award表中新增字段identity

image-20230606104628988

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字段为空

image-20230606110400860

忘记删去之前的记录

十一、增加Redis

后端config

image-20230610163546264

后端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);
		}
}

image-20230610171718556

image-20230610171601016

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值