(N-128)基于springboot,vue酒店管理系统

news2024/11/18 9:30:02

开发工具:IDEA

服务器:Tomcat9.0, jdk1.8

项目构建:maven

数据库:mysql5.7

系统分前后台,项目采用前后端分离

前端技术:vue+elementUI

服务端技术:springboot+mybatis

本系统功能包括: 

一、前台功能: 

1、用户注册模块:用户可以输入用户名、密码、昵称、姓名、手机来 进行注册。

2、用户登录模块:用户可以根据用户名、密码进行登录。

3、前台首页模块:包括广告、房间信息、酒店新闻。

4、酒店新闻模块:展示酒店标题,创建时间,详情。

5、酒店预订模块:展示了客房的详情以及评价,用户输入入住日期以及入住天数进行预订。

6、用户信息模块:展示了用户的头像、昵称、姓名、手机号码、性别并可进行修改。

7、个人订单模块:展示了全部订单、待付款订单、待入住、已入住,已退房的客房信息。

二、后台功能: 

1、管理员登录模块:管理员可以根据用户名、密码进行登录。

2、统计分析模块:管理员可以直观的查看近一周的客房数量、订单数量、用户数量。

3、会员管理模块:管理员可以查看用户的基本信息。

4、广告管理模块:管理员可以对酒店广告进行新增修改删除。

5、分类管理模块:管理员可以对客房的分类进行新增修改删除。

6、客房管理模块: 管理员可以对客房信息行增删改查。

7、房间管理模块:管理员可以查看目前所有房间的状态并对其进行增删改查。

8、订单管理模块:管理员可以找到用户提交的预订信息并进行开房和退房、查看的操作。

9、评价管理模块:管理员可以对用户的评价进行查询删除。

10、新闻管理模块:管理员可以对用户端新闻进行增删改查。

11、管理员管理模块:管理员可以对管理员的账号行增删改查。

文档截图: 

前台截图: 

后台截图:

package com.wfuhui.modules.order.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.wfuhui.common.utils.DateUtils;
import com.wfuhui.common.utils.Query;
import com.wfuhui.common.utils.R;
import com.wfuhui.modules.room.service.HouseService;
import com.wfuhui.modules.member.service.MemberService;
import com.wfuhui.modules.order.entity.OrderEntity;
import com.wfuhui.modules.order.service.OrderService;


/**
 * 订单
 * 

 */
@RestController
@RequestMapping("/order")
public class OrderController {
	@Autowired
	private OrderService orderService;
	@Autowired
	private HouseService roomService;
	@Autowired
	private MemberService memberService;
	
	/**
	 * 列表
	 */
	@RequestMapping("/list")
	public R list(@RequestParam Map<String, Object> params){
		//查询列表数据
        Query query = new Query(params);

		List<OrderEntity> orderList = orderService.queryList(query);
		int total = orderService.queryTotal(query);
		
		return R.ok().put("rows", orderList).put("total", total);
	}
	
	
	/**
	 * 信息
	 */
	@RequestMapping("/info/{id}")
	public R info(@PathVariable("id") Integer id){
		OrderEntity order = orderService.queryObject(id);
		return R.ok().put("order", order);
	}
	
	/**
	 * 保存
	 */
	@RequestMapping("/save")
	public R save(@RequestBody OrderEntity order){
		orderService.save(order);
		return R.ok();
	}
	
	/**
	 * 修改
	 */
	@RequestMapping("/update")
	public R update(@RequestBody OrderEntity order){
		orderService.update(order);
		
		return R.ok();
	}
	
	/**
	 * 删除
	 */
	@RequestMapping("/delete")
	public R delete(@RequestBody Integer[] ids){
		orderService.deleteBatch(ids);
		
		return R.ok();
	}
	
	/**
	 * 预订房间
	 * @param orderId
	 * @param roomNumber
	 * @return
	 */
	@RequestMapping("/orderRoom/{id}")
	public R orderRoom(@PathVariable("id")Integer id, String roomNumber) {
		OrderEntity order = new OrderEntity();
		order.setId(id);
		order.setOrderStatus(3);
		order.setRoomNumber(roomNumber);
		orderService.orderRoom(order);
		return R.ok();
	}
	
