前端DAY03
1、套餐管理
1.1、套餐分页查询
1.1.1、需求分析和接口设计
产品原型:
业务规则:
- 根据页码展示套餐信息
- 每页展示10条数据
- 分页查询时可以根据需要,输入套餐名称、套餐分类、售卖状态进行查询
接口设计:
- 套餐分页查询接口
- 分类查询接口
1.1.2、代码开发
- 从路由文件router.ts中找到套餐管理页面(组件)
- 制作页面头部效果
-
注意:
-
输入框、按钮、下拉框都是使用ElementUI提供的组件
-
对于前端的组件只需要参考ElementUI提供的文档,进行修改即可
-
-
导入查询套餐分类的Js方法,动态填充套餐分类下拉框
- 页面组件和数据模型进行相应调整
- 为查询按钮绑定事件,发送Ajax请求获取分页数据
完整代码
<template>
<div class="dashboard-container">
<div class="container">
<div class="tableBar">
<label style="margin-right: 5px;">
套餐名称:
</label>
<el-input v-model="name" placeholder="请输入套餐名称" style="width: 15%"/>
<label style="margin-right: 5px;">
套餐分类:
</label>
<el-select v-model="categoryId" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<label style="margin-right: 5px;">
售卖状态:
</label>
<el-select v-model="saleStatus" placeholder="请选择">
<el-option
v-for="item in saleStatusArr"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type = "primary" style="margin-left: 20px" @click="pageQuery()">查询</el-button>
<div style="float: right">
<el-button type="danger">批量删除</el-button>
<el-button type="info">+ 新建套餐</el-button>
</div>
</div>
</div>
<el-table :data="records" stripe class="tableBox" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="25" />
<el-table-column prop="name" label="套餐名称" />
<el-table-column label="图片">
<template slot-scope="scope">
<el-image style="width: 80px; height: 40px; border: none" :src="scope.row.image"></el-image>
</template>
</el-table-column>
<el-table-column prop="categoryName" label="套餐分类" />
<el-table-column prop="price" label="套餐价"/>
<el-table-column label="售卖状态">
<template slot-scope="scope">
<div class="tableColumn-status" :class="{ 'stop-use': scope.row.status === 0 }">
{{ scope.row.status === 0 ? '停售' : '启售' }}
</div>
</template>
</el-table-column>
<el-table-column prop="updateTime" label="最后操作时间" />
<el-table-column label="操作" align="center" width="250px">
<template slot-scope="scope">
<el-button type="text" size="small"> 修改 </el-button>
<el-button type="text" size="small" @click="handleStartOrStop(scope.row)">
{{ scope.row.status == '1' ? '停售' : '启售' }}
</el-button>
<el-button type="text" size="small" @click="handleDelete('S',scope.row.id)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
<el-pagination class="pageList"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { getCategoryByType } from "@/api/category";
import { getSetmealPage } from "@/api/setMeal"
export default {
//模型数据
data(){
return {
name: '', //员工姓名,对应上面的输入框
page: 1, //页码
pageSize: 10, //每页记录数
total: 0, //总记录数
records: [], //当前页面要展示的数据集合
options: [],
categoryId: '', //分类id
saleStatusArr:[
{
value: '0',
label: '停售'
},
{
value: '1',
label: '起售'
}
]
}
},
created() {
//查询套餐分类,用于填充查询页面的下拉框
getCategoryByType({type:2})
.then((res) => {
if (res.data.code === 1) {
this.options = res.data.data
}
})
//页面加载完成后查询套餐数据
this.pageQuery()
},
methods: {
//分页查询
pageQuery(){
//封装分页查询参数
const params = {
Page: this.page,
pageSize: this.pageSize,
name: this.name,
status: this.status,
categoryId: this.categoryId
}
getSetmealPage(params).then((res) => {
if(res.data.code === 1){
this.total = res.data.data.total
this.records = res.data.data.records
}
}).catch((err) => {
});
},
handleSizeChange(pageSize){
this.pageSize = pageSize
this.pageQuery()
},
handleCurrentChange(page){
this.page = page
this.pageQuery()
}
},
}
</script>
<style lang="scss">
.el-table-column--selection .cell {
padding-left: 10px;
}
</style>
<style lang="scss" scoped>
.dashboard {
&-container {
margin: 30px;
.container {
background: #fff;
position: relative;
z-index: 1;
padding: 30px 28px;
border-radius: 4px;
.tableBar {
margin-bottom: 20px;
.tableLab {
float: right;
span {
cursor: pointer;
display: inline-block;
font-size: 14px;
padding: 0 20px;
color: $gray-2;
}
}
}
.tableBox {
width: 100%;
border: 1px solid $gray-5;
border-bottom: 0;
}
.pageList {
text-align: center;
margin-top: 30px;
}
//查询黑色按钮样式
.normal-btn {
background: #333333;
color: white;
margin-left: 20px;
}
}
}
}
</style>
1.1.3、功能测试
1.2、起售停售套餐
1.2.1、需求分析和接口设计
业务规则:
- 可以对状态为“启售”的套餐进行“停售”操作
- 可以对状态为“停售”的套餐进行“启售”操作
接口设计:
1.2.2、代码开发
完整代码
<template>
<div class="dashboard-container">
<div class="container">
<div class="tableBar">
<label style="margin-right: 5px;">
套餐名称:
</label>
<el-input v-model="name" placeholder="请输入套餐名称" style="width: 15%"/>
<label style="margin-right: 5px;">
套餐分类:
</label>
<el-select v-model="categoryId" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<label style="margin-right: 5px;">
售卖状态:
</label>
<el-select v-model="saleStatus" placeholder="请选择">
<el-option
v-for="item in saleStatusArr"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type = "primary" style="margin-left: 20px" @click="pageQuery()">查询</el-button>
<div style="float: right">
<el-button type="danger">批量删除</el-button>
<el-button type="info">+ 新建套餐</el-button>
</div>
</div>
</div>
<el-table :data="records" stripe class="tableBox" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="25" />
<el-table-column prop="name" label="套餐名称" />
<el-table-column label="图片">
<template slot-scope="scope">
<el-image style="width: 80px; height: 40px; border: none" :src="scope.row.image"></el-image>
</template>
</el-table-column>
<el-table-column prop="categoryName" label="套餐分类" />
<el-table-column prop="price" label="套餐价"/>
<el-table-column label="售卖状态">
<template slot-scope="scope">
<div class="tableColumn-status" :class="{ 'stop-use': scope.row.status === 0 }">
{{ scope.row.status === 0 ? '停售' : '启售' }}
</div>
</template>
</el-table-column>
<el-table-column prop="updateTime" label="最后操作时间" />
<el-table-column label="操作" align="center" width="250px">
<template slot-scope="scope">
<el-button type="text" size="small"> 修改 </el-button>
<el-button type="text" size="small" @click="handleStartOrStop(scope.row)">
{{ scope.row.status == '1' ? '停售' : '启售' }}
</el-button>
<el-button type="text" size="small" @click="handleDelete('S',scope.row.id)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
<el-pagination class="pageList"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { getCategoryByType } from "@/api/category";
import { getSetmealPage,enableOrDisableSetmeal } from "@/api/setMeal"
export default {
//模型数据
data(){
return {
name: '', //员工姓名,对应上面的输入框
page: 1, //页码
pageSize: 10, //每页记录数
total: 0, //总记录数
records: [], //当前页面要展示的数据集合
options: [],
categoryId: '', //分类id
saleStatusArr:[
{
value: '0',
label: '停售'
},
{
value: '1',
label: '起售'
}
]
}
},
created() {
//查询套餐分类,用于填充查询页面的下拉框
getCategoryByType({type:2})
.then((res) => {
if (res.data.code === 1) {
this.options = res.data.data
}
})
//页面加载完成后查询套餐数据
this.pageQuery()
},
methods: {
//分页查询
pageQuery(){
//封装分页查询参数
const params = {
Page: this.page,
pageSize: this.pageSize,
name: this.name,
status: this.status,
categoryId: this.categoryId
}
getSetmealPage(params).then((res) => {
if(res.data.code === 1){
this.total = res.data.data.total
this.records = res.data.data.records
}
}).catch((err) => {
});
},
handleSizeChange(pageSize){
this.pageSize = pageSize
this.pageQuery()
},
handleCurrentChange(page){
this.page = page
this.pageQuery()
},
//套餐起售停售操作
handleStartOrStop(row){
const p ={
id: row.id,
status: !row.status ? 1:0
}
this.$confirm('此操作将会修改套餐的状态,是否继续?','提示',{
confirmButtonText:'确定',
cancelButtonText:'取消',
type:'warning'
}).then((res) => {
enableOrDisableSetmeal(p).then(res =>{
if(res.data.code ===1){
this.$message.success('套餐售卖状态修改成功')
this.pageQuery()
}
})
}).catch((err) => {
});
}
}
}
</script>
<style lang="scss">
.el-table-column--selection .cell {
padding-left: 10px;
}
</style>
<style lang="scss" scoped>
.dashboard {
&-container {
margin: 30px;
.container {
background: #fff;
position: relative;
z-index: 1;
padding: 30px 28px;
border-radius: 4px;
.tableBar {
margin-bottom: 20px;
.tableLab {
float: right;
span {
cursor: pointer;
display: inline-block;
font-size: 14px;
padding: 0 20px;
color: $gray-2;
}
}
}
.tableBox {
width: 100%;
border: 1px solid $gray-5;
border-bottom: 0;
}
.pageList {
text-align: center;
margin-top: 30px;
}
//查询黑色按钮样式
.normal-btn {
background: #333333;
color: white;
margin-left: 20px;
}
}
}
}
</style>
1.2.3、功能测试
1.3、删除套餐
1.3.1、需求分析和接口设计
产品原型:
业务规则:
- 点击删除按钮,删除指定的一个套餐
- 勾选需要删除的套餐,点击批量删除按钮,删除选中的一个或多个套餐
接口设计:一个接口,兼容两种删除方式
1.3.2、代码开发
- 在setMeal.ts中封装删除套餐方法,发送Ajax请求
完整代码
<template>
<div class="dashboard-container">
<div class="container">
<div class="tableBar">
<label style="margin-right: 5px;">
套餐名称:
</label>
<el-input v-model="name" placeholder="请输入套餐名称" style="width: 15%"/>
<label style="margin-right: 5px;">
套餐分类:
</label>
<el-select v-model="categoryId" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<label style="margin-right: 5px;">
售卖状态:
</label>
<el-select v-model="saleStatus" placeholder="请选择">
<el-option
v-for="item in saleStatusArr"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type = "primary" style="margin-left: 20px" @click="pageQuery()">查询</el-button>
<div style="float: right">
<el-button type="danger" @click="handleDelete('B')">批量删除</el-button>
<el-button type="info">+ 新建套餐</el-button>
</div>
</div>
</div>
<el-table :data="records" stripe class="tableBox" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="25" />
<el-table-column prop="name" label="套餐名称" />
<el-table-column label="图片">
<template slot-scope="scope">
<el-image style="width: 80px; height: 40px; border: none" :src="scope.row.image"></el-image>
</template>
</el-table-column>
<el-table-column prop="categoryName" label="套餐分类" />
<el-table-column prop="price" label="套餐价"/>
<el-table-column label="售卖状态">
<template slot-scope="scope">
<div class="tableColumn-status" :class="{ 'stop-use': scope.row.status === 0 }">
{{ scope.row.status === 0 ? '停售' : '启售' }}
</div>
</template>
</el-table-column>
<el-table-column prop="updateTime" label="最后操作时间" />
<el-table-column label="操作" align="center" width="250px">
<template slot-scope="scope">
<el-button type="text" size="small"> 修改 </el-button>
<el-button type="text" size="small" @click="handleStartOrStop(scope.row)">
{{ scope.row.status == '1' ? '停售' : '启售' }}
</el-button>
<el-button type="text" size="small" @click="handleDelete('S',scope.row.id)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
<el-pagination class="pageList"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</div>
</template>
<script lang="ts">
import { getCategoryByType } from "@/api/category";
import { getSetmealPage,enableOrDisableSetmeal,deleteSetmeal } from "@/api/setMeal"
export default {
//模型数据
data(){
return {
name: '', //员工姓名,对应上面的输入框
page: 1, //页码
pageSize: 10, //每页记录数
total: 0, //总记录数
records: [], //当前页面要展示的数据集合
options: [],
categoryId: '', //分类id
saleStatusArr:[
{
value: '0',
label: '停售'
},
{
value: '1',
label: '起售'
}
],
status:'', //售卖状态
multipleSelection: '' //当前表格选中的多个元素
}
},
created() {
//查询套餐分类,用于填充查询页面的下拉框
getCategoryByType({type:2})
.then((res) => {
if (res.data.code === 1) {
this.options = res.data.data
}
})
//页面加载完成后查询套餐数据
this.pageQuery()
},
methods: {
//分页查询
pageQuery(){
//封装分页查询参数
const params = {
Page: this.page,
pageSize: this.pageSize,
name: this.name,
status: this.status,
categoryId: this.categoryId
}
getSetmealPage(params).then((res) => {
if(res.data.code === 1){
this.total = res.data.data.total
this.records = res.data.data.records
}
}).catch((err) => {
});
},
handleSizeChange(pageSize){
this.pageSize = pageSize
this.pageQuery()
},
handleCurrentChange(page){
this.page = page
this.pageQuery()
},
//套餐起售停售操作
handleStartOrStop(row){
const p ={
id: row.id,
status: !row.status ? 1:0
}
this.$confirm('此操作将会修改套餐的状态,是否继续?','提示',{
confirmButtonText:'确定',
cancelButtonText:'取消',
type:'warning'
}).then((res) => {
enableOrDisableSetmeal(p).then(res =>{
if(res.data.code ===1){
this.$message.success('套餐售卖状态修改成功')
this.pageQuery()
}
})
}).catch((err) => {
});
},
//删除套餐
handleDelete(type: string,id: string){
this.$confirm('确定删除当前指定的套餐,是否继续?','提示',{
confirmButtonText:'确定',
cancelButtonText:'取消',
type:'warning'
}).then(() => {
let param = ''
if(type == 'B'){ //批量删除
const arr = new Array
this.multipleSelection.forEach(element => {
arr.push(element.id)
})
param = arr.join(',')
}else{ //单一删除
param = id
}
deleteSetmeal(id).then(res =>{
if(res.data.code ===1){
this.$message.success('删除成功')
this.pageQuery()
}else{
this.$message.error(res.data.msg)
}
})
})
},
//复选框
handleSelectionChange(val){
this.multipleSelection = val
}
}
}
</script>
<style lang="scss">
.el-table-column--selection .cell {
padding-left: 10px;
}
</style>
<style lang="scss" scoped>
.dashboard {
&-container {
margin: 30px;
.container {
background: #fff;
position: relative;
z-index: 1;
padding: 30px 28px;
border-radius: 4px;
.tableBar {
margin-bottom: 20px;
.tableLab {
float: right;
span {
cursor: pointer;
display: inline-block;
font-size: 14px;
padding: 0 20px;
color: $gray-2;
}
}
}
.tableBox {
width: 100%;
border: 1px solid $gray-5;
border-bottom: 0;
}
.pageList {
text-align: center;
margin-top: 30px;
}
//查询黑色按钮样式
.normal-btn {
background: #333333;
color: white;
margin-left: 20px;
}
}
}
}
</style>
ve;
z-index: 1;
padding: 30px 28px;
border-radius: 4px;
.tableBar {
margin-bottom: 20px;
.tableLab {
float: right;
span {
cursor: pointer;
display: inline-block;
font-size: 14px;
padding: 0 20px;
color: $gray-2;
}
}
}
.tableBox {
width: 100%;
border: 1px solid $gray-5;
border-bottom: 0;
}
.pageList {
text-align: center;
margin-top: 30px;
}
//查询黑色按钮样式
.normal-btn {
background: #333333;
color: white;
margin-left: 20px;
}
}
}
}
#### 1.3.3、功能测试
![\[外链图片转存中...(img-RjvVBZgA-1725427732990)\]](https://i-blog.csdnimg.cn/direct/b1ea397e7a7e4c21ae4d8ea308f08f45.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://i-blog.csdnimg.cn/direct/73025364626949a3910ce268a97ccbbf.png)