目录

五、地址管理

5.1 页面效果

5.2 数据库表设计

5.3 页面优化

5.3.1 在data中定义数据

5.3.2 模态框

5.3.3 方法绑定

5.3.4 效果展示

5.4 后台接口

5.4.1 实体类

5.4.2 Controller

5.4.3 Mapper

5.4.4 Service

5.5 接口测试

5.5.1 新增地址

5.5.2 查询地址

5.5.3 修改地址

5.5.4 删除地址

5.5.5 根据地址id查询地址

5.6 页面改造

5.6.1 地址查询

5.6.2 默认地址

5.6.3 地址新增

5.6.4 地址修改

5.6.5 地址删除


五、地址管理

5.1 页面效果

点击“新增收货地址”和“编辑”都会弹出模态框,如下所示:

5.2 数据库表设计

CREATE TABLE `tb_address`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '地址id',
  `user_id` bigint(20) NULL DEFAULT NULL COMMENT '用户id',
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收货人姓名',
  `phone` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收货人电话',
  `zip_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮编',
  `state` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '省份',
  `city` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '市',
  `district` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '区/县',
  `address` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '详细地址',
  `default_address` tinyint(1) NULL DEFAULT NULL COMMENT '1:默认地址  0:非默认地址',
  `label` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址标签',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `userId`(`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

5.3 页面优化

5.3.1 在data中定义数据

5.3.2 模态框

改造模态框,绑定数据

<div class="modal-dialog">
<div class="modal-content">
    <div class="modal-header">
    <button type="button" data-dismiss="modal" aria-hidden="true" class="sui-close">×</button>
    <h4 id="myModalLabel" class="modal-title">{{isEdit ? "编辑" : "添加"}}收货地址</h4>
    </div>
    <div class="modal-body">
    <form action="" class="sui-form form-horizontal">
        <div class="control-group">
            <label class="control-label">收货人:</label>
            <div class="controls">
                <input type="text" v-model="addressForm.name" class="input-medium">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label">联系电话:</label>
            <div class="controls">
                <input type="text" v-model="addressForm.phone" class="input-medium">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label">省:</label>
            <div class="controls">
                <input type="text" v-model="addressForm.state" class="input-medium">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label">市:</label>
            <div class="controls">
                <input type="text" v-model="addressForm.city" class="input-medium">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label">区/县:</label>
            <div class="controls">
                <input type="text" v-model="addressForm.district" class="input-medium">
            </div>
        </div>

        <div class="control-group">
            <label class="control-label">邮编:</label>
            <div class="controls">
                <input type="text" v-model="addressForm.zipCode" class="input-medium">
            </div>
        </div>
            
        <div class="control-group">
            <label class="control-label">详细地址:</label>
            <div class="controls">
                <input type="text" v-model="addressForm.address" class="input-large">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label">地址标签:</label>
            <div class="controls">
                <select class="select" v-model="addressForm.label">
                    <option value="家">家</option>
                    <option value="公司">公司</option>
                    <option value="学校">学校</option>
                </select>
            </div>
        </div>
        <div class="control-group">
            <div  style="margin-left: 100px">
                <input type="checkbox" v-model="addressForm.defaultAddress" class="checkbox">设为默认收货地址
            </div>
        </div>

    </form>
    </div>
    <div class="modal-footer">
    <button type="button" @click="addressSave" data-ok="modal" class="sui-btn btn-primary btn-large">确定</button>
    <button type="button" data-dismiss="modal" class="sui-btn btn-default btn-large">取消</button>
    </div>
</div>
</div>

5.3.3 方法绑定

新增地址:

修改地址:

模态框数据提交:

关闭模态框(两个地方):

5.3.4 效果展示

点击确定,查看提交的数据:

 

5.4 后台接口

5.4.1 实体类

package com.leyou.order.pojo;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

/**
 * @Author: 98050
 * @Time: 2018-10-30 23:08
 * @Feature: 收货地址
 */
@Table(name = "tb_address")
public class Address {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 用户id
     */
    @NotNull
    private Long userId;

    /**
     * 收货人
     */
    private String name;

    /**
     * 收货电话
     */
    private String phone;

    /**
     * 邮编
     */
    private String zipCode;

    /**
     * 省
     */
    private String state;

    /**
     * 市
     */
    private String city;

    /**
     * 区/县
     */
    private String district;

    /**
     * 详细地址
     */
    private String address;

    /**
     * 是否是默认地址
     */
    private boolean defaultAddress;

    /**
     * 地址标签
     */
    private String label;
}

5.4.2 Controller

最基本的CRUD,没什么可说的,直接上代码。需要注意的是,因为配置了用户登录拦截器,需要的用户信息从后台获取。

package com.leyou.order.controller;

import com.leyou.order.pojo.Address;
import com.leyou.order.service.AddressService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * @Author: 98050
 * @Time: 2018-10-31 09:44
 * @Feature: 地址CRUD
 */
@RestController
@RequestMapping("address")
@Api("地址管理")
public class AddressController {

    @Autowired
    private AddressService addressService;

