关于SSM框架大酒店项目的个人小小叙述

写在前面:table组件有数据源,接收到数组类型的数据之后,默认直接"破甲"就进去到一个对象里面,直接prop使用里面的数据即可

                describe组件没有数据源,接收到对象类型的数据后必须得用大胡子表达式点"."属性

                卡片里外边包着的类型必须得是数组,要不然v-for,:遍历不到,拿不到每张照片的具体数据

查询页面FoodList

                只要涉及到卡片外边就得的组件就得是el-row和el-cow,其中cow用来接收数据,并遍历

选择部门:

返回一个FoodType类型的数组(List<FoodType>),前端可以创建一个数组接收这个数组,并遍历这个数组,得到其中的每个部门对象,利用选择器(v-for这个数组,:label="对象.name,:value="对象.id,:key="索引")

Vue

queryAllFoodTypes(){
                this.$ajax.get('/djd/queryAllFoodTypes').then(resp=>{
                    this.FoodTypes=resp.data.data
                })
},

html组装

<el-form-item label="所在菜系">
    <el-select v-model="params.type" placeholder="请选择所在菜系">
        <el-option v-for="(item,index) in FoodTypes" 
               :label="item.ftname"
               :value="item.id"
               :key="index">
        </el-option>                        
    </el-select>
</el-form-item>

Idea.Controller

@RequestMapping("/queryAllFoodTypes")
    public JSONResponse queryAllFoodTypes(){
        List<FoodType> allFoodTypes = service.queryAllFoodTypes();
        return ResultStatus.suc(allFoodTypes);
}

返回的数据

{
    "code": 200,
    "msg": "success",
    "data": [
        {
            "id": 1,
            "ftname": "鲁菜",
            "info": null
        },
        {
            "id": 2,
            "ftname": "川菜",
            "info": null
        },
        {
            "id": 3,
            "ftname": "粤菜",
            "info": null
        }
    ]
}

table菜品表格展示,分页:

前面添加用到了此FoodDto因为传入的有照片仨信息,本次展示是因为用到了分页的俩数据

form表单中的v-model绑定一个对象params,特别注意<el-select>标签绑定的谁的值

前端

<el-collapse v-model="activeNames">
    <el-collapse-item title="条件查询" name="1">
        <el-form :inline="true" :model="params" class="demo-form-inline">
            <el-form-item label="菜品名称">
                <el-input v-model="params.fname" placeholder="请输入菜品名称"></el-input>
            </el-form-item>
            <el-form-item label="所在菜系">
                <el-select v-model="params.type" placeholder="请选择所在菜系">
                    <el-option v-for="(item,index) in FoodTypes" 
                    :label="item.ftname"
                    :value="item.id"
                    :key="index">
                    </el-option>                        
                </el-select>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="querySome()">查询</el-button>
            </el-form-item>
        </el-form>
    </el-collapse-item>
</el-collapse>

script

params:{
    pageNumber:1,
    pageSize:5,
    type:'',
    fname:'',
},
querySome(){
    this.$ajax.post('/djd/querySome',this.params).then(resp=>{
        console.log('查询结果为:',resp)
        this.tableData=resp.data.data.rows
        this.total=resp.data.data.total
    })
},

后端

用来接收前端分页信息和继承自Food的属性

 用来返回前端需要的所有数据(分页2+1=3信息,列表所需要的数据,这里因为是table所以他需要一个数组:表格的每一行会打开这个数组,得到里面的每一个对象[{},{},{}]),rows的数据还不知道,这里暂定为泛型<任意类型>

 前端需要展示的的数据包括三个表,定义一个表格展示页Vo用来接mybatis的result_Map数据

1:给分页类创建一个page对象类型是分页三张表Vo:其实就是把三张表的数据给page这个对象

2:执行querySome查询(添加条件以后别忘了在service层传值),结果是一堆分页Vo的数组存起来,切记在service的得加入穿过来的dto.pageNumber()和dto.pageSize()

@Override
    public List<FoodPageVO> querySome(FoodDTO dto) {
        PageHelper.startPage(dto.getPageNumber(),dto.getPageSize());
        return dao.querySome(dto);
    }

3:把得到的数据给分页构造方法,然后从pageInfo里取数据

