1. 程式人生 > >樂優商城(三十八)——訂單微服務

樂優商城(三十八)——訂單微服務

目錄

五、地址管理

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 COMMENT '地址id\r\n',
  `name` varchar(50) DEFAULT NULL COMMENT '收貨人姓名',
  `phone` varchar(50) NOT NULL COMMENT '收貨人電話',
  `zip_code` varchar(50) DEFAULT NULL COMMENT '郵編',
  `state` varchar(50) DEFAULT NULL COMMENT '省份',
  `city` varchar(50) DEFAULT NULL COMMENT '市',
  `district` varchar(50) DEFAULT NULL COMMENT '區/縣',
  `address` varchar(100) DEFAULT NULL COMMENT '詳細地址',
  `default` tinyint(1) DEFAULT NULL COMMENT '1:預設地址  0:非預設地址',
  `userId` bigint(20) NOT NULL COMMENT '使用者id',
  `label` varchar(20) DEFAULT NULL COMMENT '地址標籤',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `userId` (`userId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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;
    });
}