    /**
     * 创建收货地址
     * @return
     */
    @PostMapping
    @ApiOperation(value = "创建收货地址接口",notes = "创建地址")
    @ApiImplicitParam(name = "address",required = true,value = "地址对象")
    @ApiResponses({
            @ApiResponse(code = 201, message = "地址创建成功"),
            @ApiResponse(code = 500,message = "服务器异常")
    })
    public ResponseEntity<Void> addAddressByUserId(@RequestBody @Valid Address address){
        System.out.println(address.getDefaultAddress());
        this.addressService.addAddressByUserId(address);
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }

    /**
     * 根据用户id查询地址列表
     * @return
     */
    @GetMapping
    @ApiOperation(value = "查询收货地址接口,返回地址列表",notes = "查询地址")
    @ApiResponses({
            @ApiResponse(code = 200, message = "地址列表"),
            @ApiResponse(code = 404,message = "没有查询到结果"),
            @ApiResponse(code = 500,message = "服务器异常")
    })
    public ResponseEntity<List<Address>> queryAddressByUserId(){
        List<Address> addresses = this.addressService.queryAddressByUserId();
        if (addresses == null || addresses.size() == 0){
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }
        return ResponseEntity.ok(addresses);
    }

    /**
     * 修改收货地址
     * @param address
     * @return
     */
    @PutMapping
    @ApiOperation(value = "修改收货地址接口",notes = "修改地址")
    @ApiImplicitParam(name = "address", required=true, value = "地址对象")
    @ApiResponses({
            @ApiResponse(code = 204, message = "修改成功"),
            @ApiResponse(code = 500,message = "服务器异常")
    })
    public ResponseEntity<Void> updateAddressByUserId(@RequestBody Address address){
        this.addressService.updateAddressByUserId(address);
        return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
    }

    /**
     * 删除收货地址
     * @param addressId
     * @return
     */
    @DeleteMapping("{addressId}")
    @ApiOperation(value = "删除收货地址接口",notes = "创建地址")
    @ApiImplicitParam(name = "addressId", required=true, value = "地址id")
    @ApiResponses({
            @ApiResponse(code = 200, message = "地址删除成功"),
            @ApiResponse(code = 500,message = "服务器异常")
    })
    public ResponseEntity<Void> deleteAddress(@PathVariable("addressId") Long addressId){
        this.addressService.deleteAddress(addressId);
        return ResponseEntity.status(HttpStatus.OK).build();
    }

    @GetMapping("{addressId}")
    @ApiOperation(value = "根据id查询收货地址接口",notes = "查询地址")
    @ApiImplicitParam(name = "addressId", required=true, value = "地址id")
    @ApiResponses({
            @ApiResponse(code = 200, message = "查询成功"),
            @ApiResponse(code = 404, message = "查询失败"),
            @ApiResponse(code = 500,message = "服务器异常")
    })
    public ResponseEntity<Address> queryAddressById(@PathVariable("addressId") Long addressId){
        Address address = this.addressService.queryAddressById(addressId);
        if (address == null){
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }
        return ResponseEntity.ok(address);
    }
}

5.4.3 Mapper

package com.leyou.order.mapper;

import com.leyou.order.pojo.Address;
import tk.mybatis.mapper.common.Mapper;

/**
 * @Author: 98050
 * @Time: 2018-10-31 09:41
 * @Feature:
 */
public interface AddressMapper extends Mapper<Address> {
}

5.4.4 Service

接口

package com.leyou.order.service;

import com.leyou.order.pojo.Address;

import java.util.List;

/**
 * @Author: 98050
 * @Time: 2018-10-31 09:43
 * @Feature:
 */
public interface AddressService {
    /**
     * 删除地址
     * @param addressId
     */
    void deleteAddress(Long addressId);

    /**
     * 更新地址
     * @param address
     */
    void updateAddressByUserId(Address address);

    /**
     * 查询地址
     * @return
     */
    List<Address> queryAddressByUserId();

    /**
     * 新增收货地址
     * @param address
     */
    void addAddressByUserId(Address address);

    /**
     * 根据地址id查询地址
     * @param addressId
     * @return
     */
    Address queryAddressById(Long addressId);
}

实现

package com.leyou.order.service.impl;

import com.leyou.auth.entity.UserInfo;
import com.leyou.order.interceptor.LoginInterceptor;
import com.leyou.order.mapper.AddressMapper;
import com.leyou.order.pojo.Address;
import com.leyou.order.service.AddressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.List;

/**
 * @Author: 98050
 * @Time: 2018-10-31 09:44
 * @Feature:
 */
@Service
public class AddressServiceImpl implements AddressService {

    @Autowired
    private AddressMapper addressMapper;

    @Override
    public void deleteAddress(Long addressId) {
        UserInfo userInfo = LoginInterceptor.getLoginUser();
        Example example = new Example(Address.class);
        example.createCriteria().andEqualTo("userId",userInfo.getId()).andEqualTo("id",addressId);
        this.addressMapper.deleteByExample(example);
    }