传来的是一个json对象,记得加@RequestBody

 @RequestMapping("/querySome")
    public JSONResponse querySome(@RequestBody FoodDTO dto){
        System.out.println(dto);
        //把FoodPageVo下的三个值放到Page中返回
        Page<FoodPageVO> page = new Page<>();
        page.setPageNumber(dto.getPageNumber());
        page.setPageSize(dto.getPageSize());
        
===========//单独定义一下FoodPage的类型是数组================这点很重要
        List<FoodPageVO> foods = service.querySome(dto);
        PageInfo<FoodPageVO> info = new PageInfo(foods);
        page.setTotal(info.getTotal());
        page.setRows(info.getList());
        System.out.println(page);
        return foods!=null?ResultStatus.suc(page):ResultStatus.error("没有查到数据");
    }

mybatis

将查出的数据放到Vo类型的数组返回

        字符串类型的判断是否为空或者空字符串,数字类型的判断是否为空或等于0

连仨表

        有歧义id,id,id 不知道具体是哪个表的id 解决:f.id,ft.id,p.id

        有别名f.id,ft.id,p.id   都叫id 解决:起别名 as fid,ftid,pid /result_Map

一对一对一 association---association

        <resultMap id="起个resultMap名"  type="页面Vo具体所在哪">

                <id property="父类的id" column="表字段/如果字段较复杂,起别名后塞入"></result>

                <result property="父类属性" column="表字段"></result>

                <association property="在Vo中的属性名" javaType="作为从表的实体类在哪里">

                        <id property="类id" column="表字段"></id>

                        <result property="类id" column="类字段"></result>

        </resultMap>

​
<resultMap id="rMap_food" type="com.etoak.rst.food.vo.FoodPageVO">
        <id property="id" column="id"></id>
        <result property="fname" column="fname"></result>
        <result property="type" column="type"></result>
        <result property="beforeprice" column="beforeprice"></result>
        <result property="nowprice" column="nowprice"></result>
        <result property="tip" column="tip"></result>
        <result property="idShelve" column="idShelve"></result>
        <association property="types" javaType="com.etoak.rst.food.pojo.FoodType">
            <id property="id" column="id"></id>
            <result property="ftname" column="ftname"></result>
            <result property="info" column="info"></result>
        </association>
        <association property="pics" javaType="com.etoak.rst.food.pojo.Pic">
            <result property="savepath" column="savepath"></result>
            <result property="realname" column="realname"></result>
            <result property="uploadtime" column="uploadtime"></result>
            <result property="flag" column="flag"></result>
            <result property="foodid" column="foodid"></result>
        </association>
    </resultMap>

    <select id="querySome" resultMap="rMap_food">
        select f.id,fname,type,beforeprice,nowprice,tip,idShelve,ft.id,ftname,info,
        savepath,realname,uploadtime,flag,foodid
        from rst_food f
        left join rst_foodtype ft on f.type=ft.id
        left join rst_pic p on f.id = p.foodid and flag=1
        <where>
            <if test="fname!=null and fname!='' ">
                and f.fname like '%${fname}%'
            </if>
            <if test="type!=null and type!=0">
                and f.type=#{type}
            </if>
        </where>
    </select>

​

前端用一个数组接收page对象的这些数据

        定一个数组接收rows的数据

tableData:[],

{pageNumber,pageSize,total,rows[{id,name,price,pics{},types{}},{},{}]}

想要的具体数据格式为数组里套Food的属性加types和pics对象,这两个对象里边再有属性

table组件的每一行就可以直接破解[]数组,得到当前对象

想要的数据类型是数组包着的

