前言
完整版演示
前面我们对会员系统 分类和商品的开发 完成了收银所需的基础信息 下面我们开始完成收银台的开发
简单画了一个收银的流程图大家参考下
从这张图我们可以分析一下几点
- 可以选择会员或散客收银
- 选择会员使用相应的会员价结算
- 使用会员卡则在价格基础根据卡折扣结算
根据上述分析我搭建了一个简单的收银台
- 左边显示会员和已选择的商品信息
- 右边显示商品的价格信息
- 商品选择后可以修改数字
- 总金额自动计算
- 后续完成挂单功能便于保证收银连续性
开发中运用的组件
- Tabs 标签页 和 Card 完成右侧的商品选择
- el-autocomplete 完成会员的检索
- InputNumber Table 完成购物车开发
收银台运用过多组件会导致页面很乱 我们后续需要进行组件的封装
<template>
<div class="app-container" style="border-box:box-sizing;">
<!-- left-->
<el-row :gutter="30" style="">
<el-col :span="10">
<el-autocomplete
style="width: 100%"
popper-class="my-autocomplete"
v-model="querySearchStr"
:fetch-suggestions="querySearch"
placeholder="会员检索"
@select="handleSelect">
<i
class="el-icon-search el-input__icon"
slot="suffix"
>
</i>
<template slot-scope="{ item }">
<div v-if="item.errorMsg">
{{item.errorMsg}}
</div>
<template v-else>
<div class="name">
<i class="el-icon-user"></i>
{{ item.memberName }}
</div>
<span class="addr">
<i class="el-icon-phone"></i>
{{ item.memberPhone }}
</span>
</template>
</template>
</el-autocomplete>
<el-descriptions border title="用户信息" v-if="member.memberId" style="margin-top: 20px;margin-bottom: 20px;">
<el-descriptions-item label="用户名">{{member.memberName}}</el-descriptions-item>
<el-descriptions-item label="手机号">{{member.memberPhone}}</el-descriptions-item>
<el-descriptions-item label="备注">
{{member.remark}}
</el-descriptions-item>
</el-descriptions>
<el-descriptions border title="用户信息" v-else style="margin-top: 20px;margin-bottom: 20px;">
<el-descriptions-item label="用户名">散客</el-descriptions-item>
</el-descriptions>
<div class="grid-content bg-purple">
<el-table
border
height="400"
max-height="400"
:data="shopCart"
style="width: 100%;margin-bottom: 20px;">
<el-table-column
align="center"
prop="categoryName"
label="分类"
width="100">
</el-table-column>
<el-table-column
align="center"
prop="productName"
label="商品名"
>
</el-table-column>
<el-table-column
align="center"
prop="productAmount"
label="价格"
width="100"
>
<template slot-scope="scope">
<span v-if="app.isEmpty(member.memberId)" class="price">{{ scope.row.productAmount }}</span>
<span v-else="member.memberId" class="price">{{ scope.row.productMemberAmount }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
prop="count"
label="数量"
width="200"
>
<template slot-scope="scope">
<el-input-number size="mini" :min="0" :max="100" v-model="scope.row.count" @change="handleChange($event,scope)" ></el-input-number>
</template>
</el-table-column>
<el-table-column
align="center"
prop="totalPrice"
label="总金额"
width="100"
>
<template slot-scope="scope">
<span class="price">{{ scope.row.totalPrice }}</span>
</template>
</el-table-column>
</el-table>
<el-divider></el-divider>
总金额: <span class="price">{{app.getFloatStr(getTotalPrice)}}</span>
<el-divider></el-divider>
<el-row>
<el-button type="success">结算</el-button>
<el-button type="warning">挂单</el-button>
<el-button type="primary">取单</el-button>
</el-row>
</div>
</el-col>
<!--right-->
<el-col :span="14">
<div class="grid-content bg-purple">
<el-tabs v-model="activeName" @tab-click="handleClick" type="border-card" style="height: calc(100vh - 180px);width: 100%;overflow: scroll;overflow:hidden;">
<el-tab-pane
v-for="(item, index) in categoryList"
:key="item.categoryId"
:label="item.categoryName"
:name="item.categoryId"
>
<div>
<el-row :gutter="20" style="" v-if="productList.length>0">
<el-col @click.native="chooseProduct(item)" :span="6" v-for="item in productList" :key="item.productId" style="margin-top: 20px;cursor: pointer;">
<el-card :body-style="{ padding: '0px' }" style="height: 230px;">
<div style="height: 150px;display: flex;align-items: center;justify-content: center; box-sizing: border-box;padding-top: 10px;">
<img style="width:85%;height: 140px;border-radius: 5px;border: 1px solid #eee;" :src="baseUrl + item.productImageUrl" class="image"/>
</div>
<div style="padding:10px 0 0 10px;font-size: 16px;">
{{item.productName}}
</div>
<div style="padding:5px 0 0 10px;">
<span style="font-size: 14px;"> 散客价 <span class="price">¥ {{item.productAmount}}</span></span><br/>
<span style="font-size: 14px;"> 会员价 <span class="price">¥ {{item.productMemberAmount}}</span></span>
</div>
</el-card>
</el-col>
</el-row>
<div v-else>
<el-empty description="该分类商品为空">
</el-empty>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import {accAdd, accMul,isEmpty} from "@/utils";
import confirm from "@/utils/confirm";
import {getCategoryList} from "@/api/business/category/category";
import {getProductList} from "@/api/business/product/product";
import {getMemberList} from "@/api/business/member/member";
export default {
name: "cashierDesk",
data(){
return{
shopCart: [],
categoryList: [],
productList: [],
activeName: "",
member: {},
querySearchStr: '',
}
},
mounted() {
this.getCategoryList()
},
computed:{
getTotalPrice(){
let totalPrice = 0;
for(let product of this.shopCart){
const noMember = isEmpty(this.member.memberId)
let productTotalPrice
if(noMember){
productTotalPrice = accMul(product.productAmount,product.count)
}else{
productTotalPrice = accMul(product.productMemberAmount,product.count)
}
this.$set(product, 'totalPrice', productTotalPrice)
totalPrice = accAdd(totalPrice,productTotalPrice);
}
return totalPrice;
}
},
watch:{
shopCart(newVal,oldVal){
let showCardList = newVal
console.log('这是监听属性新的')
}
},
methods:{
querySearch(queryString, cb) {
if(queryString){
getMemberList({querySearch:queryString}).then(res=>{
// 调用 callback 返回建议列表的数据
cb(res.data);
})
}else{
cb([
{errorMsg:'暂无数据'}
])
}
},
getCategoryList(){
getCategoryList().then(res=>{
this.categoryList = res.data
if(this.categoryList.length>0){
this.activeName = this.categoryList[0].categoryId
getProductList({categoryId:this.activeName }).then(res=>{
this.productList = res.data
})
}
})
},
handleClick(e){
//拿到分类id
const categoryId = e.name
getProductList({categoryId:categoryId}).then(res=>{
this.productList = res.data
})
},
handleChange(e,scope){
console.log(e)
console.log(scope.$index)
if(e==0){
confirm('要删除该条目吗?').then(res=>{
if(res){
this.shopCart.splice(scope.$index,1)
}else{
this.shopCart[scope.$index].count = 1
}
})
}
},
chooseProduct(e){
let product = e;
let findProductIndex = this.shopCart.findIndex(p => p.productId == product.productId);
console.log(findProductIndex)
if(findProductIndex == -1){
this.$set(product, 'count', 1)
this.shopCart.push(product)
}else{
this.shopCart[findProductIndex].count += 1
}
console.log(this.shopCart)
},
handleSelect(e){
console.log(e)
this.member = e
}
}
}
</script>
<style scoped>
::v-deep .el-tabs--border-card>.el-tabs__header .el-tabs__item{
height: 50px;
line-height: 50px;
font-size: 14px;
}
.price{
font-weight: bold;
color: #ff5b57;
}
</style>
代码地址
https://gitee.com/ddeatrr/memberShop
然后为了大家预览我把开发板也部署了 大家可以参考
http://store.gbadd.space/