用spring boot + vue生成一个点餐系统
时间: 2023-12-02 11:06:19 浏览: 57
好的,下面是一个简单的点餐系统的搭建步骤:
1. 创建Spring Boot项目
首先我们需要创建一个Spring Boot项目,可以使用Spring官方提供的[Spring Initializr](https://start.spring.io/)来生成项目模板,选择Web、JPA、MySQL等依赖。
2. 创建数据库表
我们需要在MySQL数据库中创建两个表,一个是菜品表,一个是订单表。具体表结构如下:
```sql
-- 菜品表
CREATE TABLE `dish` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`price` double NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
-- 订单表
CREATE TABLE `order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`total_price` double NOT NULL,
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
-- 订单项表
CREATE TABLE `order_item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`dish_id` int(11) NOT NULL,
`quantity` int(11) NOT NULL,
`price` double NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_order_id` (`order_id`),
KEY `fk_dish_id` (`dish_id`),
CONSTRAINT `fk_dish_id` FOREIGN KEY (`dish_id`) REFERENCES `dish` (`id`),
CONSTRAINT `fk_order_id` FOREIGN KEY (`order_id`) REFERENCES `order` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
```
3. 创建后端API
我们需要创建一些后端API,用于菜品的CRUD和订单的创建。具体实现可以参考下面的代码:
```java
@RestController
@RequestMapping("/api/dish")
public class DishController {
@Autowired
private DishRepository dishRepository;
@GetMapping
public List<Dish> list() {
return dishRepository.findAll();
}
@PostMapping
public Dish create(@RequestBody Dish dish) {
return dishRepository.save(dish);
}
@PutMapping("/{id}")
public Dish update(@PathVariable Long id, @RequestBody Dish dish) {
dish.setId(id);
return dishRepository.save(dish);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
dishRepository.deleteById(id);
}
}
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Autowired
private DishRepository dishRepository;
@Autowired
private OrderRepository orderRepository;
@Autowired
private OrderItemRepository orderItemRepository;
@PostMapping
public Order create(@RequestBody List<OrderItem> orderItems) {
double totalPrice = orderItems.stream().mapToDouble(item -> item.getPrice() * item.getQuantity()).sum();
Order order = new Order(totalPrice, LocalDateTime.now());
order = orderRepository.save(order);
for (OrderItem orderItem : orderItems) {
orderItem.setOrder(order);
orderItemRepository.save(orderItem);
}
return order;
}
}
```
其中,`DishRepository`、`OrderRepository`和`OrderItemRepository`是用于操作数据库的JPA接口。
4. 创建前端页面
我们可以使用Vue来实现前端页面,首先创建一个Vue项目,然后在`src/components`目录下创建一个`DishList.vue`组件和一个`OrderCart.vue`组件。
`DishList.vue`组件用于显示菜品列表和添加菜品到购物车,具体实现可以参考下面的代码:
```vue
<template>
<div class="dish-list">
<div class="dish" v-for="dish in dishes" :key="dish.id">
<div class="name">{{ dish.name }}</div>
<div class="price">¥{{ dish.price }}</div>
<button @click="addItem(dish)">加入购物车</button>
</div>
</div>
</template>
<script>
export default {
props: {
dishes: {
type: Array,
required: true
}
},
methods: {
addItem(dish) {
this.$emit('add-item', dish)
}
}
}
</script>
```
`OrderCart.vue`组件用于显示购物车里的菜品和提交订单,具体实现可以参考下面的代码:
```vue
<template>
<div class="order-cart">
<div class="item" v-for="(item, index) in items" :key="index">
<div class="name">{{ item.dish.name }}</div>
<div class="quantity">× {{ item.quantity }}</div>
<div class="price">¥{{ item.price }}</div>
<button @click="removeItem(index)">删除</button>
</div>
<div class="total-price">总价:¥{{ totalPrice }}</div>
<button @click="submitOrder">提交订单</button>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
required: true
},
totalPrice: {
type: Number,
required: true
}
},
methods: {
removeItem(index) {
this.$emit('remove-item', index)
},
submitOrder() {
this.$emit('submit-order')
}
}
}
</script>
```
最后,在主页面中引入这两个组件,并添加必要的样式即可:
```vue
<template>
<div class="app">
<div class="header">点餐系统</div>
<div class="main">
<div class="dish-list-wrapper">
<div class="title">菜品列表</div>
<DishList :dishes="dishes" @add-item="addItem"></DishList>
</div>
<div class="order-cart-wrapper">
<div class="title">订单</div>
<OrderCart :items="items" :totalPrice="totalPrice" @remove-item="removeItem" @submit-order="submitOrder"></OrderCart>
</div>
</div>
</div>
</template>
<script>
import DishList from '@/components/DishList.vue'
import OrderCart from '@/components/OrderCart.vue'
export default {
components: {
DishList,
OrderCart
},
data() {
return {
dishes: [],
items: [],
totalPrice: 0
}
},
mounted() {
this.loadDishes()
},
methods: {
loadDishes() {
// 调用后端API获取菜品列表
axios.get('/api/dish').then(response => {
this.dishes = response.data
})
},
addItem(dish) {
let item = this.items.find(item => item.dish.id === dish.id)
if (item) {
item.quantity++
item.price += dish.price
} else {
item = {
dish: dish,
quantity: 1,
price: dish.price
}
this.items.push(item)
}
this.totalPrice += dish.price
},
removeItem(index) {
let item = this.items[index]
this.items.splice(index, 1)
this.totalPrice -= item.price
},
submitOrder() {
let orderItems = this.items.map(item => {
return {
dishId: item.dish.id,
quantity: item.quantity,
price: item.price
}
})
// 调用后端API提交订单
axios.post('/api/order', orderItems).then(response => {
alert('订单提交成功!')
this.items = []
this.totalPrice = 0
})
}
}
}
</script>
<style scoped>
.app {
display: flex;
flex-direction: column;
height: 100%;
}
.header {
height: 50px;
line-height: 50px;
text-align: center;
font-size: 24px;
font-weight: bold;
}
.main {
display: flex;
flex: 1;
padding: 20px;
}
.dish-list-wrapper {
flex: 1;
margin-right: 20px;
}
.order-cart-wrapper {
width: 300px;
}
.title {
font-size: 20px;
font-weight: bold;
margin-bottom: 10px;
}
.dish {
display: flex;
align-items: center;
height: 50px;
padding: 0 20px;
border-bottom: 1px solid #ccc;
}
.name {
flex: 1;
}
.price {
margin-left: 20px;
}
.order-cart {
border: 1px solid #ccc;
border-radius: 5px;
padding: 20px;
}
.item {
display: flex;
align-items: center;
height: 50px;
padding: 0 20px;
border-bottom: 1px solid #ccc;
}
.quantity {
margin-left: 20px;
}
.price {
margin-left: 20px;
}
.total-price {
font-size: 20px;
font-weight: bold;
margin-top: 10px;
}
</style>
```
完成以上步骤后,我们就可以启动应用并访问页面了,可以看到一个简单的点餐系统。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)