{
    "code": 200,
    "msg": "success",
    "data": {
        "pageNumber": 1,
        "pageSize": 5,
        "total": 6,
        "rows": [
            {
                "id": 14,
                "fname": "麦子",
                "beforeprice": 123.0,
                "nowprice": 123.0,
                "type": 1,
                "tip": "2312",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/b1140ea9486b4b72b5435e277ab08323.jpg",
                    "realname": "麦子.jpg",
                    "uploadtime": "2023-07-23",
                    "foodid": 14,
                    "flag": 1
                },
                "types": {
                    "id": 14,
                    "ftname": "鲁菜",
                    "info": "这是鲁菜"
                }
            },
            {
                "id": 15,
                "fname": "麦麦子",
                "beforeprice": 333.0,
                "nowprice": 111.0,
                "type": 2,
                "tip": "qwe",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/9f6e791dba424a23b68463ac7abd8ddc.jpg",
                    "realname": "麦子.jpg",
                    "uploadtime": "2023-07-23",
                    "foodid": 15,
                    "flag": 1
                },
                "types": {
                    "id": 15,
                    "ftname": "川菜",
                    "info": "这是川菜"
                }
            },
            {
                "id": 16,
                "fname": "光膀子",
                "beforeprice": 333.0,
                "nowprice": 123.0,
                "type": 2,
                "tip": "jklj",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/3725696a7ed84698953d397ce405d095.jpg",
                    "realname": "光膀子.jpg",
                    "uploadtime": "2023-07-23",
                    "foodid": 16,
                    "flag": 1
                },
                "types": {
                    "id": 16,
                    "ftname": "川菜",
                    "info": "这是川菜"
                }
            },
            {
                "id": 17,
                "fname": "蝴蝶",
                "beforeprice": 9809.0,
                "nowprice": 5687.0,
                "type": 3,
                "tip": "见识到了",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/bf14159a0ed243c2a5daf859d11c18e9.webp",
                    "realname": "蝴蝶.webp",
                    "uploadtime": "2023-07-23",
                    "foodid": 17,
                    "flag": 1
                },
                "types": {
                    "id": 17,
                    "ftname": "粤菜",
                    "info": "这是粤菜"
                }
            },
            {
                "id": 18,
                "fname": "瀑布",
                "beforeprice": 11.0,
                "nowprice": 1111.0,
                "type": 2,
                "tip": "1",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/bf14159a0ed243c2a5daf859d11c18e9.webp",
                    "realname": "蝴蝶.webp",
                    "uploadtime": "2023-07-23",
                    "foodid": 18,
                    "flag": 1
                },
                "types": {
                    "id": 18,
                    "ftname": "川菜",
                    "info": "这是川菜"
                }
            }
        ]
    }
}

列表

 <el-table :data="tableData" border stripe style="width: 100%">
            <el-table-column type="index"></el-table-column>
            <el-table-column  label="封面" width="180">
            <template slot-scope="scope">
                <el-image :src="scope.row.pics?'http://localhost:8080/djd/'+scope.row.pics.savepath:mypic" />
            </template>
        </el-table-column>
            <el-table-column prop="fname" label="菜名"></el-table-column>
            <el-table-column prop="beforeprice" label="原价"></el-table-column>
            <el-table-column prop="nowprice" label="现价"></el-table-column>
            <el-table-column prop="type" label="菜系"></el-table-column>
            <el-table-column prop="tip" label="标签"></el-table-column>
            <el-table-column prop="idShelve" label="是否上架"></el-table-column>
            <el-table-column  label="操作">
                <template slot-scope="scope">
                    <el-button type="success" size="mini"  @click="jumpToFoodInfo(scope.row.id)">查看菜品</el-button>
                    <el-button type="success" size="mini"  @click="deleteFood(scope.row.id)">删除菜品</el-button>
                </template>
            </el-table-column>
        </el-table>

想要显示照片外边必须套template模板scope.row就是当前对象,再.pics.savepath就是照片地址

<el-table-column  label="封面" width="180">
            <template slot-scope="scope">
                <el-image :src="scope.row.pics?'http://localhost:8080/djd/'+scope.row.pics.savepath:mypic" />
            </template>
</el-table-column>

分页(务必不要忘了函数回显)

        两个钩子函数,当前页,每页记录数,total

<el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="params.pageNumber"
                :page-sizes="[5,6,7,8]"
                :page-size="params.pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
</el-pagination>
total:0,
mypic:require('@/assets/logo.png'),
params:{
pageNumber:1,
pageSize:5,
type:'',
fname:'',
},
//每页记录数发生变化
handleSizeChange(v){ 
    this.params.pageSize=v
    this.querySome()
},
//当前页发生改变时触发
handleCurrentChange(v){
    this.params.pageNumber=v
    this.querySome()
},

querySome(){
    this.$ajax.post('/djd/querySome',this.params).then(resp=>{
    console.log('查询结果为:',resp)
    this.tableData=resp.data.data.rows
    this.total=resp.data.data.total
    })
},

   

每一道菜品详情页(描述列表)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

路由跳转带传值

jumpToFoodInfo(foodid){
    this.$router.push({
        path:`/foodinfo`,query:{id:foodid}
    })
},

mounted里执行this.queryFoodInfoById()方法,返回值是一个对象{id,fname,nowprice,{[],[]},{}}

前端带着菜的id发请求

queryFoodInfoById(){
                this.$ajax.post('/djd/queryFoodInfoById','id='+this.$route.query.id).then(resp=>{
                    console.log(resp)
                    this.foodPicType=resp.data.data
                }
                )
            }

后端发回去的是一个对象,唯一不同的是,一道菜有多个照片,用数组装Pic,把多张照片放到这个List数组里

 单个值,直接int id(指定传来的形参名)