	/**
	 * 退房
	 * @param orderId
	 * @param roomNumber
	 * @return
	 */
	@RequestMapping("/returnRoom/{id}")
	public R returnRoom(@PathVariable("id")Integer id) {
		OrderEntity order = new OrderEntity();
		order.setId(id);
		order.setOrderStatus(4);
		orderService.returnRoom(order);
		//减少已售
		orderService.delHouseVolume(order.getId());
		return R.ok();
	}
	
}
<template>
    <div>
        <el-container>
            <el-header><mainHeader></mainHeader>
            </el-header>
            <el-container>
                <mainSidebar :active="active"></mainSidebar>
                <el-main>
                     <div v-if="showList">
                    <el-form :inline="true" :model="q" class="demo-form-inline">
                        <el-form-item label="客房名称">
                            <el-input v-model="q.houseName" placeholder="客房名称"></el-input>
                        </el-form-item>
                        <el-form-item>
                            <el-button type="primary" @click="query">查询</el-button>
                            <el-button type="success" @click="add">新增</el-button>
                            <el-button type="warning" @click="update">修改</el-button>
                            <el-button type="danger" @click="del">删除</el-button>
                        </el-form-item>
                    </el-form>
                        <el-table
                        :data="houseList"
                        style="width: 100%"
                        @selection-change="handleSelectionChange">
                        <el-table-column
                          type="selection"
                          width="55">
                        </el-table-column>
                        <el-table-column
                            prop="picUrl"
                            label="图片"
                            >
                            <template slot-scope="scope">
                                <el-image
                                    style="width: 100px; height: 80px"
                                    :src="scope.row.picUrl"></el-image>
                            </template>
                        </el-table-column>
                        <el-table-column
                            prop="houseName"
                            label="客房名称"
                            >
                        </el-table-column>
                        <el-table-column
                            prop="category.categoryName"
                            label="分类">
                        </el-table-column>
                        <el-table-column
                            prop="price"
                            label="价格">
                        </el-table-column>
                        <el-table-column
                            prop="stock"
                            label="房间数量">
                        </el-table-column>
                        <el-table-column
                            prop="createTime"
                            label="创建时间">
                        </el-table-column>
                        </el-table>
                        <el-pagination
                            @size-change="handleSizeChange"
                            @current-change="handleCurrentChange"
                            :current-page="q.page"
                            :page-sizes="[10, 50, 100]"
                            :page-size="q.limit"
                            layout="total, sizes, prev, pager, next, jumper"
                            :total="total">
                        </el-pagination>
                     </div>
                        <div v-if="!showList">
                        <el-form :model="house" label-width="120px">
                            <el-form-item label="图片">
                                <el-upload
                                class="avatar-uploader"
                                action="http://127.0.0.1:10001/api/fileupload/upload"
                                list-type="picture-card"
                                multiple
                                :file-list="fileList"
                                :on-success="handleAvatarSuccess"
                                :on-remove="imgRemove"
                                :before-upload="beforeAvatarUpload">
                                <i class="el-icon-plus avatar-uploader-icon"></i>
                                </el-upload>

                            </el-form-item>
                        <el-form-item label="客房名称">
                            <el-input v-model="house.houseName"></el-input>
                        </el-form-item>
                        <el-form-item label="分类">
                            <el-select v-model="house.categoryId" placeholder="请选择">
                                <el-option
                                v-for="item in categoryList"
                                :key="item.id"
                                :label="item.categoryName"
                                :value="item.id">
                                </el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="价格">
                            <el-input v-model="house.price"></el-input>
                        </el-form-item>
                        <el-form-item label="房间数量">
                            <el-input v-model="house.stock"></el-input>
                        </el-form-item>
                        <el-form-item label="详情">
                            <quill-editor ref="text" v-model="house.describe" :options="editorOption" style="height: 300px; margin-bottom: 50px;" />
                        </el-form-item>
                        <el-form-item>
                            <el-button type="primary" @click="onSubmit">保存</el-button>
                            <el-button @click="cancel">取消</el-button>
                        </el-form-item>
                        </el-form>
                    </div>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>