    @Override
    public void updateAddressByUserId(Address address) {
        UserInfo userInfo = LoginInterceptor.getLoginUser();
        address.setUserId(userInfo.getId());
        this.addressMapper.updateByPrimaryKeySelective(address);

    }

    @Override
    public List<Address> queryAddressByUserId() {
        UserInfo userInfo = LoginInterceptor.getLoginUser();
        Example example = new Example(Address.class);
        example.createCriteria().andEqualTo("userId",userInfo.getId());
        return this.addressMapper.selectByExample(example);
    }

    @Override
    public void addAddressByUserId(Address address) {
        UserInfo userInfo = LoginInterceptor.getLoginUser();
        address.setUserId(userInfo.getId());
        this.addressMapper.insert(address);
    }

    @Override
    public Address queryAddressById(Long addressId) {
        UserInfo userInfo = LoginInterceptor.getLoginUser();
        Example example = new Example(Address.class);
        example.createCriteria().andEqualTo("id",addressId).andEqualTo("userId",userInfo.getId());
        return this.addressMapper.selectByExample(example).get(0);
    }
}

5.5 接口测试

在进行接口测试时,必须要设置cookie,假设用户已经登录。可以使用工具:Edit This Cookie

5.5.1 新增地址

{     
   "name":"王五",  
   "phone":"18834888888", 
   "zipCode":"123132", 
   "state":"陕西省",   
   "city":"西安市",  
   "district":"碑林区", 
   "address":"陕西省西安市碑林区", 
   "label":"学校", 
   "defaultAddress":true
}

结果:

查看数据库:

5.5.2 查询地址

结果:

5.5.3 修改地址

结果:

数据库:

5.5.4 删除地址

结果:

数据库:

5.5.5 根据地址id查询地址

结果:

5.6 页面改造

5.6.1 地址查询

在页面加载时,查询当前登录用户下所有地址信息。然后保存在可选地址列表addresses中进行渲染,查询地址时将默认地址放在第一位:

页面渲染:

<ul class="addr-detail">
    <li class="addr-item" v-for="(a,i) in addresses" :key="i">
        <div>
            <div :class="{con:true,name:true,selected:i === selectedAddress}"><a href="javascript:;" @click.stop="selectedAddress=i" >{{a.name}}<span title="点击取消选择"></span>&nbsp;</a></div>
            <div class="con address">{{a.state + a.city + a.district + a.address}} <span>{{a.phone}}</span>
                <span class="base" v-if="a.defaultAddress">默认地址</span>
                <span class="edittext">
                    <a data-toggle="modal" @click="editAddress(a.id)" data-target=".edit" data-keyboard="false" >编辑</a>&nbsp;&nbsp;
                    <a href="javascript:;" @click="deleteAddress(a.id)">删除</a></span>
            </div>
            <div class="clearfix"></div>
        </div>
    </li>
</ul>

效果:

5.6.2 默认地址

一个用户只设置一个默认地址,那么在新增和修改地址时就要做处理,如果新增或修改的地址被设置为默认地址,那么该用户下其它地址都是非默认地址,对AddressServiceImpl中进行修改:

新增方法:setDefaultAddress

public void setDefaultAddress(Address address){
        if (address.getDefaultAddress()){
            //如果将本地址设置为默认地址,那么该用户下的其他地址都应该是非默认地址
            List<Address> addressList = this.queryAddressByUserId();
            addressList.forEach(addressTemp -> {
                if (addressTemp.getDefaultAddress()){
                    addressTemp.setDefaultAddress(false);
                    this.addressMapper.updateByPrimaryKeySelective(addressTemp);
                }
            } );
        }
    }

5.6.3 地址新增

模态框打开,输入信息,然后点击保存。这里面保存修改二合一,通过isEdit来判断是修改还是新增:

addressSave(){
    //1.验证是否登录
    ly.verifyUser().then(() => {
        //2.登录,发起请求,保存或者修改地址
        if (this.isEdit === false) {
            //2.1新增
            ly.http.post("/address", this.addressForm).then(() => {
                //保存成功,重新加载数据
                this.loadData();
                //清空表单
                this.clear();
            }).catch()
        }else {
            //2.2 修改
            ly.http.put("/address", this.addressForm).then(() => {
                //修改成功,重新加载数据
                this.loadData();
                //清空表单
                this.clear();
            }).catch()
        }
    }).catch(() => {
        //3.未登录
        window.location.href = "/login.html?returnUrl=" + window.location.href;
    });
}

5.6.4 地址修改

当点击修改时,通过传入的地址id查询相应地址信息,然后回显到表单中

editAddress(id){
    this.isEdit = true;
    ly.verifyUser().then(() => {
        ly.http.get("address/"+id).then(({data}) => {
            this.addressForm = data;
        })
    }).catch(() => {
        window.location = "/login.html?returnUrl=" + window.location.href;
    })
},

5.6.5 地址删除

deleteAddress(id){
    ly.verifyUser().then(() => {
        ly.http.delete("/address/"+id).then(() => {
            this.loadData();
        })
    }).catch(() => {
        window.location.href = "/login.html?returnUrl=" + window.location.href;
    });
}

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