//单个菜的信息
@RequestMapping("queryFoodInfoById")
public JSONResponse queryFoodInfoById(int id){
    FoodPicTypeVO foodInfo = service.queryFoodInfoById(id);
    return foodInfo!=null?ResultStatus.suc(foodInfo):ResultStatus.error("没有此菜的信息");
}

mybatis

        set到PageTypePicVo

<resultMap id="rMap_foodInfo" type="com.etoak.rst.food.vo.FoodPicTypeVO">
        <id property="id" column="id"></id>
        <result property="fname" column="fname"></result>
        <result property="type" column="type"></result>
        <result property="beforeprice" column="beforeprice"></result>
        <result property="nowprice" column="nowprice"></result>
        <result property="tip" column="tip"></result>
        <result property="idShelve" column="idShelve"></result>
        <association property="types" javaType="com.etoak.rst.food.pojo.FoodType">
            <result property="id" column="id"></result>
            <result property="ftname" column="ftname"></result>
            <result property="info" column="info"></result>
        </association>
        <collection property="pics" ofType="com.etoak.rst.food.pojo.Pic" javaType="java.util.List">
            <result property="id" column="pid"></result>
            <result property="savepath" column="savepath"></result>
            <result property="realname" column="realname"></result>
            <result property="uploadtime" column="uploadtime"></result>
            <result property="flag" column="flag"></result>
            <result property="foodid" column="foodid"></result>
        </collection>
    </resultMap>
    <select id="queryFoodInfoById" resultMap="rMap_foodInfo">
        select f.id,fname,type,beforeprice,nowprice,tip,idShelve,ft.id,ftname,info,
        p.id pid,savepath,realname,uploadtime,flag,foodid from rst_food f
        left join rst_foodtype ft on f.type=ft.id
        left join rst_pic p on f.id = p.foodid where f.id=#{id}
    </select>

返回的数据

特别要注意:这里的数据是个对象包着的,为了在卡片组件里遍历多张卡片所以pics那部分是用数组包着每个的照片对象

{
    "code": 200,
    "msg": "success",
    "data": {
        "id": 14,
        "fname": "麦子",
        "beforeprice": 123.0,
        "nowprice": 123.0,
        "type": 1,
        "tip": "2312",
        "idShelve": 0,
        "pics": [
            {
                "id": 18,
                "savepath": "/files/b9b820e13c7048ddb3c23659266a0c24.jpg",
                "realname": "七星瓢虫.jpg",
                "uploadtime": "2023-07-23",
                "foodid": 14,
                "flag": 0
            },
            {
                "id": 19,
                "savepath": "/files/b1140ea9486b4b72b5435e277ab08323.jpg",
                "realname": "麦子.jpg",
                "uploadtime": "2023-07-23",
                "foodid": 14,
                "flag": 1
            }
        ],
        "types": {
            "id": 14,
            "ftname": "鲁菜",
            "info": "这是鲁菜"
        }
    }
}

前端初始化一个对象接收这个对象,描述列表只能根据这个接收的对象使用大胡子表达式来显示值

data(picid) {
    return {
        foodPicType:{},
    }
},

如果描述列表规定了有几column:3,子描述列表需设置:span="3"才能把下一个子描述列表挤下去,和他一样占3个column

<子描述列表>

        <el-row>

                <el-col v-for="" :key>

                        <el-card :body-style="{padding:'0px'}">

                        </el-card>

                </el-col>

        </el-row>

</子描述列表>

修改菜的封面

传入的值必须是遍历得到的每个照片对象,需要拿着照片的id和foodid在service实现类中开始事务处理

get方法的传值

updateAvatar(pic){
                this.$ajax.get('/djd/updateAvatar',{
                    params:{
                        pid: pic.id,
                        foodid: pic.foodid
                    }
                }).then(resp=>{
                    if (resp.data.code==200) {
                        this.$message.success("头像修改成功!")
                        this.queryFoodInfoById()
                    }else{
                        this.$message.warning("头像修改失败!")
                    }
                })
            },

后端

 // 修改菜封面
    @GetMapping("/updateAvatar")
    public JSONResponse updateAvatar(int pid, int foodid){
        boolean flag = service.updateAvatar(pid, foodid);
        return flag?ResultStatus.suc("修改成功"):ResultStatus.error("修改失败");
    }

serviceImpl

@Override
    @Transactional
    public boolean updateAvatar(int pid, int foodid) {
        /**  修改原来的 需要foodid */
        int count = dao.updateOrigin(foodid);
        /**  修改现在的 */
        int count2 = dao.updateNow(pid);
        return count>0 && count2>0;
    }

mybatis(把带foodid(相同菜)照片全设为0,再把id(当前菜)设为1)

