day18【前台】订单
1、搭建环境
1.1、引入依赖
- 在
order-consumer
工程中引入所需依赖
<dependencies>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding17-member-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入springboot&redis整合场景 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 引入springboot&springsession整合场景 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
1.2、创建yml配置文件
server:
port: 6000
spring:
application:
name: atguigu-crowd-order
thymeleaf:
prefix: classpath:/templates/
suffix: .html
redis:
host: 192.168.152.129
session:
store-type: redis
eureka:
client:
service-url:
defaultZone: http://localhost:1000/eureka
1.3、创建主启动类
@EnableFeignClients
:启用Feign
客户端功能@EnableDiscoveryClient
:启用服务注册发现功能
// 启用Feign客户端功能
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class CrowdMainClass {
public static void main(String[] args) {
SpringApplication.run(CrowdMainClass.class, args);
}
}
1.4、配置zuul路由规则
- 配置
atguigu-crowd-order
的路由规则
zuul:
ignored-services: "*"
sensitive-headers: "*" # 在Zuul向其他微服务重定向时保持原本头信息(请求头、响应头)
routes:
crowd-portal:
service-id: atguigu-crowd-auth
path: /** # 这里一定要使用两个“*”号,不然“/”路径后面的多层路径将无法访问
crowd-project:
service-id: atguigu-crowd-project
path: /project/** # 这里一定要使用两个“*”号,不然“/”路径后面的多层路径将无法访问
crowd-order:
service-id: atguigu-crowd-order
path: /order/**
2、订单建模
2.1、实体类结构
2.2、物理建模
2.2.1、订单表
CREATE TABLE `project_crowd`.`t_order` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`order_num` CHAR(100) COMMENT '订单号',
`pay_order_num` CHAR(100) COMMENT '支付宝流水号',
`order_amount` DOUBLE (10, 5) COMMENT '订单金额',
`invoice` INT COMMENT '是否开发票(0 不开, 1 开) ',
`invoice_title` CHAR(100) COMMENT '发票抬头',
`order_remark` CHAR(100) COMMENT '订单备注',
`address_id` CHAR(100) COMMENT '收货地址 id',
PRIMARY KEY (`id`)
) ;
2.2.2、收货地址表
CREATE TABLE `project_crowd`.`t_address`
(
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`receive_name` CHAR(100) COMMENT '收件人',
`phone_num` CHAR(100) COMMENT '手机号',
`address` CHAR(200) COMMENT '收货地址',
`member_id` INT COMMENT '用户 id',
PRIMARY KEY (`id`)
) ;
2.2.3、项目信息表
CREATE TABLE `project_crowd`.`t_order_project`
(
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`project_name` CHAR(200) COMMENT '项目名称',
`launch_name` CHAR(100) COMMENT '发起人',
`return_content` CHAR(200) COMMENT '回报内容',
`return_count` INT COMMENT '回报数量',
`support_price` INT COMMENT '支持单价',
`freight` INT COMMENT '配送费用',
`order_id` INT COMMENT '订单表的主键',
PRIMARY KEY (`id`)
) ;
3、逆向工程
3.1、逆向工程配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- mybatis-generator:generate -->
<context id="atguiguTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是;false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection
driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/project_crowd"
userId="root"
password="root">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL
和 NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成Entity类的路径 -->
<javaModelGenerator targetProject=".\src\main\java"
targetPackage="com.atguigu.crowd.entity.po">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:XxxMapper.xml映射文件生成的路径 -->
<sqlMapGenerator targetProject=".\src\main\java"
targetPackage="com.atguigu.crowd.mapper">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:Mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetProject=".\src\main\java"
targetPackage="com.atguigu.crowd.mapper">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 数据库表名字和我们的entity类对应的映射指定 -->
<table tableName="t_order" domainObjectName="OrderPO" />
<table tableName="t_address" domainObjectName="AddressPO" />
<table tableName="t_order_project" domainObjectName="OrderProjectPO" />
</context>
</generatorConfiguration>
3.2、执行逆向工程
3.3、资源归位
3.3.1、实体类
3.3.2、Mapper接口
3.3.3、Mapper映射文件
4、确认回报信息
4.1、跳转至支持页面
- 单击【支持】超链接跳转至支持页面,带上
projectId
和returnId
(会面编写SQL
才发现,原来并不需要携带projectId
,不过带了就带了吧)
<a th:href="'http://www.crowd.com/order/confirm/return/info/'+${detailProjectVO.projectId}+'/'+${return.returnId}" class="btn btn-warning btn-lg">支持</a>
4.2、创建VO
- 创建
OrderProjectVO
类:支持页面对应的VO
类,由于需要存入Redis
,该类必须是可序列化类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderProjectVO implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String projectName;
private String launchName;
private String returnContent;
private Integer returnCount;
private Integer supportPrice;
private Integer freight;
private Integer orderId;
private Integer signalPurchase;
private Integer purchase;
}
4.3、order-consumer调用接口
order-consumer
调用远程mysql-provider
微服务:- 获取订单回报页面的数据
- 并将查询到的数据存入
session
,以便后一页面使用
@Controller
public class OrderHandler {
@Autowired
private MySQLRemoteService mySQLRemoteService;
@RequestMapping("/confirm/return/info/{projectId}/{returnId}")
public String showReturnConfirmInfo(
@PathVariable("projectId") Integer projectId,
@PathVariable("returnId") Integer returnId,
HttpSession session) {
ResultEntity<OrderProjectVO> resultEntity =
mySQLRemoteService.getOrderProjectVORemote(projectId, returnId);
if(ResultEntity.SUCCESS.equals(resultEntity.getResult())) {
OrderProjectVO orderProjectVO = resultEntity.getData();
// 为了能够在后续操作中保持orderProjectVO数据,存入Session域
session.setAttribute("orderProjectVO", orderProjectVO);
}
return "confirm_return";
}
}
4.4、mysql-provider暴露接口
4.4.1、Handler层
- 调用
Service
层获取订单回报页面的数据
@RestController
public class OrderProviderHandler {
@Autowired
private OrderService orderService;
@RequestMapping("/get/order/project/vo/remote")
ResultEntity<OrderProjectVO> getOrderProjectVORemote(
@RequestParam("projectId") Integer projectId,
@RequestParam("returnId") Integer returnId) {
try {
OrderProjectVO orderProjectVO = orderService.getOrderProjectVO(projectId, returnId);
return ResultEntity.successWithData(orderProjectVO);
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
}
4.4.2、Service层
- 调用
Mapper
层获取订单回报页面的数据
@Service
@Transactional(readOnly = true)
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderProjectPOMapper orderProjectPOMapper;
@Override
public OrderProjectVO getOrderProjectVO(Integer projectId, Integer returnId) {
return orderProjectPOMapper.selectOrderProjectVO(returnId);
}
}
4.5、Mapper层编写SQL
4.5.1、Mapper接口
Mapper
接口中声明接口
OrderProjectVO selectOrderProjectVO(Integer returnId);
4.5.2、Mapper映射文件
t_project
表通过memberId
与t_member_launch_info
相关联t_project
表通过projectId
与t_return
相关联- 两个
LEFT JOIN
完事儿
<select id="selectOrderProjectVO" resultType="com.atguigu.crowd.entity.vo.OrderProjectVO">
SELECT DISTINCT
t_project.`project_name` projectName,
t_return.`content` returnContent,
t_member_launch_info.`description_simple` launchName,
t_return.`supportmoney` supportPrice,
t_return.`freight` freight,
t_return.`count` returnCount,
t_return.`signalpurchase` signalPurchase,
t_return.`purchase` purchase
FROM t_project
LEFT JOIN t_member_launch_info ON t_project.memberid=t_member_launch_info.memberid
LEFT JOIN t_return ON t_project.id=t_return.projectid
WHERE t_return.id=#{returnId}
</select>
- 不加限定条件,
LEFT JOIN
得到的结果
SELECT *
FROM t_project
LEFT JOIN t_member_launch_info ON t_project.memberid=t_member_launch_info.memberid
LEFT JOIN t_return ON t_project.id=t_return.projectid
4.5.3、关于Left Join
t_role
表:角色表
t_admin
表:管理员表
inner_admin_role
表:管理员、角色中间表
-
目标一:查询拥有指定
roleId
的管理员信息- 不加查询条件(
Left Join
:坐标所有数据都会出现在结果集中,连接结果表中没有值的字段以null
填充)
SELECT * FROM t_admin LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id`
- 查询所有字段
SELECT * FROM t_admin LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id` WHERE inner_admin_role.`role_id` = 239
- 去除多余字段:
adminId
和roleId
SELECT t_admin.`id`, t_admin.`login_acct`, t_admin.`user_pswd`, t_admin.`user_name`, t_admin.`email`, t_admin.`create_time` FROM t_admin LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id` WHERE inner_admin_role.`role_id` = 239
- 不加查询条件(
-
查询拥有指定
roleId
的管理员信息及其角色信息- 不加限制条件(
Left Join
:坐标所有数据都会出现在结果集中,连接结果表中没有值的字段以null
填充)
SELECT * FROM t_admin LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id` LEFT JOIN t_role ON t_role.`id` = inner_admin_role.`role_id`
- 查询所有字段
SELECT * FROM t_admin LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id` LEFT JOIN t_role ON t_role.`id` = inner_admin_role.`role_id` WHERE inner_admin_role.`role_id` = 239
- 去除多余字段
SELECT t_admin.`id`, t_admin.`login_acct`, t_admin.`user_pswd`, t_admin.`user_name`, t_admin.`email`, t_admin.`create_time`, t_role.`id`, t_role.`name` FROM t_admin LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id` LEFT JOIN t_role ON t_role.`id` = inner_admin_role.`role_id` WHERE inner_admin_role.`role_id` = 239
- 不加限制条件(
4.6、api声明远程调用接口
api
中的方法声明部分需与mysql-provider
的Handler
方法一致
@RequestMapping("/get/order/project/vo/remote")
ResultEntity<OrderProjectVO> getOrderProjectVORemote(@RequestParam("projectId") Integer projectId, @RequestParam("returnId") Integer returnId);
4.7、确认回报页面
1、页面显示数据
<div class="col-md-12 column">
<table class="table table-bordered"
style="text-align: center;">
<thead>
<tr style="background-color: #ddd;">
<td>项目名称</td>
<td>发起人</td>
<td width="300">回报内容</td>
<td width="80">回报数量</td>
<td>支持单价</td>
<td>配送费用</td>
</tr>
</thead>
<tbody>
<tr>
<td th:text="${session.orderProjectVO.projectName}">活性富氢净水直饮机</td>
<td th:text="${session.orderProjectVO.launchName}">深圳市博实永道电子商务有限公司</td>
<td th:text="${session.orderProjectVO.returnContent}">每满1750人抽取一台活性富氢净水直饮机,至少抽取一台。抽取名额(小数点后一位四舍五入)=参与人数÷1750人,由苏宁官方抽取。</td>
<td><input id="returnCountInput" type="text" class="form-control"
style="width: 60px;" th:value="${session.orderProjectVO.returnCount}"></td>
<td style="color: #F60" th:text="${session.orderProjectVO.supportPrice}">¥ 1.00</td>
<td th:if="${session.orderProjectVO.freight == 0}">免运费</td>
<td th:if="${session.orderProjectVO.freight != 0}" th:text="${session.orderProjectVO.freight}">免运费</td>
</tr>
</tbody>
</table>
<div style="float: right;">
<p>
总价(含运费):<span id="totalAmount" style="font-size: 16px; color: #F60;">¥[[${session.orderProjectVO.returnCount*session.orderProjectVO.supportPrice}]]</span>
</p>
<button id="submitBtn" type="button" class="btn btn-warning btn-lg"
style="float: right;">
<i class="glyphicon glyphicon-credit-card"></i> 去结算
</button>
</div>
</div>
2、修改商品数量
var signalPurchase = [[${session.orderProjectVO.signalPurchase}]];
var purchase = [[${session.orderProjectVO.purchase}]];
$('#myTab a').click(function(e) {
e.preventDefault()
$(this).tab('show')
});
$("#returnCountInput").change(function(){
var returnCount = $.trim($(this).val());
if(returnCount == null || returnCount == "") {
alert("请输入有效数据!");
$(this).val(this.defaultValue);
return ;
}
if(signalPurchase == 1 && returnCount > purchase) {
alert("不能超过限购数量!");
return ;
}
var supportPrice = [[${session.orderProjectVO.supportPrice}]];
$("#totalAmount").text("¥"+(supportPrice * returnCount));
});
3、提交表单
$("#submitBtn").click(function(){
var returnCount = $("#returnCountInput").val();
window.location.href = "order/confirm/order/"+returnCount;
});
4.8、测试
5、确认订单信息
5.1、创建VO
- 创建
AddressVO
类:对应页面上的地址信息,由于AddressVO
类的对象需要存入Redis
缓存中,该类必须支持序列化
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AddressVO implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String receiveName;
private String phoneNum;
private String address;
private Integer memberId;
}
5.2、回显确认订单页面
5.2.1、order-consumer调用接口
- 点击【确认回报信息】页面中的【去结算】按钮,将回报数量提交至后端
Handler
,所以,后端Handler
方法需要做如下处理:- 将表单提交的回报数量设置到
session
域的OrderProjectVO
对象中 - 从
session
域中获取memberId
,查询用户的收货地址(List<AddressVO>
)
- 将表单提交的回报数量设置到
@RequestMapping("/confirm/order/{returnCount}")
public String showConfirmOrderInfo(
@PathVariable("returnCount") Integer returnCount,
HttpSession session) {
// 1.把接收到的回报数量合并到Session域
OrderProjectVO orderProjectVO = (OrderProjectVO) session.getAttribute("orderProjectVO");
orderProjectVO.setReturnCount(returnCount);
session.setAttribute("orderProjectVO", orderProjectVO);
// 2.获取当前已登录用户的id
MemberLoginVO memberLoginVO = (MemberLoginVO) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER);
Integer memberId = memberLoginVO.getId();
// 3.查询目前的收货地址数据
ResultEntity<List<AddressVO>> resultEntity = mySQLRemoteService.getAddressVORemote(memberId);
if(ResultEntity.SUCCESS.equals(resultEntity.getResult())) {
List<AddressVO> list = resultEntity.getData();
session.setAttribute("addressVOList", list);
}
return "confirm_order";
}
5.2.2、mysql-provider暴露接口
1、Handler层
- 调用
Service
层,获取用户地址信息
@RequestMapping("/get/address/vo/remote")
ResultEntity<List<AddressVO>> getAddressVORemote(@RequestParam("memberId") Integer memberId) {
try {
List<AddressVO> addressVOList = orderService.getAddressVOList(memberId);
return ResultEntity.successWithData(addressVOList);
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
2、Service层
- 调用
Mapper
层,获取用户地址信息(将PO
对象转为VO
对象,用于页面显示)
@Autowired
private AddressPOMapper addressPOMapper;
@Override
public List<AddressVO> getAddressVOList(Integer memberId) {
AddressPOExample example = new AddressPOExample();
example.createCriteria().andMemberIdEqualTo(memberId);
List<AddressPO> addressPOList = addressPOMapper.selectByExample(example);
List<AddressVO> addressVOList = new ArrayList<AddressVO>();
for (AddressPO addressPO : addressPOList) {
AddressVO addressVO = new AddressVO();
BeanUtils.copyProperties(addressPO, addressVO);
addressVOList.add(addressVO);
}
return addressVOList;
}
5.2.3、api声明远程调用接口
api
工程中声明远程调用接口
@RequestMapping("/get/address/vo/remote")
ResultEntity<List<AddressVO>> getAddressVORemote(@RequestParam("memberId") Integer memberId);
5.3、确认订单页面
5.3.1、页面显示数据
1、收货地址
<div class="col-md-12 column" style="padding: 0 120px;">
<div th:if="${#strings.isEmpty(session.addressVOList)}">尚未创建收货地址</div>
<div th:if="${not #strings.isEmpty(session.addressVOList)}">
<div th:each="address : ${session.addressVOList}" class="radio">
<label> <input type="radio" name="addressId" th:value="${address.id}"
id="optionsRadios1"/> [[${address.receiveName}]]
[[${address.phoneNum}]] [[${address.address}]]
</label>
</div>
</div>
<div class="radio">
<label> <input type="radio" name="optionsRadios"
id="optionsRadios2" value="option2"> 新地址
</label>
</div>
<div
style="border: 10px solid #f60; border-bottom-color: #eceeef; border-width: 10px; width: 20px; margin-left: 20px; margin-top: -20px; border-left-color: rgba(221, 221, 221, 0); border-top-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);"></div>
<div class="panel panel-default"
style="border-style: dashed; background-color: #eceeef">
<div class="panel-body">
<div class="col-md-12 column">
<form action="order/save/address" method="post" class="form-horizontal">
<input type="hidden" name="memberId" th:value="${session.loginMember.id}" />
<div class="form-group">
<label class="col-sm-2 control-label">收货人(*)</label>
<div class="col-sm-10">
<input type="text" name="receiveName" class="form-control"
style="width: 200px;" placeholder="姓名:xxxx">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">手机(*)</label>
<div class="col-sm-10">
<input class="form-control" name="phoneNum" type="text"
style="width: 200px;" placeholder="请填写11位手机号码"></input>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">地址(*)</label>
<div class="col-sm-10">
<input class="form-control" name="address" type="text"
style="width: 400px;" placeholder="请填写11位手机号码"></input>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<button type="submit" class="btn btn-primary">确认配送信息</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
2、发票信息
<div class="container-fluid">
<div class="row clearfix">
<div class="col-md-12 column">
<blockquote
style="border-left: 5px solid #f60; color: #f60; padding: 0 0 0 20px;">
<b> 发票信息 </b>
</blockquote>
</div>
<div class="col-md-12 column" style="padding: 0 120px;">
<div class="radio">
<label> <input type="radio" name="optionsRadios1"
id="optionsRadios1" value="option1" checked> 无需发票
</label>
</div>
<div class="radio">
<label> <input type="radio" name="optionsRadios1"
id="optionsRadios2" value="option2"> 需要发票
</label>
</div>
<div
style="border: 10px solid #f60; border-bottom-color: #eceeef; border-width: 10px; width: 20px; margin-left: 20px; margin-top: -20px; border-left-color: rgba(221, 221, 221, 0); border-top-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);"></div>
<div class="panel panel-default"
style="border-style: dashed; background-color: #eceeef">
<div class="panel-body">
<div class="col-md-12 column">
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">发票抬头(*)</label>
<div class="col-sm-10">
<input type="text" class="form-control"
style="width: 200px;" placeholder="个人">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
3、项目信息
<div class="col-md-12 column">
<table class="table table-bordered"
style="text-align: center;">
<thead>
<tr style="background-color: #ddd;">
<td>项目名称</td>
<td>发起人</td>
<td width="300">回报内容</td>
<td width="80">回报数量</td>
<td>支持单价</td>
<td>配送费用</td>
</tr>
</thead>
<tbody>
<tr>
<td th:text="${session.orderProjectVO.projectName}">活性富氢净水直饮机</td>
<td th:text="${session.orderProjectVO.launchName}">深圳市博实永道电子商务有限公司</td>
<td th:text="${session.orderProjectVO.returnContent}">每满1750人抽取一台活性富氢净水直饮机,至少抽取一台。抽取名额(小数点后一位四舍五入)=参与人数÷1750人,由苏宁官方抽取。</td>
<td th:text="${session.orderProjectVO.returnCount}">55</td>
<td style="color: #F60" th:text="${session.orderProjectVO.supportPrice}">¥ 1.00</td>
<td th:if="${session.orderProjectVO.freight == 0}">免运费</td>
<td th:if="${session.orderProjectVO.freight != 0}" th:text="${session.orderProjectVO.freight}">免运费</td>
</tr>
</tbody>
</table>
</div>
4、账单
<div class="col-md-12 column">
<div class="alert alert-warning alert-dismissable"
style="text-align: right; border: 2px solid #ffc287;">
<ul style="list-style: none;">
<li style="margin-top: 10px;">支持金额:<span
style="color: red;">¥[[${session.orderProjectVO.returnCount*session.orderProjectVO.supportPrice}]]</span></li>
<li style="margin-top: 10px;">配送费用:<span
style="color: red;">¥[[${session.orderProjectVO.freight}]]</span></li>
<li style="margin-top: 10px; margin-bottom: 10px;"><h2>
支付总金额:<span style="color: red;">¥[[${session.orderProjectVO.returnCount*session.orderProjectVO.supportPrice+session.orderProjectVO.freight}]]</span>
</h2></li>
<li
style="margin-top: 10px; padding: 5px; border: 1px solid #F00; display: initial; background: #FFF;">
<i class="glyphicon glyphicon-info-sign"></i> <strong>您需要先
<a href="#address">设置配送信息</a> ,再提交订单
</strong>
</li>
<li style="margin-top: 10px;">
请在下单后15分钟内付款,否则您的订单会被自动关闭。</li>
<li style="margin-top: 10px;">
<button id="payButton" disabled="disabled" type="button"
class="btn btn-warning btn-lg"
onclick="window.location.href='pay-step-3.html'">
<i class="glyphicon glyphicon-credit-card"></i> 立即付款
</button>
</li>
<li style="margin-top: 10px;">
<div class="checkbox">
<label>
<input id="knowRoleCheckBox" type="checkbox">我已了解风险和规则
</label>
</div>
</li>
</ul>
</div>
</div>
5.4、新建收货地址
5.4.1、提交收货地址
- 提交收货地址时,带上
memberId
,这样才能知道是哪个用户的收货地址
<form action="order/save/address" method="post" class="form-horizontal">
<input type="hidden" name="memberId" th:value="${session.loginMember.id}" />
<div class="form-group">
<label class="col-sm-2 control-label">收货人(*)</label>
<div class="col-sm-10">
<input type="text" name="receiveName" class="form-control"
style="width: 200px;" placeholder="姓名:xxxx">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">手机(*)</label>
<div class="col-sm-10">
<input class="form-control" name="phoneNum" type="text"
style="width: 200px;" placeholder="请填写11位手机号码"></input>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">地址(*)</label>
<div class="col-sm-10">
<input class="form-control" name="address" type="text"
style="width: 400px;" placeholder="请填写11位手机号码"></input>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<button type="submit" class="btn btn-primary">确认配送信息</button>
</div>
</div>
</form>
5.4.2、order-consumer调用接口
- 调用
mysql-provider
保存地址信息,并重定向至当前页面,需带上returnCount
(回报数量)
private Logger logger = LoggerFactory.getLogger(OrderHandler.class);
@RequestMapping("/save/address")
public String saveAddress(AddressVO addressVO, HttpSession session) {
// 1.执行地址信息的保存
ResultEntity<String> resultEntity = mySQLRemoteService.saveAddressRemote(addressVO);
logger.debug("地址保存处理结果:"+resultEntity.getResult());
// 2.从Session域获取orderProjectVO对象
OrderProjectVO orderProjectVO = (OrderProjectVO) session.getAttribute("orderProjectVO");
// 3.从orderProjectVO对象中获取returnCount
Integer returnCount = orderProjectVO.getReturnCount();
// 4.重定向到指定地址,重新进入确认订单页面
return "redirect:http://www.crowd.com/order/confirm/order/"+returnCount;
}
5.4.3、mysql-provider暴露接口
1、Handler层
- 调用
Service
层保存用户收货地址
@RequestMapping("/save/address/remote")
public ResultEntity<String> saveAddressRemote(@RequestBody AddressVO addressVO) {
try {
orderService.saveAddress(addressVO);
return ResultEntity.successWithoutData();
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
2、Service层
- 将
addressVO
对象转换为addressPO
对象,保存至数据库
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Override
public void saveAddress(AddressVO addressVO) {
AddressPO addressPO = new AddressPO();
BeanUtils.copyProperties(addressVO, addressPO);
addressPOMapper.insert(addressPO);
}
5.4.4、api声明远程调用接口
- 在
api
工程中i声明远程调用接口,由于需要传输AddressVO
对象,需要添加@RequestBody
注解:以`json字符串格式进行传输
@RequestMapping("/save/address/remote")
ResultEntity<String> saveAddressRemote(@RequestBody AddressVO addressVO);
5.4.5、测试
- 收货地址回显正常
5.5、立即付款是否生效
5.5.1、代码
- 勾选用户协议,才能付款
<!-- 页面按钮 -->
<li style="margin-top: 10px;">
<button id="payButton" disabled="disabled" type="button"
class="btn btn-warning btn-lg"
onclick="window.location.href='pay-step-3.html'">
<i class="glyphicon glyphicon-credit-card"></i> 立即付款
</button>
</li>
<li style="margin-top: 10px;">
<div class="checkbox">
<label>
<input id="knowRoleCheckBox" type="checkbox">我已了解风险和规则
</label>
</div>
</li>
<!-- javascript代码 -->
$("#knowRoleCheckBox").click(function(){
var currentStatus = this.checked;
if(currentStatus) {
$("#payButton").prop("disabled", "");
}else{
$("#payButton").prop("disabled","disabled");
}
});
5.5.2、测试
- 【立即付款】按钮失效
- 【立即付款】按钮生效