typora-copy-images-to: upload # 頁面預覽 ## 訂單詳情 ![image-20230227071834134](https://s2.loli.net/2023/06/19/8rXsPWOn3MdlRNx.png) ![image-20230227071900964] ...
頁面預覽
訂單詳情
訂單列表
第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