<update id="updateOrigin">
        update rst_pic set flag=0 where foodid=#{foodid}
    </update>
    <update id="updateNow">
        update rst_pic set flag=1 where id=#{pid}
    </update>

展示所有的菜系

        得到菜系的fname,id

mounted() {
    this.queryAllFoodTypes()
},

        初始化一个fts数组,接收菜系对象数组

data() {
    return {
        mypic:require('@/assets/logo.png'),
        fts:[],
        activeName:'',
        foods:[],//某个菜系下的菜品信息
    }
},

在标签页子组件中遍历这个数组

        v-for="(item,index) in fts"

        :label="item.ftname"

        :name="item.id+''"

        :key="index"

<div>
        <el-card class="card-box">
            <el-tabs v-model="activeName" type="card" @tab-click="queryFoodById">
                <el-tab-pane v-for="(item,index) in fts" :label="item.ftname" :name="item.id+''" :key="index" :ftid="item.id">
                    <el-row>
                        <el-col :span="6" v-for="(item, index) in foods" :key="index">
                            <el-card :body-style="{ padding: '0px' }">
                            <img style="width:350px;height:350px" :src="item.pics?'http://localhost:8080/djd'+item.pics.savepath:mypic" class="image">
                            <div style="padding: 14px;">

                                <span>{{item.fname}} | <strong>{{item.nowprice}}$</strong></span>
                                <div class="bottom clearfix">
                                <time class="time">{{ item.pics.uploadtime }}</time><br>
                                <el-button type="text" class="button" @click="addToCar(item)">加入购物车</el-button>
                                </div>
                            </div>
                            </el-card>
                        </el-col>
                    </el-row>
                </el-tab-pane>
            </el-tabs>
        </el-card>    
    </div>

根据菜系查这个菜系下有哪些菜

        1:在标签加上@tab-click的激发动作

        2:然后在子标签上带上要携带的数据,这里携带的是遍历得到的单菜系id,

                :ftid="item.id"

        3:函数

                

queryFoodById(tab,event){
    let id = tab.$attrs.ftid
    this.doQueryFoodByType(id)
},
doQueryFoodByType(id){
    this.$ajax.post('/djd/queryFoodsById','ftid='+id).then(resp=>{
    console.log(resp)
    this.foods=resp.data.data
    console.log('foodsssssssssss',this.foods)
    })
},

        4:初始化一个foods数组接收三张表的参数

                这里的得到的数据是需要上来就要被<el-col><card></card></el-col>遍历然后对象点.的,所以需要传一个数组

后端

//cus页面每种菜系的菜品
    @RequestMapping("/queryFoodsById")
    public JSONResponse queryFoodsById(int ftid){
        List<FoodPageVO> foodsAndPic = service.queryFoodsById(ftid);
        return foodsAndPic!=null?ResultStatus.suc(foodsAndPic):ResultStatus.error("没有数据");
    }
}

myabtis

<select id="queryFoodsById" resultMap="rMap_food">
        select f.id,fname,type,beforeprice,nowprice,tip,idShelve,ft.id,ftname,info,
        savepath,realname,uploadtime,flag,foodid
        from rst_food f
        left join rst_foodtype ft on f.type=ft.id
        left join rst_pic p on f.id = p.foodid and flag=1 where ft.id=#{ftid}
</select>

默认打开就是第一个菜系标签页子组件

        前提:执行所有菜系的id和ftname的查询赋值到fts数组中

        1:根据实例化的fts得到所有的菜系的id和ftname,让标签组件v-model(双向绑定)一直处于被选中状态,第一个菜系的id被选中(但仅仅选中子标签,不会触发这种菜系找所有菜的查询)==>手动从菜系数组里找到第一个菜系的id,展示这个菜系的每道菜

        2:从实例化的fts数组拿第一个菜系的id去查询,就展示了默认进入界面的第一个菜系的所有菜

//查询菜系信息
queryAllFoodTypes(){
    this.$ajax.post('/djd/queryAllFoodTypes').then(resp=>{
    this.fts=resp.data.data
    //鲁菜第一
    this.activeName=this.fts[0].id+''
    this.doQueryFoodByType(this.fts[0].id)
    })
}

添加购物车

拿到登录用户cid和每道菜的fid,往后端发链接,后端利用Redis把这些数据存下来

//真正添加购物车的方法
doAddToCar(foodid){
    let cusid = window.sessionStorage.getItem("cusid")
    if (cusid) {
        this.$ajax.post('/cus/addToCar','fid='+foodid+'&cid='+cusid).then(resp=>{
            if (resp.data.code===200) {
                this.$message.success("添加成功!")
            }
        }).catch(error=>{
            console.log('error:',error)
        })
    }
},