<script>
import { quillEditor } from 'vue-quill-editor'
import {quillRedefine} from 'vue-quill-editor-upload'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.bubble.css'
import 'quill/dist/quill.snow.css'
import mainHeader from '../../../components/admin-main-header'
import mainSidebar from '../../../components/admin-main-sidebar'
export default {
  name: "House",
  data() {
    return {
      total: 0,
      houseList: [],
      categoryList: [],
      q: {
        houseName: '',
        page: this.currentPage,
        limit: this.pageSize
      },
      asideStyle: {
        height: '500px'
      },
      house: {
          picUrl: ''
      },
      active: '5',
      showList: true,
      editorOption: {},
      fileList: [],
      ids: []
    };
  },
  components: {
    quillEditor,
    quillRedefine,
    mainHeader,
    mainSidebar
  },
  methods:{
      handleSizeChange(e){
          //console.log(e)
          this.q.limit = e;
          this.query();
      },
      handleCurrentChange(e){
          //console.log(e)
          this.q.page = e;
          this.query();
      },
      query(){
        var that = this;
        this.$axios.get(this.domain + '/house/list',
        { headers:{ token: localStorage.getItem("atoken") },
          params: that.q
        }).then(function(res){
            if(res.data.code == 0){//成功
              that.houseList = res.data.rows
              that.total = res.data.total
            }else{

            }
        })
      },
      queryCategory(){
        var that = this;
        this.$axios.get(this.domain + '/category/listAll',
        {
            headers:{ token: localStorage.getItem("atoken") }
        }).then(function(res){
            if(res.data.code == 0){//成功
              that.categoryList = res.data.categoryList
            }else{

            }
        })
      },
      queryHouse(id){
        var that = this;
        this.$axios.get(this.domain + '/house/info/'+id,
        {
            headers:{ token: localStorage.getItem("atoken") }
        }).then(function(res){
            if(res.data.code == 0){//成功
              that.house = res.data.house
              that.initImage(res.data.house.picUrls)
            }else{

            }
        })
      },
      initImage(picUrls){
        this.fileList=[];
        let urlList = picUrls.map(function(item, index){
          return {url: picUrls[index]}
        });
        for (let url in urlList){
          this.fileList.push(urlList[url]);
        }
      },
      onSubmit(e){
        var that = this;
        var data = this.house;
        data.picUrls = this.fileList.map(function(item, index){
            return item.url
        })
        data.picUrl = data.picUrls[0]
        var action = data.id == null ? "save" : "update";
        this.$axios.post(this.domain + '/house/'+action,
            data,
            {
                headers: {'token': localStorage.getItem("atoken")}
            }
        ).then(function(res){
            //console.log(res)
            if(res.data.code == 0){//成功
              that.showList = true;
              that.query();
            }else{
              that.errorMsg = res.data.msg;
              that.$message.error(res.data.msg);
            }
        })
      },
      add(){
          this.showList = false
          this.fileList = []
          this.house = {
              picUrls: []
          }
      },
      cancel(){
          this.showList = true
      },
      update(){
        if(this.ids.length != 1){
            this.$message.info("请选择一条数据");
            return;
        }
        this.showList = false;
        this.queryHouse(this.ids[0]);
      },
      del(){
        if(this.ids.length == 0){
            this.$message.info("请选择数据");
            return;
        }
        var that = this;
        this.$axios.post(this.domain + '/house/delete',
            that.ids, {
            headers: {'token': localStorage.getItem("atoken")}
        }).then(function(res){
            //console.log(res)
            if(res.data.code == 0){//成功
              that.query();
            }else{
              that.errorMsg = res.data.msg;
              that.$message.error(res.data.msg);
            }
        })
      },
      handleAvatarSuccess(e){
          this.fileList.push({
              url: e.url
          });
      },
      imgRemove(file, fileList){
          this.fileList = fileList;
      },
      beforeAvatarUpload(e){

      },
      handleSelectionChange(e){
        var ids = [];
        for(var i = 0; i < e.length; i++){
            ids.push(e[i].id)
        }
        this.ids = ids;
      }
  },
  created(){
    var docHeight = document.documentElement.clientHeight;
    this.asideStyle.height = docHeight - 76 + "px";
    var user = localStorage.getItem("auser");
    if(user){
        this.user = JSON.parse(user);
    }else{
        this.$router.push("admin_login");
    }
    this.query();
    this.queryCategory();
    this.editorOption = quillRedefine(
    {
        // 图片上传的设置
        uploadConfig: {
        action: this.domain + '/api/fileupload/upload',  // 必填参数 图片上传地址
        size: 500,  // 可选参数   图片限制大小,单位为Kb, 1M = 1024Kb
        accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon',  // 可选参数 可上传的图片格式
        // 必选参数  res是一个函数,函数接收的response为上传成功时服务器返回的数据
        // 你必须把返回的数据中所包含的图片地址 return 回去
        res: (respnse) => {
            return respnse.url
        },
        name: 'file'  // 图片上传参数名
        }
    }
    )
    //console.log(this.editorOption)

  }
};
</script>

