尚医通-day14【创建订单】(内附源码)
页面预览
订单详情
订单列表
第01章-创建订单
生成订单分析
- 生成订单方法参数:就诊人id与 排班id
- 生成订单需要获取就诊人信息(微服务远程调用service-user)
- 获取排班信息与规则信息(微服务远程调用service-hosp)
- 下单后,通过接口去医院预约下单(httpclient远程调用医院端的接口)
- 下单成功更新排班信息并发送短信(向mq发送信息)
1、创建订单微服务
1.1、创建数据库
资料:资料>订单微服务>guigu_syt_order.sql
1.2、创建service-order微服务
在service模块下创建service-order模块
1.3、添加依赖
在service-order中添加依赖:
<dependencies>
<!--实体-->
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>model</artifactId>
<version>1.0</version>
</dependency>
<!--服务通用配置-->
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-util</artifactId>
<version>1.0</version>
</dependency>
<!--自定义安全模块-->
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>spring-security</artifactId>
<version>1.0</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--时间日期工具-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
1.4、使用代码生成器
找到service-util模块中的代码生成器,修改moduleName为order
,并执行,然后删除entity包,相关类中引入model模块中的类
1.5、创建配置文件
在server-order模块中resources目录下创建文件
application.yml
:
spring:
application:
name: service-order
profiles:
active: dev,redis
application-dev.yml
:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:com/atguigu/syt/order/mapper/xml/*.xml
server:
port: 8205
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
password: 123456
url: jdbc:mysql://localhost:3306/guigu_syt_order?characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
username: root
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
logging:
level:
root: info
file:
path: order
feign:
client:
config:
default:
connect-timeout: 2000 #连接建立的超时时长,单位是ms,默认1s
read-timeout: 2000 #处理请求的超时时间,单位是ms,默认为1s
sentinel:
enabled: true #开启Feign对Sentinel的支持
1.6、配置网关
在server-gateway中配置网关路由
- id: service-order
predicates: Path=/*/order/**
uri: lb://service-order
1.7、创建启动类
package com.atguigu.syt.order;
@SpringBootApplication
@ComponentScan(basePackages = {"com.atguigu"})
@EnableFeignClients("com.atguigu.syt")
public class ServiceOrderApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceOrderApplication.class, args);
}
}
2、获取就诊人接口
2.1、Controller
在service-user模块创建controller.inner包,创建InnerPatientController类
package com.atguigu.syt.user.controller.inner;
@Api(tags = "就诊人接口-供其他微服务远程调用")
@RestController
@RequestMapping("/inner/user/patient")
public class InnerPatientController {
@Resource
private PatientService patientService;
@ApiOperation("获取就诊人")
@ApiImplicitParam(name = "id",value = "就诊人id", required = true)
@GetMapping("/get/{id}")
public Patient getPatient(@PathVariable("id") Long id) {
return patientService.getById(id);
}
}
2.2、创建service-user-client模块
在service-client下创建service-user-client
在service-client
中添加依赖
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>model</artifactId>
<version>1.0</version>
</dependency>
2.3、创建Feign接口
在service-user-client中创建接口
package com.atguigu.syt.user.client;
@FeignClient(
value = "service-user",
contextId = "patientFeignClient",
fallback = PatientDegradeFeignClient.class)
public interface PatientFeignClient {
/**
* 获取就诊人
* @param id
* @return
*/
@GetMapping("/inner/user/patient/get/{id}")
Patient getPatient(@PathVariable Long id);
}
降级:
package com.atguigu.syt.user.client.impl;
@Component
public class PatientDegradeFeignClient implements PatientFeignClient {
@Override
public Patient getPatient(Long id) {
return null;
}
}
3、获取排班信息接口
3.1、Controller
在service-hosp模块创建controller.inner包,创建InnerScheduleController类
package com.atguigu.syt.hosp.controller.inner;
@Api(tags = "医院接口-供其他微服务远程调用")
@RestController
@RequestMapping("/inner/hosp/hospital")
public class InnerScheduleController {
@Resource
private ScheduleService scheduleService;
@ApiOperation("根据排班id获取预约下单数据")
@ApiImplicitParam(name = "scheduleId",value = "排班id", required = true)
@GetMapping("/getScheduleOrderVo/{scheduleId}")
public ScheduleOrderVo getScheduleOrderVo(@PathVariable String scheduleId) {
return scheduleService.getScheduleOrderVo(scheduleId);
}
}
3.2、Service
接口:ServiceScheduleService
/**
* 获取排班相关数据
* @param scheduleId
* @return
*/
ScheduleOrderVo getScheduleOrderVo(String scheduleId);
实现:ScheduleServiceImpl
@Override
public ScheduleOrderVo getScheduleOrderVo(String scheduleId) {
Schedule schedule = this.getDetailById(scheduleId);
String hosname = (String)schedule.getParam().get("hosname");
String depname = (String)schedule.getParam().get("depname");
ScheduleOrderVo scheduleOrderVo = new ScheduleOrderVo();
scheduleOrderVo.setHoscode(schedule.getHoscode()); //医院编号
scheduleOrderVo.setHosname(hosname); //医院名称
scheduleOrderVo.setDepcode(schedule.getDepcode()); //科室编号
scheduleOrderVo.setDepname(depname); //科室名称
scheduleOrderVo.setHosScheduleId(schedule.getHosScheduleId()); //医院端的排班主键
scheduleOrderVo.setAvailableNumber(schedule.getAvailableNumber()); //剩余预约数
scheduleOrderVo.setTitle(hosname + depname + "挂号费");
scheduleOrderVo.setReserveDate(schedule.getWorkDate()); //安排日期
scheduleOrderVo.setReserveTime(schedule.getWorkTime()); //安排时间(0:上午 1:下午)
scheduleOrderVo.setAmount(schedule.getAmount());//挂号费用
//获取预约规则相关数据
Hospital hospital = hospitalRepository.findByHoscode(schedule.getHoscode());
BookingRule bookingRule = hospital.getBookingRule();
String quitTime = bookingRule.getQuitTime();//退号时间
//退号实际时间(如:就诊前一天为-1,当天为0)
DateTime quitDay = new DateTime(schedule.getWorkDate()).plusDays(bookingRule.getQuitDay());//退号日期
DateTime quitDateTime = this.getDateTime(quitDay, quitTime);//可退号的具体的日期和时间
scheduleOrderVo.setQuitTime(quitDateTime.toDate());
return scheduleOrderVo;
}
3.3、创建service-hosp-client模块
在service-client下创建service-hosp-client
3.4、创建Feign接口
在service-hosp-client中创建接口
package com.atguigu.syt.hosp.client;
@FeignClient(
value = "service-hosp",
contextId = "scheduleFeignClient",
fallback = ScheduleDegradeFeignClient.class
)
public interface ScheduleFeignClient {
/**
* 根据排班id获取预约下单数据
* @param scheduleId
* @return
*/
@GetMapping("/inner/hosp/hospital/getScheduleOrderVo/{scheduleId}")
ScheduleOrderVo getScheduleOrderVo(@PathVariable("scheduleId") String scheduleId);
}
降级:
package com.atguigu.syt.hosp.client.impl;
@Component
public class ScheduleDegradeFeignClient implements ScheduleFeignClient {
@Override
public ScheduleOrderVo getScheduleOrderVo(String scheduleId) {
return null;
}
}
4、生成订单
4.1、service中引入依赖
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-user-client</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-hosp-client</artifactId>
<version>1.0</version>
</dependency>
4.2、Controller
在service-order中创建controller.front包,创建FrontOrderInfoController类,定义创建订单接口
package com.atguigu.syt.order.controller.front;
@Api(tags = "订单接口")
@RestController
@RequestMapping("/front/order/orderInfo")
public class FrontOrderInfoController {
@Resource
private OrderInfoService orderInfoService;
@Resource
private AuthContextHolder authContextHolder;
@ApiOperation("创建订单")
@ApiImplicitParams({
@ApiImplicitParam(name = "scheduleId",value = "排班id", required = true),
@ApiImplicitParam(name = "patientId",value = "就诊人id", required = true)})
@PostMapping("/auth/submitOrder/{scheduleId}/{patientId}")
public Result<Long> submitOrder(@PathVariable String scheduleId, @PathVariable Long patientId, HttpServletRequest request, HttpServletResponse response) {
authContextHolder.checkAuth(request, response);
Long orderId = orderInfoService.submitOrder(scheduleId, patientId);
return Result.ok(orderId);
}
}
4.3、Service
接口:OrderInfoService
/**
* 根据排班id和就诊人id创建订单
* @param scheduleId
* @param patientId
* @return 新订单id
*/
Long submitOrder(String scheduleId, Long patientId);
实现:OrderInfoServiceImpl
@Resource
private PatientFeignClient patientFeignClient;
@Resource
private ScheduleFeignClient scheduleFeignClient;
@Override
public Long submitOrder(String scheduleId, Long patientId) {
//就诊人数据:远程获取就诊人数据(openfeign)
Patient patient = patientFeignClient.getPatient(patientId);
if(patient == null) {
throw new GuiguException(ResultCodeEnum.PARAM_ERROR);
}
//获取医院排班相关数据
ScheduleOrderVo scheduleOrderVo = scheduleFeignClient.getScheduleOrderVo(scheduleId);
if(scheduleOrderVo == null) {
throw new GuiguException(ResultCodeEnum.PARAM_ERROR);
}
//SignInfoVo signInfoVo = hospitalFeignClient.getSignInfoVo(scheduleOrderVo.getHoscode());
SignInfoVo signInfoVo = new SignInfoVo();
signInfoVo.setSignKey("8af52af00baf6aec434109fc17164aae");
signInfoVo.setApiUrl("http://localhost:9998");
if(signInfoVo == null) {
throw new GuiguException(ResultCodeEnum.PARAM_ERROR);
}
if(scheduleOrderVo.getAvailableNumber() <= 0) {
throw new GuiguException(ResultCodeEnum.NUMBER_NO);
}
//创建订单对象
OrderInfo orderInfo = new OrderInfo();
//基本信息
String outTradeNo = UUID.randomUUID().toString().replace("-", "");
orderInfo.setOutTradeNo(outTradeNo); //订单号
orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus());//未支付
//就诊人数据
orderInfo.setPatientId(patientId);
orderInfo.setPatientPhone(patient.getPhone());
orderInfo.setPatientName(patient.getName());
orderInfo.setUserId(patient.getUserId());
//医院排班相关数据
orderInfo.setScheduleId(scheduleId);
BeanUtils.copyProperties(scheduleOrderVo, orderInfo);//拷贝相关属性
//step4:调用医院端接口获取相关数据
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("hoscode", scheduleOrderVo.getHoscode());
paramsMap.put("depcode", scheduleOrderVo.getDepcode());
paramsMap.put("hosScheduleId", scheduleOrderVo.getHosScheduleId());
paramsMap.put(
"reserveDate",
new DateTime(scheduleOrderVo.getReserveDate()).toString("yyyy-MM-dd")
);
paramsMap.put("reserveTime", scheduleOrderVo.getReserveTime());
paramsMap.put("amount", scheduleOrderVo.getAmount());
paramsMap.put("name", patient.getName());
paramsMap.put("certificatesType", patient.getCertificatesType());
paramsMap.put("certificatesNo", patient.getCertificatesNo());
paramsMap.put("sex", patient.getSex());
paramsMap.put("birthdate", patient.getBirthdate());
paramsMap.put("phone", patient.getPhone());
paramsMap.put("isMarry", patient.getIsMarry());
paramsMap.put("timestamp", HttpRequestHelper.getTimestamp());
paramsMap.put("sign", HttpRequestHelper.getSign(paramsMap, signInfoVo.getSignKey()));//标准签名
JSONObject jsonResult = HttpRequestHelper.sendRequest(
paramsMap, signInfoVo.getApiUrl() + "/order/submitOrder"
);
log.info("结果:" + jsonResult.toJSONString());
if(jsonResult.getInteger("code") != 200){//失败
log.error("预约失败,"
+ "code:" + jsonResult.getInteger("code")
+ ",message:" + jsonResult.getString("message")
);
throw new GuiguException(ResultCodeEnum.FAIL.getCode(), jsonResult.getString("message"));
}
JSONObject data = jsonResult.getJSONObject("data");
String hosOrderId = data.getString("hosOrderId");
Integer number = data.getInteger("number");
String fetchTime = data.getString("fetchTime");
String fetchAddress = data.getString("fetchAddress");
orderInfo.setHosOrderId(hosOrderId);
orderInfo.setNumber(number);
orderInfo.setFetchTime(fetchTime);
orderInfo.setFetchAddress(fetchAddress);
baseMapper.insert(orderInfo);
//使用这两个数据更新平台端的最新的排班数量
Integer reservedNumber = data.getInteger("reservedNumber");
Integer availableNumber = data.getInteger("availableNumber");
//目的1:更新mongodb数据库中的排班数量
//TODO 中间件:MQ 异步解耦
//目的2:给就诊人发短信 TODO:MQ
return orderInfo.getId(); //返回订单id
}
5、前端整合
5.1、api
创建api/orderInfo.js
import request from '@/utils/request'
export default {
//生成订单
submitOrder(scheduleId, patientId) {
return request({
url: `/front/order/orderInfo/auth/submitOrder/${scheduleId}/${patientId}`,
method: 'post'
})
}
}
5.2、组件
在booking.vue组件中完善下单方法
<div class="v-button" @click="submitOrder()">{{orderText}}</div>
定义data
orderBtnDisabled: false, //防止重复提交
orderText: '确认挂号'
引入api
import orderInfoApi from '~/api/orderInfo'
完善方法
//确认挂号
submitOrder() {
if (this.orderBtnDisabled) return
this.orderBtnDisabled = true
this.orderText = '预约挂号中...'
orderInfoApi
.submitOrder(this.scheduleId, this.patient.id)
.then((response) => {
window.location.href = '/order/show?orderId=' + response.data
})
},
第02章-订单详情(作业)
1、后端接口
1.1、Controller
在FrontOrderInfoController中添加方法
@ApiOperation("根据订单id查询订单详情")
@ApiImplicitParam(name = "orderId",value = "订单id", required = true)
@GetMapping("/auth/getOrder/{orderId}")
public Result<OrderInfo> getOrder(@PathVariable Long orderId, HttpServletRequest request, HttpServletResponse response) {
authContextHolder.checkAuth(request, response);
OrderInfo orderInfo = orderInfoService.getOrderInfo(orderId);
return Result.ok(orderInfo);
}
1.2、Service
接口:OrderInfoService
/**
* 根据订单id获取订单详情
* @param orderId
* @return
*/
OrderInfo getOrderInfo(Long orderId);
实现:OrderInfoServiceImpl
@Override
public OrderInfo getOrderInfo(Long orderId) {
OrderInfo orderInfo = baseMapper.selectById(orderId);
return this.packOrderInfo(orderInfo);
}
辅助方法
/**
* 封装订单数据
* @param orderInfo
* @return
*/
private OrderInfo packOrderInfo(OrderInfo orderInfo) {
orderInfo.getParam().put(
"orderStatusString",
OrderStatusEnum.getStatusNameByStatus(orderInfo.getOrderStatus())
);
return orderInfo;
}
3、前端整合
3.1、api
在orderInfo.js添加方法
//订单详情
getOrder(orderId) {
return request({
url: `/front/order/orderInfo/auth/getOrder/${orderId}`,
method: `get`
})
},
2、页面渲染
资料:资料>订单微服务>order
pages/order/show.vue组件
第03章-订单列表(作业)
1、后端接口
1.1、Controller
在FrontOrderInfoController中添加方法
@ApiOperation("订单列表")
@GetMapping("/auth/list")
public Result<List<OrderInfo>> list(HttpServletRequest request, HttpServletResponse response) {
Long userId = authContextHolder.checkAuth(request, response);
List<OrderInfo> orderInfolist = orderInfoService.selectList(userId);
return Result.ok(orderInfolist);
}
1.2、Service
接口:OrderInfoService
/**
* 获取当前用户订单列表
* @param userId
* @return
*/
List<OrderInfo> selectList(Long userId);
实现:OrderInfoServiceImpl
@Override
public List<OrderInfo> selectList(Long userId) {
LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderInfo::getUserId, userId);
List<OrderInfo> orderInfoList = baseMapper.selectList(queryWrapper);
orderInfoList.stream().forEach(this::packOrderInfo);
return orderInfoList;
}
2、前端整合
2.1、api
在orderInfo.js添加方法
//订单列表
getList() {
return request({
url: `/front/order/orderInfo/auth/list`,
method: `get`
})
},
2.2、页面渲
资料:资料>订单微服务>order
pages/order/index.vue组件
源码:https://gitee.com/dengyaojava/guigu-syt-parent
本文来自博客园,作者:自律即自由-,转载请注明原文链接:https://www.cnblogs.com/deyo/p/17491080.html