后端

        .hexists(_,_):判断当前用户和菜名是否存在

        如果存在==>.hincrby(_,_,1L)数量+1

        不存在==>.hset(_,_,"1")添进去       

@RequestMapping("/addToCar")
    public JSONResponse addToCar(String fid,String cid){
        //获取和Redis的链接
        RedisUtil ru = RedisUtil.getRedisUtil();
        //判断购物车(redis的数据库)中是否有对应的数据
        //哈希,是否存在
        //cid: fid:num
        Boolean flag = ru.hexists(cid, fid);
        if(flag){
            //存在:数量+1
            ru.hincrby(cid,fid,1L);
        }else{
            //不存在:存进去
            ru.hset(cid,fid,"1");
        }
        return ResultStatus.suc("添加成功");
    }

从购物车拿东西

        拿东西只需要用户的cid即可,后端建立了一个工具篮子来装数据(后端部分会详细讲到),返回的数据形式见后边

                关于合计的计算方法:

                        1:用遍历拿到每道菜的sum,然后+=这次查到的总金额                        

                        2:由于每次进购物车界面或修改(主要是修改,每次修改都会回显从后端从新拿值)菜的数量都会改变从后端取到的sum值,所以初始化一个hj(合计不展示在table里,且需要遍历累加),每次改变都要this.hj=0.0,重置上次的合计hj金额,再遍历出来新的sum赋值给实例化的hj

queryFromCart(){
//每次计算合计先清空
this.hj=0.0
let cusid = window.sessionStorage.getItem("cusid")
if (cusid) {
    this.$ajax.post('/cus/queryFromCart','cid='+cusid).then(resp=>{
        if (resp.data.code===200) {
            console.log(resp)
            this.tableData=resp.data.data
            this.tableData.forEach(lz=>{
                this.hj+=lz.sum
            })
        }
    }).catch(error=>{
        console.log('error:',error)
    })} 
},

界面

        谁然直接"破甲"[{}],但数据封装到了每道菜破甲之后的food里

<div class="qqq">
        <el-table @selection-change="changeSelection" :data="tableData" border stripe style="width: 100%">
            <el-table-column type="index"></el-table-column>
            <el-table-column type="selection"></el-table-column>
            <el-table-column  label="封面" width="180">
            <template slot-scope="scope">
                <el-image :src="scope.row.food.pics?'http://localhost:8080/djd/'+scope.row.food.pics.savepath:mypic" />
            </template>
        </el-table-column>
            <!--绑定谁-->
            <el-table-column label="数量">
                <template slot-scope="scope">
                    <!--row是篮子-->
                    <el-input-number v-model="scope.row.count" @change="updateCount(scope.row)" :min="0" :max="10"></el-input-number>
                </template>
            </el-table-column>
            <el-table-column prop="food.fname" label="菜名"></el-table-column>
            <el-table-column prop="food.beforeprice" label="原价"></el-table-column>
            <el-table-column prop="food.nowprice" label="现价"></el-table-column>
            <el-table-column prop="food.type" label="菜系"></el-table-column>
            <el-table-column prop="sum" label="总价"></el-table-column>
        </el-table>
        <h1>合计:{{hj}}</h1>
        <br/><br/>
        <el-button type="success" @click="jumpToOrders">提交订单</el-button>
    </div>

后端

        关于篮子工具类的解释:篮子类存放每道菜的数量,每道菜的总金额(算出来),Food类型的food(后面调service层查询时可以看到Food类其实是FoodPageVo的一个父类,FoodPageVo这个子类包含了food,pic,foodtype三张表的数据,把子类类型的数据让父类来接,不过分!)

        用篮子类来装每道菜对象的(三张表信息,数量,金额),且前端是以表格的形式展示,所以需要一个数组,给这个数组起个名叫lanzis,每一个不带s的lanzi独享包含(三张表信息,数量,金额)

        根据传过来的用户cid可以查找到对应的key:(key:value)也就是(fid:count)值,需要用一个键值对集合去接收

        新建一个键值对的map,利用增强for得到每一道菜的fid和count,把篮子每次循环的时候跟着new一个不带s的菜对象,每次循环都给每道菜对象set count,food的值(这个food是调用service传值,刚才从redis取到的fid去找,这道菜的三张表的所有信息,得到的是FoodPageVo子类类型,但用Food父类装,因为FoodPageVo继承自Food),num需要在Lanzi类里根据刚才查到的food三张表里的数据getNowPrice*刚才赋值的count数量

        每一次循环把每道菜装到篮子数组返回给前端

        .hgetall(_):得到菜的fid,数量count