<style scoped>

</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1115480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

推荐《机动战士高达SEED DESTINY》

《机动战士高达SEED DESTINY》是《机动战士高达SEED》的续集&#xff0c;于日本时间2004年10月9日—2005年10月1日每周六下午六点在每日放送、TBS电视台系列电视台播出&#xff0c;全50话。 [1] 台湾版权由博英社取得&#xff0c;并于2005年10月8日起由中国电视公司在每周六播…

光伏三相并网逆变器的控制策略与性能分析(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【c语言】atoi的模拟实现

1.头文件 atoi() 是 C语言的一个标准库函数&#xff0c;定义在<stdlib.h>头文件中 2.atoi的解析 具体来讲&#xff0c;atoi() 函数首先会丢弃尽可能多的空白字符&#xff0c;直至找到第一个非空白字符&#xff0c;然后从该字符开始&#xff0c;识别 “”、“-” 以及 …

Python---循环---while循环

Python中的循环 包括 while循环与for循环&#xff0c;本文以while循环为主。 Python中所有的知识点&#xff0c;都是为了解决某个问题诞生的&#xff0c;就好比中文的汉字&#xff0c;每个汉字都是为了解决某种意思表达而诞生的。 1、什么是循环 现实生活中&#xff0c;也有…

华硕ROG吹雪和微星刀锋钛两者如何选择

## 华硕Rog系列主板里面的吹雪和微星主板里面的刀锋钛两者相比分别有什么特点&#xff0c;二选一应该选择哪个&#xff1f; 首先&#xff0c;要明确"吹雪"和"刀锋钛"并不是主板本身的名称&#xff0c;而是主板系列或某种设计风格的称呼。华硕和微星都是非常…

隐式类型转换

什么是隐式类型转换&#xff0c;多参数的造函数隐式类型转换&#xff0c;和单参数的构造函数隐式类型转换有什么区别 C中有三种主要的隐式类型转换&#xff1a; 1:多参数的构造函数隐式类型转换 2:单参数的构造函数隐式类型转换 3:成员函数隐式类型转换。…

【KingHistorian】新授权配置与使用说明

哈喽&#xff0c;大家好&#xff0c;我是雷工。 今天在现场安装KingHistorian的授权时&#xff0c;一时想不起来上次咋安装的了&#xff0c;真是好记性不如烂笔头&#xff0c;更何况记性还不咋地&#xff0c;又琢磨了半小时才想起来&#xff0c;现将授权配置与使用说明整理如下…

idea leetcode配置

idea leetcode配置 配置页面如下图所示&#xff0c;根据需要&#xff0c;填入登录用户名、密码、文件存放路径&#xff0c;注意如果要使用自定义的代码结构配置&#xff0c;要勾选图中框出来的选项。 Code FileName&#xff1a; $!velocityTool.camelCaseName(${question.tit…

零基础新手也能会的H5邀请函制作教程

随着科技的的发展&#xff0c;H5邀请函已经成为了各种活动、婚礼、会议等场合的常见邀约方式。它们不仅可以提供动态、互动的体验&#xff0c;还能让邀请内容更加丰富多彩。下面&#xff0c;我们将通过乔拓云平台&#xff0c;带领大家一步步完成H5邀请函的制作。 1. 选择可靠的…

H3C交换机 万兆光模块可以插在千兆光口上使用吗?

环境&#xff1a; S6520X-24ST-SI交换机 H3C LSWM1QSTK2万兆40G堆叠线QSFP 问题描述&#xff1a; H3C交换机 万兆光模块可以插在千兆光口上使用吗&#xff1f; 答案&#xff1a; H3C交换机的万兆光模块&#xff08;10 Gigabit Ethernet Module&#xff09;通常使用的是SFP…

基于主动移频法与AFD孤岛检测的单相并网逆变器仿真(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

光储并网直流微电网simulink仿真模型,光伏采用mppt实现最大功率输出研究

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

来看看 Discourse 3.2.0.beta2 版本添加的新功能

3.2.0.beta2 版本是在 2023-10-16 发布的&#xff0c;根据官方的说法&#xff0c;主要添加了 3 个新功能。 官方的发布日志页面&#xff1a;3.2.0.beta2: Auto delete unused tags, custom date range for reports, new chat notifications, and more - announcements - Disco…

专题:链表常考题目汇总

文章目录 反转类型&#xff1a;206.反转链表完整版二刷记录 25. K个一组反转链表1 &#xff1a;子链表左闭右闭反转版本2 &#xff1a; 子链表左闭右开反转版本&#xff08;推荐&#xff09;⭐反转链表左闭右闭和左闭右开 合并类型&#xff1a;21.合并两个有序链表1: 递归法2: …

解决方法:从客户端(---<A href=“http://l...“)中检测到有潜在危险的 Request.Form 值。

从客户端(-----<A href"http://l...")中检测到有潜在危险的 Request.Form 值。 解决方法&#xff1a;应该是不同的.net Framework版本对代码的校验不同&#xff0c;造成在高版本操作系统&#xff08;即高.net Framework版本校验&#xff09;不兼容&#xff0c;可…

YOLO目标检测——红白细胞血小板数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;红白细胞血小板计数和分类数据集说明&#xff1a;YOLO目标检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富。使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xml)、coco(json)和yolo(txt)三种格式标签&…

【试题032】C语言关系运算符例题

1.题目&#xff1a;设int a2,b4,c5;&#xff0c;则表达式ab!c>b>a的值为&#xff1f; 2.代码分析&#xff1a; //设int a2,b4,c5;&#xff0c;则表达式ab!c>b>a的值为?int a 2, b 4, c 5;printf("%d\n", (a b ! c > b > a));//分析&#xff…

Python合并同类别且相交的矩形框

Python合并同类别且相交的矩形框 前言前提条件相关介绍实验环境Python合并同类别且相交的矩形框代码实现 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容&#xff0c;可点击进入Python日常小操作专栏、YOLO系列专栏、自然语言处理专栏或…

攻防世界web篇-disabled_button

一个不能按的按钮&#xff0c;试过点击&#xff0c;确实是点不了&#xff0c;所以只能查看源代码喽 经过仔细查看&#xff0c;发现这里多了disabled&#xff0c;这个参数在linux中是禁止的意思&#xff0c;大概是这个意思吧&#xff0c;毕竟开机不自启就用这个参数 在控制台这…

REACH 附录XVII发布关于微塑料限制管控要求是什么?如何办理?

REACH 附录XVII发布关于微塑料限制管控要求 2023年9月27日&#xff0c;欧盟官方公报(0JEU)发布了法规(EU)2023/2055&#xff0c;在REACH法规附件XVII中增加了第78条对微塑料的新限制要求。 新的限制将从2023年10月17日起生效&#xff0c;部分物品的过渡期将从4年延长到12年。…