@RequestMapping("queryFromCart")
    public JSONResponse queryFromCart(String cid){
        //3.返回一堆篮子
        //篮子里现在有每道菜的:Food属性,数量和金额
        //传到前端的第二个data就是篮子是一个数组
        List<Lanzi> lanzis = new ArrayList<>();
        RedisUtil ru = RedisUtil.getRedisUtil();
        //1.foodid num 取
        Map<String, String> map = ru.hgetall(cid);
        //横着切
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> kv:entries){
            String fid = kv.getKey();
            String num = kv.getValue();
            //2.取了之后怎么存?造个篮子,拿个篮子存 篮子:Food food,int count,Double sum
                //其中总价是计算之后得到的
                /*getSum(){
                  return count*food.getNowPrice();
                  }*/
            //引入FoodService
            //篮子就是每道菜,每次造一个菜篮子对象
            Lanzi lz = new Lanzi();
            //这个fid是是前面存进去的fid现在又取出来
            //queryFoodById:根据一道菜的id查单道菜的food,foodtype,pic
            lz.setFood(foodService.queryFoodById(Integer.parseInt(fid)));
            lz.setCount(Integer.parseInt(num));
            lanzis.add(lz);
        }
        return lanzis.size()>0?ResultStatus.suc(lanzis):ResultStatus.error("没有篮子");
    }

返回的数据

{
    "code": 200,
    "msg": "success",
    "data": [
        {
            "food": {
                "id": 19,
                "fname": "132312",
                "beforeprice": 2131.0,
                "nowprice": 213.0,
                "type": 1,
                "tip": "123",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/bf14159a0ed243c2a5daf859d11c18e9.webp",
                    "realname": "蝴蝶.webp",
                    "uploadtime": "2023-07-23",
                    "foodid": 19,
                    "flag": 1
                },
                "types": {
                    "id": 19,
                    "ftname": "鲁菜",
                    "info": "这是鲁菜"
                }
            },
            "count": 1,
            "sum": 213.0
        },
        {
            "food": {
                "id": 14,
                "fname": "麦子",
                "beforeprice": 123.0,
                "nowprice": 123.0,
                "type": 1,
                "tip": "2312",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/b1140ea9486b4b72b5435e277ab08323.jpg",
                    "realname": "麦子.jpg",
                    "uploadtime": "2023-07-23",
                    "foodid": 14,
                    "flag": 1
                },
                "types": {
                    "id": 14,
                    "ftname": "鲁菜",
                    "info": "这是鲁菜"
                }
            },
            "count": 2,
            "sum": 246.0
        },
        {
            "food": {
                "id": 16,
                "fname": "光膀子",
                "beforeprice": 333.0,
                "nowprice": 123.0,
                "type": 2,
                "tip": "jklj",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/3725696a7ed84698953d397ce405d095.jpg",
                    "realname": "光膀子.jpg",
                    "uploadtime": "2023-07-23",
                    "foodid": 16,
                    "flag": 1
                },
                "types": {
                    "id": 16,
                    "ftname": "川菜",
                    "info": "这是川菜"
                }
            },
            "count": 1,
            "sum": 123.0
        },
        {
            "food": {
                "id": 17,
                "fname": "蝴蝶",
                "beforeprice": 9809.0,
                "nowprice": 5687.0,
                "type": 3,
                "tip": "见识到了",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/bf14159a0ed243c2a5daf859d11c18e9.webp",
                    "realname": "蝴蝶.webp",
                    "uploadtime": "2023-07-23",
                    "foodid": 17,
                    "flag": 1
                },
                "types": {
                    "id": 17,
                    "ftname": "粤菜",
                    "info": "这是粤菜"
                }
            },
            "count": 1,
            "sum": 5687.0
        },
        {
            "food": {
                "id": 18,
                "fname": "瀑布",
                "beforeprice": 11.0,
                "nowprice": 1111.0,
                "type": 2,
                "tip": "1",
                "idShelve": 0,
                "pics": {
                    "id": 0,
                    "savepath": "/files/bf14159a0ed243c2a5daf859d11c18e9.webp",
                    "realname": "蝴蝶.webp",
                    "uploadtime": "2023-07-23",
                    "foodid": 18,
                    "flag": 1
                },
                "types": {
                    "id": 18,
                    "ftname": "川菜",
                    "info": "这是川菜"
                }
            },
            "count": 1,
            "sum": 1111.0
        }
    ]
}

修改购物车中菜的数量

        需要拿着用户的cid,菜的fid,菜的数量去修改

        每次记得从redis里重新获取新数据

updateCount(lz){
    console.log('lz id:',lz)
    let cusid = window.sessionStorage.getItem("cusid")
    if (cusid) {                                            
    this.$ajax.post('/cus/updateCount','cid='+cusid+'&fid='+lz.food.id+'&count='+lz.count).then                        )resp=>{
    if (resp.data.code===200) {
        //每次修改完重新从redis取最新的数据,刷新页面数据
         this.queryFromCart()
    }
        }).catch(error=>{
            console.log('error:',error)
        })
    }
},

        后端

        如果count数量=0,==>.hdel(_,_):删去这道菜

        如果count数量不等于0==>.hset(_,_,_):加上新数量

@RequestMapping("/updateCount")
    public JSONResponse updateCount(String cid,String fid,String count){
        RedisUtil ru = RedisUtil.getRedisUtil();
        if (count.equals("0") || Integer.parseInt(count)==0){
            //根据key,value(key)删去数据
            ru.hdel(cid,fid);
        }else {
            //加上数
            ru.hset(cid,fid,count);
        }
        return ResultStatus.suc("修改成功");
    }

触发复选框事件

        添加表格子项(type="selection"),table组件添加@selection-change="changeSelection"

<el-table @selection-change="changeSelection" :data="tableData" border stripe style="width: 100%">
    <el-table-column type="selection"></el-table-column>
</el-table>

        复选框触发事件方法

//复选框触发事件
changeSelection(v){
    this.selections=v
},

带着选中的几道菜去订单页

        遍历selection这个集合(需要实例化),加菜的"id,"一直加到最后一个,减去最后一个逗号",",赋值给一个变量ids,ids带着这一堆菜的id通过路由发送到订单页,路由query的传值方式

jumpToOrders(){
    if (this.selections && this.selections.length>0) {
    let ids=""
    this.selections.forEach(lz=>{
        ids+=lz.food.id+","
    })
    ids=ids.substring(0,ids.length-1)
    this.$router.push({path:'/orders',
        query:{
            ids:ids
        }
    })
    }else{
        this.$message.warning("请至少选择一条")
    }
},

订单页带着cusid查询默认地址

因为查询后的地址需要显示为省-市-区,而原来的Address表里有没有这个属性,所以创建了一个Vo,给他加上了这个属性,查询全部地址类似,只是没有判断defaultAddress=#{1}

//查询默认地址
    @RequestMapping("/queryDefaultAddress")
    public JSONResponse queryDefaultAddress(int cusid){
        AddressVo vo = service.queryDefaultAddress(cusid);
        return vo!=null && vo.getPca()!=null?ResultStatus.suc(vo):ResultStatus.error("默认地址查询失败");
    }

默认地址,全部地址

        不过有许多个默认地址,需要用一个addressVo的数组来接

//查询默认地址
    @RequestMapping("/queryDefaultAddress")
    public JSONResponse queryDefaultAddress(int cusid){
        AddressVo vo = service.queryDefaultAddress(cusid);
        return vo!=null && vo.getPca()!=null?ResultStatus.suc(vo):ResultStatus.error("默认地址查询失败");
    }
    //查询全部地址
    @RequestMapping("/queryAllAddressById")
    public JSONResponse queryAllAddressById(int cusid){
        List<AddressVo> vo = service.queryAllAddressById(cusid);
        return vo!=null && vo.size()>0?ResultStatus.suc(vo):ResultStatus.error("默认地址查询失败");
    }

mybatis

<select id="queryAddressById" resultType="com.etoak.rst.customer.vo.AddressVo">
        select aid as id,cusid,concat_ws('-',pro.name,city.name,area.name) as pca,info,flag,defaultaddress,receiver,phone
        from rst_address a
        left join locations pro on pro.id=a.proid
        left join locations city on city.id=a.cityid
        left join locations area on area.id=a.areaid
        where cusid=#{cusid} and defaultaddress=1
</select>

 返回的数据

{
    "code": 200,
    "msg": "success",
    "data": {
        "id": 1,
        "cusid": 1,
        "proid": 0,
        "cityid": 0,
        "areaid": 0,
        "info": "山大北路",
        "flag": "公司",
        "defaultaddress": 1,
        "receiver": "张三",
        "phone": "17865502330",
        "enable": 0,
        "pca": "山东省-济南市-市中区"
    }
}

返回的数据为

购物车界面

返回的数据为

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值