1, Make an appointment to place an order
requirement analysis
Order table structure
Order analysis
Refer to business interface 5.1 of Shang Yi Tong API interface document.docx to make an appointment and place an order
Order parameters: visiting person id and shift id
- We need to get the information of the patient when placing an order
- Get shift scheduling and order information and rule information
- Get the signature information of the hospital, and then go to the hospital to make an appointment and place an order through the interface
- Order successfully, update the scheduling information and send SMS
2. Build the service order module
2.1 build the service order module
Refer to the service user module for the construction process
2.2 modify configuration
1. Modify pom XML, introducing dependencies
<dependencies> <dependency> <groupId>com.atguigu</groupId> <artifactId>service_cmn_client</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
2. Add configuration file application properties
# Service port server.port=8206 # service name spring.application.name=service-order # Environment settings: dev, test, prod spring.profiles.active=dev # mysql database connection spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.44.165:3306/yygh_hosp?characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=root123 #Return the global time format of json spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8 spring.data.mongodb.uri=mongodb://192.168.44.165:27017/yygh_hosp # nacos service address spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 #rabbitmq address spring.rabbitmq.host=192.168.44.165 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest
2.3 startup
@SpringBootApplication @ComponentScan(basePackages = {"com.atguigu"}) @EnableDiscoveryClient @EnableFeignClients(basePackages = {"com.atguigu"}) public class ServiceOrderApplication { public static void main(String[] args) { SpringApplication.run(ServiceOrderApplication.class, args); } }
2.4 configure gateway
#Set routing id spring.cloud.gateway.routes[6].id=service-order #Set the uri of the route spring.cloud.gateway.routes[6].uri=lb://service-order #Set the route assertion, and the agent servicerId is the /auth/ path of auth service spring.cloud.gateway.routes[6].predicates= Path=/*/order/**
3. Add order basic class
3.1 add model
Note: since entity objects have no logic, we have imported them uniformly
com.atguigu.yygh.model.order.OrderInfo
3.2 add Mapper
Add com atguigu. yygh. order. mapper. OrderInfoMapper
public interface OrderInfoMapper extends BaseMapper<OrderInfo> { }
3.3 add service interface and implementation class
1. Add com atguigu. yygh. order. service. Orderservice interface
public interface OrderService extends IService<OrderInfo> { //Save order Long saveOrder(String scheduleId, Long patientId); }
2. Add com atguigu. yygh. order. service. impl. Orderserviceimpl interface implementation
@Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService { //Save order @Override public Long saveOrder(String scheduleId, Long patientId) { return null; } }
3.4 add controller
Add com atguigu. yygh. order. api. Orderapicontroller class
@Api(tags = "Order interface") @RestController @RequestMapping("/api/order/orderInfo") public class OrderApiController { @Autowired private OrderService orderService; @ApiOperation(value = "Create order") @PostMapping("auth/submitOrder/{scheduleId}/{patientId}") public Result submitOrder( @ApiParam(name = "scheduleId", value = "Scheduling id", required = true) @PathVariable String scheduleId, @ApiParam(name = "patientId", value = "the patient id", required = true) @PathVariable Long patientId) { return Result.ok(orderService.saveOrder(scheduleId, patientId)); } }
Encapsulate Feign call to get the doctor interface
4.1 api interface for obtaining patient information
Operation module: service user
Add a method in the PatientApiController class
@ApiOperation(value = "Get the patient") @GetMapping("inner/get/{id}") public Patient getPatientOrder( @ApiParam(name = "id", value = "the patient id", required = true) @PathVariable("id") Long id) { return patientService.getById(id); }
4.2 build the service user client module
4.2.1 build the service user client module
The construction process is like the service CMN client module
4.2.2 add Feign interface class
@FeignClient(value = "service-user") @Repository public interface PatientFeignClient { //Get the patient @GetMapping("/api/user/patient/inner/get/{id}") Patient getPatient(@PathVariable("id") Long id); }
Encapsulate Feign call to obtain shift scheduling and order information interface
5.1 api interface for obtaining shift scheduling and order information
Operation module: Service Hosp
5.1.1 add service interface and Implementation
1. Add an interface to the ScheduleService class
//Get the reservation and order data according to the shift id ScheduleOrderVo getScheduleOrderVo(String scheduleId);
2. Add an implementation in the ScheduleServiceImpl class
//Get the reservation and order data according to the shift id @Override public ScheduleOrderVo getScheduleOrderVo(String scheduleId) { ScheduleOrderVo scheduleOrderVo = new ScheduleOrderVo(); //Scheduling information Schedule schedule = baseMapper.selectById(scheduleId); if(null == schedule) { throw new YyghException(ResultCodeEnum.PARAM_ERROR); } //Get appointment rule information Hospital hospital = hospitalService.getByHoscode(schedule.getHoscode()); if(null == hospital) { throw new YyghException(ResultCodeEnum.DATA_ERROR); } BookingRule bookingRule = hospital.getBookingRule(); if(null == bookingRule) { throw new YyghException(ResultCodeEnum.PARAM_ERROR); } scheduleOrderVo.setHoscode(schedule.getHoscode()); scheduleOrderVo.setHosname(hospitalService.getHospName(schedule.getHoscode())); scheduleOrderVo.setDepcode(schedule.getDepcode()); scheduleOrderVo.setDepname(departmentService.getDepName(schedule.getHoscode(), schedule.getDepcode())); scheduleOrderVo.setHosScheduleId(schedule.getHosScheduleId()); scheduleOrderVo.setAvailableNumber(schedule.getAvailableNumber()); scheduleOrderVo.setTitle(schedule.getTitle()); scheduleOrderVo.setReserveDate(schedule.getWorkDate()); scheduleOrderVo.setReserveTime(schedule.getWorkTime()); scheduleOrderVo.setAmount(schedule.getAmount()); //The number of days until cancellation (for example, the day before the visit is -1, and the day is 0) int quitDay = bookingRule.getQuitDay(); DateTime quitTime = this.getDateTime(new DateTime(schedule.getWorkDate()).plusDays(quitDay).toDate(), bookingRule.getQuitTime()); scheduleOrderVo.setQuitTime(quitTime.toDate()); //Appointment start time DateTime startTime = this.getDateTime(new Date(), bookingRule.getReleaseTime()); scheduleOrderVo.setStartTime(startTime.toDate()); //Appointment deadline DateTime endTime = this.getDateTime(new DateTime().plusDays(bookingRule.getCycle()).toDate(), bookingRule.getStopTime()); scheduleOrderVo.setEndTime(endTime.toDate()); //Registration stop time of the day DateTime stopTime = this.getDateTime(new Date(), bookingRule.getStopTime()); scheduleOrderVo.setStartTime(startTime.toDate()); return scheduleOrderVo; }
5.1.2 add controller method
Add methods in the HospitalApiController class
@ApiOperation(value = "According to scheduling id Get appointment and order data") @GetMapping("inner/getScheduleOrderVo/{scheduleId}") public ScheduleOrderVo getScheduleOrderVo( @ApiParam(name = "scheduleId", value = "Scheduling id", required = true) @PathVariable("scheduleId") String scheduleId) { return scheduleService.getScheduleOrderVo(scheduleId); }
5.2 interface for obtaining order reference signature information
Operation module: Service Hosp
5.2.1 add service interface and Implementation
1. Add an interface to the HospitalSetService class
//Get hospital signature information SignInfoVo getSignInfoVo(String hoscode);
2. Add an implementation in the HospitalSetServiceImpl class
//Get hospital signature information @Override public SignInfoVo getSignInfoVo(String hoscode) { QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>(); wrapper.eq("hoscode",hoscode); HospitalSet hospitalSet = baseMapper.selectOne(wrapper); if(null == hospitalSet) { throw new YyghException(ResultCodeEnum.HOSPITAL_OPEN); } SignInfoVo signInfoVo = new SignInfoVo(); signInfoVo.setApiUrl(hospitalSet.getApiUrl()); signInfoVo.setSignKey(hospitalSet.getSignKey()); return signInfoVo; }
5.2.2 add controller method
Add methods in the HospitalApiController class
@ApiOperation(value = "Get hospital signature information") @GetMapping("inner/getSignInfoVo/{hoscode}") public SignInfoVo getSignInfoVo( @ApiParam(name = "hoscode", value = "hospital code", required = true) @PathVariable("hoscode") String hoscode) { return hospitalSetService.getSignInfoVo(hoscode); }
5.3 build the service Hosp client module
5.3.1 build the service Hosp client module
The construction process is like the service CMN client module
5.3.2 add Feign interface class
@FeignClient(value = "service-hosp") @Repository public interface HospitalFeignClient { /** * Get the reservation and order data according to the shift id */ @GetMapping("/api/hosp/hospital/inner/getScheduleOrderVo/{scheduleId}") ScheduleOrderVo getScheduleOrderVo(@PathVariable("scheduleId") String scheduleId); /** * Get hospital signature information */ @GetMapping("/api/hosp/hospital/inner/getSignInfoVo/{hoscode}") SignInfoVo getSignInfoVo(@PathVariable("hoscode") String hoscode); }
Realize the order interface
Operation module: Service Order
6.1 import dependency
<dependencies> <dependency> <groupId>com.atguigu</groupId> <artifactId>service_cmn_client</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>com.atguigu</groupId> <artifactId>service_hosp_client</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>com.atguigu</groupId> <artifactId>service_user_client</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
6.2 packaging and ordering tools
Encapsulate the HttpRequestHelper class and add a signature request method
public class HttpRequestHelper { /** * * @param paramMap * @return */ public static Map<String, Object> switchMap(Map<String, String[]> paramMap) { Map<String, Object> resultMap = new HashMap<>(); for (Map.Entry<String, String[]> param : paramMap.entrySet()) { resultMap.put(param.getKey(), param.getValue()[0]); } return resultMap; } /** * Request data for signature * @param paramMap * @param signKey * @return */ public static String getSign(Map<String, Object> paramMap, String signKey) { if(paramMap.containsKey("sign")) { paramMap.remove("sign"); } TreeMap<String, Object> sorted = new TreeMap<>(paramMap); StringBuilder str = new StringBuilder(); for (Map.Entry<String, Object> param : sorted.entrySet()) { str.append(param.getValue()).append("|"); } str.append(signKey); log.info("Before encryption:" + str.toString()); String md5Str = MD5.encrypt(str.toString()); log.info("After encryption:" + md5Str); return md5Str; } /** * Signature verification * @param paramMap * @param signKey * @return */ public static boolean isSignEquals(Map<String, Object> paramMap, String signKey) { String sign = (String)paramMap.get("sign"); String md5Str = getSign(paramMap, signKey); if(!sign.equals(md5Str)) { return false; } return true; } /** * Get timestamp * @return */ public static long getTimestamp() { return new Date().getTime(); } /** * Encapsulate synchronization request */ public static JSONObject sendRequest(Map<String, Object> paramMap, String url){ String result = ""; try { //Encapsulate post parameters StringBuilder postdata = new StringBuilder(); for (Map.Entry<String, Object> param : paramMap.entrySet()) { postdata.append(param.getKey()).append("=") .append(param.getValue()).append("&"); } log.info(String.format("--> Send request: post data %1s", postdata)); byte[] reqData = postdata.toString().getBytes("utf-8"); byte[] respdata = HttpUtil.doPost(url,reqData); result = new String(respdata); log.info(String.format("--> Response result: result data %1s", result)); } catch (Exception ex) { ex.printStackTrace(); } return JSONObject.parseObject(result); } }
6.3 realize the order interface
Modify the ordering method of OrderServiceImpl class
@Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService { @Autowired private PatientFeignClient patientFeignClient; @Autowired private HospitalFeignClient hospitalFeignClient; //Save order @Override public Long saveOrder(String scheduleId, Long patientId) { Patient patient = patientFeignClient.getPatient(patientId); if(null == patient) { throw new YyghException(ResultCodeEnum.PARAM_ERROR); } ScheduleOrderVo scheduleOrderVo = hospitalFeignClient.getScheduleOrderVo(scheduleId); if(null == scheduleOrderVo) { throw new YyghException(ResultCodeEnum.PARAM_ERROR); } //Cannot make an appointment at the current time if(new DateTime(scheduleOrderVo.getStartTime()).isAfterNow() || new DateTime(scheduleOrderVo.getEndTime()).isBeforeNow()) { throw new YyghException(ResultCodeEnum.TIME_NO); } SignInfoVo signInfoVo = hospitalFeignClient.getSignInfoVo(scheduleOrderVo.getHoscode()); if(null == scheduleOrderVo) { throw new YyghException(ResultCodeEnum.PARAM_ERROR); } if(scheduleOrderVo.getAvailableNumber() <= 0) { throw new YyghException(ResultCodeEnum.NUMBER_NO); } OrderInfo orderInfo = new OrderInfo(); BeanUtils.copyProperties(scheduleOrderVo, orderInfo); String outTradeNo = System.currentTimeMillis() + ""+ new Random().nextInt(100); orderInfo.setOutTradeNo(outTradeNo); orderInfo.setScheduleId(scheduleId); orderInfo.setUserId(patient.getUserId()); orderInfo.setPatientId(patientId); orderInfo.setPatientName(patient.getName()); orderInfo.setPatientPhone(patient.getPhone()); orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus()); this.save(orderInfo); Map<String, Object> paramMap = new HashMap<>(); paramMap.put("hoscode",orderInfo.getHoscode()); paramMap.put("depcode",orderInfo.getDepcode()); paramMap.put("hosScheduleId",orderInfo.getScheduleId()); paramMap.put("reserveDate",new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd")); paramMap.put("reserveTime", orderInfo.getReserveTime()); paramMap.put("amount",orderInfo.getAmount()); paramMap.put("name", patient.getName()); paramMap.put("certificatesType",patient.getCertificatesType()); paramMap.put("certificatesNo", patient.getCertificatesNo()); paramMap.put("sex",patient.getSex()); paramMap.put("birthdate", patient.getBirthdate()); paramMap.put("phone",patient.getPhone()); paramMap.put("isMarry", patient.getIsMarry()); paramMap.put("provinceCode",patient.getProvinceCode()); paramMap.put("cityCode", patient.getCityCode()); paramMap.put("districtCode",patient.getDistrictCode()); paramMap.put("address",patient.getAddress()); //contacts paramMap.put("contactsName",patient.getContactsName()); paramMap.put("contactsCertificatesType", patient.getContactsCertificatesType()); paramMap.put("contactsCertificatesNo",patient.getContactsCertificatesNo()); paramMap.put("contactsPhone",patient.getContactsPhone()); paramMap.put("timestamp", HttpRequestHelper.getTimestamp()); String sign = HttpRequestHelper.getSign(paramMap, signInfoVo.getSignKey()); paramMap.put("sign", sign); JSONObject result = HttpRequestHelper.sendRequest(paramMap, signInfoVo.getApiUrl()+"/order/submitOrder"); if(result.getInteger("code") == 200) { JSONObject jsonObject = result.getJSONObject("data"); //Unique ID of appointment record (primary key of hospital appointment record) String hosRecordId = jsonObject.getString("hosRecordId"); //Appointment serial number Integer number = jsonObject.getInteger("number");; //Number acquisition time String fetchTime = jsonObject.getString("fetchTime");; //Number taking address String fetchAddress = jsonObject.getString("fetchAddress");; //Update order orderInfo.setHosRecordId(hosRecordId); orderInfo.setNumber(number); orderInfo.setFetchTime(fetchTime); orderInfo.setFetchAddress(fetchAddress); baseMapper.updateById(orderInfo); //Number of scheduled appointments Integer reservedNumber = jsonObject.getInteger("reservedNumber"); //Remaining appointments of shift scheduling Integer availableNumber = jsonObject.getInteger("availableNumber"); //Send mq information update number source and SMS notification } else { throw new YyghException(result.getString("message"), ResultCodeEnum.FAIL.getCode()); } return orderInfo.getId(); } }
Post appointment processing logic
After the appointment is successful, we need to update the number of appointments and SMS to remind us that the appointment is successful. In order to improve the concurrency of the order, we will hand over this part of the logic to mq to complete for us. If the appointment is successful, we can send a message
(1) Introduction to RabbitMQ
Take the commodity order scenario as an example,
If the commodity service and order service are two different micro services, the order service needs to call the commodity service to deduct inventory during the order placing process. According to the traditional way, the order placing process can only return to the success of the order after the call is completed. If the inventory deduction of goods and services is delayed or failed due to network fluctuations and other reasons, it will bring poor user experience. If such processing is obviously inappropriate in high concurrency scenarios, how to optimize it? This requires message queuing.
Message queuing provides an asynchronous communication mechanism. The sender of a message does not have to wait until the message is successfully processed before returning, but returns immediately. Message oriented middleware is responsible for handling network communication. If the network connection is unavailable, the messages are temporarily stored in the queue. When the network is unblocked, the messages are forwarded to the corresponding applications or services, provided that these services subscribe to the queue. If message oriented middleware is used between Commodity services and order services, it can not only improve the concurrency, but also reduce the coupling between services.
RabbitMQ is such a message queue. RabbitMQ is an open source message broker queue server used to share data between completely different applications through common protocols.
(2) Typical application scenarios:
Asynchronous processing. Put the message into the message middleware and wait until it is needed.
Flow peak shaving. For example, in the second kill activity, the number of visits increases sharply in a short time. Using the message queue, when the message queue is full, it will refuse to respond and jump to the error page, so that the system will not crash due to overload.
Log processing
Application decoupling
(2) Install RabbitMQ
docker pull rabbitmq:management docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management
Management background: http://IP:15672
7.1 rabbit util module packaging
Since mq may be used by many modules in the future, we can package it into a module and directly reference it where necessary
7.1.1 build rabbit util module
It is built under the common module. The building process is as follows: common util
7.1.2 modify pom xml
<dependencies> <!--rabbitmq Message queue--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> </dependencies>
7.1.3 packaging service method
@Service public class RabbitService { @Autowired private RabbitTemplate rabbitTemplate; /** * send message * @param exchange Switch * @param routingKey Routing key * @param message news */ public boolean sendMessage(String exchange, String routingKey, Object message) { rabbitTemplate.convertAndSend(exchange, routingKey, message); return true; } }
7.1.4 configure mq message converter
@Configuration public class MQConfig { @Bean public MessageConverter messageConverter(){ return new Jackson2JsonMessageConverter(); } }
Note: the default is string converter
7.2 encapsulated SMS interface
Operation module: Service MSM
7.2.1 import dependency
<dependency> <groupId>com.atguigu</groupId> <artifactId>rabbit_util</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
7.2.2 add configuration
In resources/application Properties add
#rabbitmq address spring.rabbitmq.host=192.168.44.165 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest
7.2.3 add constant configuration
In rabbit util module com atguigu. yygh. common. constant. Mqconst class add
public class MqConst { /** * Make an appointment to place an order */ public static final String EXCHANGE_DIRECT_ORDER = "exchange.direct.order"; public static final String ROUTING_ORDER = "order"; //queue public static final String QUEUE_ORDER = "queue.order"; /** * short message */ public static final String EXCHANGE_DIRECT_MSM = "exchange.direct.msm"; public static final String ROUTING_MSM_ITEM = "msm.item"; //queue public static final String QUEUE_MSM_ITEM = "queue.msm.item"; }
7.2.4 encapsulate the SMS entity in the model module
@Data @ApiModel(description = "SMS entity") public class MsmVo { @ApiModelProperty(value = "phone") private String phone; @ApiModelProperty(value = "SMS template code") private String templateCode; @ApiModelProperty(value = "SMS template parameters") private Map<String,Object> param; }
Note: unified introduction
7.2.5 encapsulating the service interface
1. Add an interface to the MsmService class
boolean send(MsmVo msmVo);
2. Add interface implementation in MsmServiceImpl class
@Override public boolean send(MsmVo msmVo) { if(!StringUtils.isEmpty(msmVo.getPhone())) { String code = (String)msmVo.getParam().get("code"); return this.send(msmVo.getPhone(),code); } return false; }
7.2.6 package mq listener
@Component public class SmsReceiver { @Autowired private MsmService msmService; @RabbitListener(bindings = @QueueBinding( value = @Queue(value = MqConst.QUEUE_MSM_ITEM, durable = "true"), exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_MSM), key = {MqConst.ROUTING_MSM_ITEM} )) public void send(MsmVo msmVo, Message message, Channel channel) { msmService.send(msmVo); } }
7.3 number of package update shifts
Operation module: Service Hosp
7.3.1 import dependency
<!--rabbitmq Message queue--> <dependency> <groupId>com.atguigu.yygh</groupId> <artifactId>rabbit-util</artifactId> <version>1.0</version> </dependency>
7.3.2 add configuration
In resources/application Properties add
#rabbitmq address spring.rabbitmq.host=192.168.44.165 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest
7.3.3 add constant configuration
In rabbit util module com atguigu. yygh. common. constant. Mqconst class add
/** * Make an appointment to place an order */ public static final String EXCHANGE_DIRECT_ORDER = "exchange.direct.order"; public static final String ROUTING_ORDER = "order"; //queue public static final String QUEUE_ORDER = "queue.order";
7.3.4 package and update the scheduling entity in the model module
@Data @ApiModel(description = "OrderMqVo") public class OrderMqVo { @ApiModelProperty(value = "Bookable number") private Integer reservedNumber; @ApiModelProperty(value = "Remaining appointments") private Integer availableNumber; @ApiModelProperty(value = "Scheduling id") private String scheduleId; @ApiModelProperty(value = "SMS entity") private MsmVo msmVo; }
Note: it has been uniformly introduced. This object puts a SMS entity. After the order is placed successfully, we send a message and let mq ensure that both messages are sent successfully
7.3.5 encapsulating the service interface
1. Add an interface to the ScheduleService class
/** * Modify shift scheduling */ void update(Schedule schedule);
2. Add interface implementation in ScheduleServiceImpl class
@Override public void update(Schedule schedule) { schedule.setUpdateTime(new Date()); //If the primary key is consistent, it means updating scheduleRepository.save(schedule); }
7.3.6 package mq listener
@Component public class HospitalReceiver { @Autowired private ScheduleService scheduleService; @Autowired private RabbitService rabbitService; @RabbitListener(bindings = @QueueBinding( value = @Queue(value = MqConst.QUEUE_ORDER, durable = "true"), exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_ORDER), key = {MqConst.ROUTING_ORDER} )) public void receiver(OrderMqVo orderMqVo, Message message, Channel channel) throws IOException { //Number of appointments updated successfully Schedule schedule = scheduleService.getScheduleId(orderMqVo.getScheduleId()); schedule.setReservedNumber(orderMqVo.getReservedNumber()); schedule.setAvailableNumber(orderMqVo.getAvailableNumber()); scheduleService.update(schedule); //Send SMS MsmVo msmVo = orderMqVo.getMsmVo(); if(null != msmVo) { rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM, MqConst.ROUTING_MSM_ITEM, msmVo); } } }
7.4 adjust the order interface
Operation module: Service Order
7.4.1 import dependency
<dependency> <groupId>com.atguigu</groupId> <artifactId>rabbit_util</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
7.4.2 add configuration
In resources/application Properties add
#rabbitmq address spring.rabbitmq.host=192.168.44.165 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest
7.4.3 modify the order interface
Modify the ordering method of OrderServiceImpl class
@Autowired private RabbitService rabbitService; @Transactional(rollbackFor = Exception.class) @Override public Long saveOrder(String scheduleId, Long patientId) { ....... //Number of scheduled appointments Integer reservedNumber = jsonObject.getInteger("reservedNumber"); //Remaining appointments of shift scheduling Integer availableNumber = jsonObject.getInteger("availableNumber"); //Send mq information update number source and SMS notification //Send mq information update number source OrderMqVo orderMqVo = new OrderMqVo(); orderMqVo.setScheduleId(scheduleId); orderMqVo.setReservedNumber(reservedNumber); orderMqVo.setAvailableNumber(availableNumber); //SMS prompt MsmVo msmVo = new MsmVo(); msmVo.setPhone(orderInfo.getPatientPhone()); msmVo.setTemplateCode("SMS_194640721"); String reserveDate = new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd") + (orderInfo.getReserveTime()==0 ? "morning": "afternoon"); Map<String,Object> param = new HashMap<String,Object>(){{ put("title", orderInfo.getHosname()+"|"+orderInfo.getDepname()+"|"+orderInfo.getTitle()); put("amount", orderInfo.getAmount()); put("reserveDate", reserveDate); put("name", orderInfo.getPatientName()); put("quitTime", new DateTime(orderInfo.getQuitTime()).toString("yyyy-MM-dd HH:mm")); }}; msmVo.setParam(param); orderMqVo.setMsmVo(msmVo); rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER, MqConst.ROUTING_ORDER, orderMqVo); } else { throw new YyghException(result.getString("message"), ResultCodeEnum.FAIL.getCode()); } return orderInfo.getId(); }
2, Order management
Order list
api interface
1.1.1 add service interface and implementation class
1. Add an interface to the OrderInfoService class
/** * Paging list */ IPage<OrderInfo> selectPage(Page<OrderInfo> pageParam, OrderQueryVo orderQueryVo);
2. Add interface implementation in OrderInfoServiceImpl class
//Order list (condition query with pagination) @Override public IPage<OrderInfo> selectPage(Page<OrderInfo> pageParam, OrderQueryVo orderQueryVo) { //orderQueryVo get condition value String name = orderQueryVo.getKeyword(); //Hospital name Long patientId = orderQueryVo.getPatientId(); //Name of the patient String orderStatus = orderQueryVo.getOrderStatus(); //Order status String reserveDate = orderQueryVo.getReserveDate();//Schedule time String createTimeBegin = orderQueryVo.getCreateTimeBegin(); String createTimeEnd = orderQueryVo.getCreateTimeEnd(); //Judge whether the condition value is not empty QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>(); if(!StringUtils.isEmpty(name)) { wrapper.like("hosname",name); } if(!StringUtils.isEmpty(patientId)) { wrapper.eq("patient_id",patientId); } if(!StringUtils.isEmpty(orderStatus)) { wrapper.eq("order_status",orderStatus); } if(!StringUtils.isEmpty(reserveDate)) { wrapper.ge("reserve_date",reserveDate); } if(!StringUtils.isEmpty(createTimeBegin)) { wrapper.ge("create_time",createTimeBegin); } if(!StringUtils.isEmpty(createTimeEnd)) { wrapper.le("create_time",createTimeEnd); } //Call the method of mapper IPage<OrderInfo> pages = baseMapper.selectPage(pageParam, wrapper); //Number becomes corresponding value encapsulation pages.getRecords().stream().forEach(item -> { this.packOrderInfo(item); }); return pages; } private OrderInfo packOrderInfo(OrderInfo orderInfo) { orderInfo.getParam().put("orderStatusString", OrderStatusEnum.getStatusNameByStatus(orderInfo.getOrderStatus())); return orderInfo; }
1.1.2 add controller
Add a method in the OrderApiController class
//Order list (condition query with pagination) @GetMapping("auth/{page}/{limit}") public Result list(@PathVariable Long page, @PathVariable Long limit, OrderQueryVo orderQueryVo, HttpServletRequest request) { //Set current user id orderQueryVo.setUserId(AuthContextHolder.getUserId(request)); Page<OrderInfo> pageParam = new Page<>(page,limit); IPage<OrderInfo> pageModel = orderService.selectPage(pageParam,orderQueryVo); return Result.ok(pageModel); } @ApiOperation(value = "Get order status") @GetMapping("auth/getStatusList") public Result getStatusList() { return Result.ok(OrderStatusEnum.getStatusList()); }
Note: the order status is encapsulated in enumeration. A drop-down list is required for page search, so we return to the page through the interface
front end
1.2.1 encapsulating api requests
At /api/orderinfo JS add method
//Order list getPageList(page, limit, searchObj) { return request({ url: `${api_name}/auth/${page}/${limit}`, method: `get`, params: searchObj }) }, //Order status getStatusList() { return request({ url: `${api_name}/auth/getStatusList`, method: 'get' }) },
1.2.2 page display
Create /pages/order/index Vue component
<template> <!-- header --> <div class="nav-container page-component"> <!--Left Navigation #start --> <div class="nav left-nav"> <div class="nav-item "> <span class="v-link clickable dark" οnclick="javascript:window.location='/user'">Real name authentication </span> </div> <div class="nav-item selected"> <span class="v-link selected dark" οnclick="javascript:window.location='/order'"> Registered order </span> </div> <div class="nav-item "> <span class="v-link clickable dark" οnclick="javascript:window.location='/patient'"> Patient management </span> </div> <div class="nav-item "> <span class="v-link clickable dark"> Modify account information </span> </div> <div class="nav-item "> <span class="v-link clickable dark"> Feedback </span> </div> </div> <!-- Left Navigation #end --> <!-- Content on the right #start --> <div class="page-container"> <div class="personal-order"> <div class="title"> Registered order</div> <el-form :inline="true"> <el-form-item label="the patient:"> <el-select v-model="searchObj.patientId" placeholder="Please select a doctor" class="v-select patient-select"> <el-option v-for="item in patientList" :key="item.id" :label="item.name + '[' + item.certificatesNo + ']'" :value="item.id"> </el-option> </el-select> </el-form-item> <el-form-item label="Order status:" style="margin-left: 80px"> <el-select v-model="searchObj.orderStatus" placeholder="whole" class="v-select patient-select" style="width: 200px;"> <el-option v-for="item in statusList" :key="item.status" :label="item.comment" :value="item.status"> </el-option> </el-select> </el-form-item> <el-form-item> <el-button type="text" class="search-button v-link highlight clickable selected" @click="fetchData()"> query </el-button> </el-form-item> </el-form> <div class="table-wrapper table"> <el-table :data="list" stripe style="width: 100%"> <el-table-column label="Visit time" width="120"> <template slot-scope="scope"> {{ scope.row.reserveDate }} {{ scope.row.reserveTime === 0 ? 'morning' : 'afternoon' }} </template> </el-table-column> <el-table-column prop="hosname" label="hospital" width="100"> </el-table-column> <el-table-column prop="depname" label="Department"> </el-table-column> <el-table-column prop="title" label="doctor"> </el-table-column> <el-table-column prop="amount" label="medical service fee "> </el-table-column> <el-table-column prop="patientName" label="the patient"> </el-table-column> <el-table-column prop="param.orderStatusString" label="Order status"> </el-table-column> <el-table-column label="operation"> <template slot-scope="scope"> <el-button type="text" class="v-link highlight clickable selected" @click="show(scope.row.id)">details</el-button> </template> </el-table-column> </el-table> </div> <!-- paging --> <el-pagination class="pagination" layout="prev, pager, next" :current-page="page" :total="total" :page-size="limit" @current-change="fetchData"> </el-pagination> </div> </div> <!-- Content on the right #end --> </div> <!-- footer --> </template> <script> import '~/assets/css/hospital_personal.css' import '~/assets/css/hospital.css' import orderInfoApi from '@/api/order/orderInfo' import patientApi from '@/api/user/patient' export default { data() { return { list: [], // banner list total: 0, // Total records in the database page: 1, // Default page number limit: 10, // Records per page searchObj: {}, // Query form object patientList: [], statusList: [] } }, created() { this.orderId = this.$route.query.orderId this.fetchData() this.findPatientList() this.getStatusList() }, methods: { fetchData(page = 1) { this.page = page orderInfoApi.getPageList(this.page, this.limit, this.searchObj).then(response => { console.log(response.data); this.list = response.data.records this.total = response.data.total }) }, findPatientList() { patientApi.findList().then(response => { this.patientList = response.data }) }, getStatusList() { orderInfoApi.getStatusList().then(response => { this.statusList = response.data }) }, changeSize(size) { console.log(size) this.limit = size this.fetchData(1) }, show(id) { window.location.href = '/order/show?orderId=' + id } } } </script>
Order details
2.1 api interface
2.1.1 add service interface and implementation class
1. Add an interface to the OrderInfoService class
/** * Get order details */ OrderInfo getOrderInfo(Long id);
2. Add interface implementation in OrderInfoServiceImpl class
//Query order details according to order id @Override public OrderInfo getOrder(String orderId) { OrderInfo orderInfo = baseMapper.selectById(orderId); return this.packOrderInfo(orderInfo); }
2.1.2 add controller
Add a method in the OrderApiController class
//Query order details according to order id @GetMapping("auth/getOrders/{orderId}") public Result getOrders(@PathVariable String orderId) { OrderInfo orderInfo = orderService.getOrder(orderId); return Result.ok(orderInfo); }
2.2 front end
2.2.1 encapsulating api requests
At /api/order/orderinfo JS add method
//Order details getOrders(orderId) { return request({ url: `${api_name}/auth/getOrders/${orderId}`, method: `get` }) },
2.2.2 page display
Create /pages/order/show Vue component
<template> <!-- header --> <div class="nav-container page-component"> <!--Left Navigation #start --> <div class="nav left-nav"> <div class="nav-item "> <span class="v-link clickable dark" οnclick="javascript:window.location='/user'">Real name authentication </span> </div> <div class="nav-item selected"> <span class="v-link selected dark" οnclick="javascript:window.location='/order'"> Registered order </span> </div> <div class="nav-item "> <span class="v-link clickable dark" οnclick="javascript:window.location='/patient'"> Patient management </span> </div> <div class="nav-item "> <span class="v-link clickable dark"> Modify account information </span> </div> <div class="nav-item "> <span class="v-link clickable dark"> Feedback </span> </div> </div> <!-- Left Navigation #end --> <!-- Content on the right #start --> <div class="page-container"> <div class="order-detail"> <div class="title"> Registration details</div> <div class="status-bar"> <div class="left-wrapper"> <div class="status-wrapper BOOKING_SUCCESS"> <span class="iconfont"></span> {{ orderInfo.param.orderStatusString }} </div> </div> <div class="right-wrapper"> <img src="//img.114yygh.com/static/web/code_order_detail.png" class="code-img"> <div class="content-wrapper"> <div> WeChat<span class="iconfont"></span>Follow "Beijing 114 appointment registration"</div> <div class="watch-wrapper"> Fast registration and easy medical treatment</div> </div> </div> </div> <div class="info-wrapper"> <div class="title-wrapper"> <div class="block"></div> <div>Registration information</div> </div> <div class="info-form"> <el-form ref="form" :model="form"> <el-form-item label="Patient information:"> <div class="content"><span>{{ orderInfo.patientName }}</span></div> </el-form-item> <el-form-item label="Date of visit:"> <div class="content"><span>{{ orderInfo.reserveDate }} {{ orderInfo.reserveTime == 0 ? 'morning' : 'afternoon' }}</span></div> </el-form-item> <el-form-item label="Hospital:"> <div class="content"><span>{{ orderInfo.hosname }} </span></div> </el-form-item> <el-form-item label="Department:"> <div class="content"><span>{{ orderInfo.depname }} </span></div> </el-form-item> <el-form-item label="Doctor Title:"> <div class="content"><span>{{ orderInfo.title }} </span></div> </el-form-item> <el-form-item label="Medical service fee:"> <div class="content"> <div class="fee">{{ orderInfo.amount }}element </div> </div> </el-form-item> <el-form-item label="Registration No.:"> <div class="content"><span>{{ orderInfo.outTradeNo }} </span></div> </el-form-item> <el-form-item label="Registration time:"> <div class="content"><span>{{ orderInfo.createTime }}</span></div> </el-form-item> </el-form> </div> </div> <div class="rule-wrapper mt40"> <div class="rule-title"> matters needing attention</div> <div>1,Please confirm whether the information of the doctor is accurate. If you fill in the wrong number, you will not be able to get a doctor, and the loss will be borne by yourself;<br> <span style="color:red">2,[Take number] on the day of treatment{{ orderInfo.fetchTime }}Take a number in the hospital. If you don't take a number, it will be regarded as breaking the appointment, and the number will not be returned or replaced;</span><br> 3,[Back number] in{{ orderInfo.quitTime }}The number can be refunded online before, and the number and fee can not be refunded after the expiration of the time limit;<br> 4,Beijing 114 appointment registration supports self funded patients to make an appointment with their ID card, and supports Beijing medical insurance patients to make an appointment with the Beijing social security card on the platform. Please bring the valid ID card used for appointment registration to the hospital to get the number on the day of treatment;<br> 5,Please note that medical insurance patients in Beijing cannot use social security cards to get numbers in outpatient clinics during hospitalization. </div> </div> <div class="bottom-wrapper mt60" v-if="orderInfo.orderStatus == 0 || orderInfo.orderStatus == 1"> <div class="button-wrapper"> <div class="v-button white" @click="cancelOrder()">cancel reservation</div> </div> <div class="button-wrapper ml20" v-if="orderInfo.orderStatus == 0"> <div class="v-button" @click="pay()">payment</div> </div> </div> </div> </div> <!-- Content on the right #end --> <!-- Wechat payment pop-up box --> <el-dialog :visible.sync="dialogPayVisible" style="text-align: left" :append-to-body="true" width="500px" @close="closeDialog"> <div class="container"> <div class="operate-view" style="height: 350px;"> <div class="wrapper wechat"> <div> <img src="images/weixin.jpg" alt=""> <div style="text-align: center;line-height: 25px;margin-bottom: 40px;"> Please use wechat to scan<br/> Scanning QR code for payment </div> </div> </div> </div> </div> </el-dialog> </div> <!-- footer --> </template> <script> import '~/assets/css/hospital_personal.css' import '~/assets/css/hospital.css' import orderInfoApi from '@/api/orderInfo' export default { data() { return { orderId: null, orderInfo: { param: {} }, dialogPayVisible: false, payObj: {}, timer: null // Timer name } }, created() { this.orderId = this.$route.query.orderId this.init() }, methods: { init() { orderInfoApi.getOrders(this.orderId).then(response => { console.log(response.data); this.orderInfo = response.data }) } } } </script> <style> .info-wrapper { padding-left: 0; padding-top: 0; } .content-wrapper { color: #333; font-size: 14px; padding-bottom: 0; } .bottom-wrapper { width: 100%; } .button-wrapper { margin: 0; } .el-form-item { margin-bottom: 5px; } .bottom-wrapper .button-wrapper { margin-top: 0; } </style>
3, Platform order management
Order list
api interface
Add controller method
Add com atguigu. yygh. order. controller. Ordercontroller class
@Api(tags = "Order interface") @RestController @RequestMapping("/admin/order/orderInfo") public class OrderController { @Autowired private OrderService orderService; @ApiOperation(value = "Get paging list") @GetMapping("{page}/{limit}") public Result index( @ApiParam(name = "page", value = "Current page number", required = true) @PathVariable Long page, @ApiParam(name = "limit", value = "Records per page", required = true) @PathVariable Long limit, @ApiParam(name = "orderCountQueryVo", value = "Query object", required = false) OrderQueryVo orderQueryVo) { Page<OrderInfo> pageParam = new Page<>(page, limit); IPage<OrderInfo> pageModel = orderService.selectPage(pageParam, orderQueryVo); return Result.ok(pageModel); } @ApiOperation(value = "Get order status") @GetMapping("getStatusList") public Result getStatusList() { return Result.ok(OrderStatusEnum.getStatusList()); } }
1.2 front end
1.2.1 add route
In src/router/index JS file add route
{ path: '/order', component: Layout, redirect: '/order/orderInfo/list', name: 'BasesInfo', meta: { title: 'Order management', icon: 'table' }, alwaysShow: true, children: [ { path: 'orderInfo/list', name: 'Order list', component: () =>import('@/views/order/orderInfo/list'), meta: { title: 'Order list' } } ] }
1.2.2 encapsulating api requests
Add /api/order/orderinfo JS file
import request from '@/utils/request' const api_name = '/admin/order/orderInfo' export default { getPageList(page, limit, searchObj) { return request({ url: `${api_name}/${page}/${limit}`, method: 'get', params: searchObj }) }, getStatusList() { return request({ url: `${api_name}/getStatusList`, method: 'get' }) } }
1.2.3 add components
Create /views/order/orderinfo/list Vue component
<template> <div class="app-container"> <el-form :inline="true" class="demo-form-inline"> <el-form-item> <el-input v-model="searchObj.hosname" placeholder="Hospital name"/> </el-form-item> <el-form-item> <el-input v-model="searchObj.outTradeNo" placeholder="order number"/> </el-form-item> <el-form-item> <el-input v-model="searchObj.patientName" placeholder="Name of the patient"/> </el-form-item> <el-form-item> <el-date-picker v-model="searchObj.createTimeBegin" type="date" placeholder="Select Start Date" value-format="yyyy-MM-dd" /> </el-form-item> <el-form-item> <el-date-picker v-model="searchObj.createTimeEnd" type="date" placeholder="Select a deadline" value-format="yyyy-MM-dd" /> </el-form-item> <el-form-item> <el-date-picker v-model="searchObj.reserveDate" type="date" placeholder="Date of visit" value-format="yyyy-MM-dd" /> </el-form-item> <el-form-item> <el-select v-model="searchObj.orderStatus" placeholder="Order status" class="v-select patient-select"> <el-option v-for="item in statusList" :key="item.status" :label="item.comment" :value="item.status"> </el-option> </el-select> </el-form-item> <el-button type="primary" icon="el-icon-search" @click="fetchData()">query</el-button> <el-button type="default" @click="resetData()">empty</el-button> </el-form> <!-- list --> <el-table v-loading="listLoading" :data="list" border fit highlight-current-row> <el-table-column label="Serial number" width="60" align="center"> <template slot-scope="scope"> {{ (page - 1) * limit + scope.$index + 1 }} </template> </el-table-column> <el-table-column prop="outTradeNo" label="Order transaction number" width="160"/> <el-table-column prop="hosname" label="Hospital name" width="160"/> <el-table-column prop="depname" label="Department name" width="160"/> <el-table-column prop="title" label="Doctor title" /> <el-table-column label="Schedule time" width="130"> <template slot-scope="scope"> {{ scope.row.reserveDate }} {{ scope.row.reserveTime === 0 ? 'morning' : 'afternoon' }} </template> </el-table-column> <el-table-column prop="patientName" label="the patient" /> <el-table-column prop="number" label="Appointment number sequence" width="80"/> <el-table-column prop="amount" label="service charge" width="70"/> <el-table-column prop="param.orderStatusString" label="Order status" /> <el-table-column prop="createTime" label="Creation time" width="156"/> <el-table-column label="operation" width="100" align="center"> <template slot-scope="scope"> <router-link :to="'/order/orderInfo/show/'+scope.row.id"> <el-button type="primary" size="mini" icon="el-icon-edit">see</el-button> </router-link> </template> </el-table-column> </el-table> <!-- Paging component --> <el-pagination :current-page="page" :total="total" :page-size="limit" :page-sizes="[5, 10, 20, 30, 40, 50, 100]" style="padding: 30px 0; text-align: center;" layout="sizes, prev, pager, next, jumper, ->, total, slot" @current-change="fetchData" @size-change="changeSize" /> </div> </template> <script> import orderInfoApi from '@/api/order/orderInfo' export default { data() { return { listLoading: true, // Whether the data is loading list: null, // banner list total: 0, // Total records in the database page: 1, // Default page number limit: 10, // Records per page searchObj: {} // Query form object } }, // Life cycle function: the memory is ready, and the page has not been rendered created() { this.fetchData() this.getStatusList() }, methods: { // When the page number changes changeSize(size) { console.log(size) this.limit = size this.fetchData(1) }, // Load banner list data fetchData(page = 1) { console.log('Turn the page...' + page) // Get remote data asynchronously (ajax) this.page = page orderInfoApi.getPageList(this.page, this.limit, this.searchObj).then( response => { debugger this.list = response.data.records this.total = response.data.total // Data loading and binding succeeded this.listLoading = false } ) }, getStatusList() { orderInfoApi.getStatusList().then(response => { this.statusList = response.data }) }, // Reset query form resetData() { console.log('Reset query form') this.searchObj = {} this.fetchData() } } } </script>
Order details
2.1 api interface
2.1.1 add service interface and implementation class
1. Add an interface to the OrderInfoService class
/** * Order details * @param orderId * @return */ Map<String,Object> show(Long orderId);
2. Add interface implementation in OrderInfoServiceImpl class
@Override public Map<String, Object> show(Long orderId) { Map<String, Object> map = new HashMap<>(); OrderInfo orderInfo = this.packOrderInfo(this.getById(orderId)); map.put("orderInfo", orderInfo); Patient patient = patientFeignClient.getPatient(orderInfo.getPatientId()); map.put("patient", patient); return map; }
2.1.2 add controller
Add method in OrderController class
@ApiOperation(value = "Get order") @GetMapping("show/{id}") public Result get( @ApiParam(name = "orderId", value = "order id", required = true) @PathVariable Long id) { return Result.ok(orderService.show(id)); }
2.2 front end
2.2.1 add route
In src/router/index JS file add route
{ path: '/order', component: Layout, redirect: '/order/orderInfo/list', name: 'BasesInfo', meta: { title: 'Order management', icon: 'table' }, alwaysShow: true, children: [ { path: 'orderInfo/list', name: 'Order list', component: () =>import('@/views/order/orderInfo/list'), meta: { title: 'Order list' } }, { path: 'orderInfo/show/:id', name: 'see', component: () =>import('@/views/order/orderInfo/show'), meta: { title: 'see', noCache: true }, hidden: true } ] }
2.2.2 encapsulating api requests
At /api/order/orderinfo JS file adding method
getById(id) { return request({ url: `${api_name}/show/${id}`, method: 'get' }) }
2.2.3 modify list components
Modify /views/order/orderinfo/list Vue component
<el-table-column label="operation"width="100"align="center"> <template slot-scope="scope"> <router-link :to="'/order/orderInfo/show/'+scope.row.id"> <el-button type="primary" size="mini" icon="el-icon-edit">see</el-button> </router-link> </template> </el-table-column>
2.2.4 add components
Create /views/order/orderinfo/show Vue component
<template> <div class="app-container"> <h4>Order information</h4> <table class="table table-striped table-condenseda table-bordered" width="100%"> <tbody> <tr> <th width="15%">Order transaction number</th> <td width="35%"><b style="font-size: 14px">{{ orderInfo.outTradeNo }}</b> </td> <th width="15%">Hospital name</th> <td width="35%">{{ orderInfo.hosname }}</td> </tr> <tr> <th>Department name</th> <td>{{ orderInfo.depname }}</td> <th>Doctor title</th> <td>{{ orderInfo.title }}</td> </tr> <tr> <th>Scheduled date</th> <td>{{ orderInfo.reserveDate }} {{ orderInfo.reserveTime === 0 ? 'morning' : 'afternoon' }}</td> <th>Appointment number sequence</th> <td>{{ orderInfo.number }}</td> </tr> <tr> <th>medical service fee </th> <td>{{ orderInfo.amount }}</td> <th>Suggested date</th> <td>{{ orderInfo.fetchTime }}</td> </tr> <tr> <th>Location of number taking</th> <td>{{ orderInfo.fetchAddress }}</td> <th>Cancellation time</th> <td>{{ orderInfo.quitTime }}</td> </tr> <tr> <th>Order status</th> <td >{{ orderInfo.param.orderStatusString }}</td> <th>time of appointment</th> <td>{{ orderInfo.createTime }}</td> </tr> </tbody> </table> <h4>Patient information</h4> <table class="table table-striped table-condenseda table-bordered" width="100%"> <tbody> <tr> <th width="15%">full name</th> <td width="35%">{{ patient.name }}day</td> <th width="15%">Document type </th> <td width="35%">{{ patient.param.certificatesTypeString }}</td> </tr> <tr> <th>Certificate No</th> <td>{{ patient.certificatesNo }}</td> <th>Gender</th> <td>{{ patient.sex === 1 ? 'male' : 'female' }}</td> </tr> <tr> <th>date of birth</th> <td>{{ patient.birthdate }}</td> <th>mobile phone</th> <td>{{ patient.phone }}</td> </tr> <tr> <th>Married or not</th> <td>{{ patient.isMarry === 1 ? 'yes' : 'no' }}</td> <th>address</th> <td>{{ patient.param.fullAddress }}</td> </tr> <tr> <th>Contact name</th> <td>{{ patient.contactsName }}</td> <th>Contact ID type</th> <td>{{ patient.param.contactsCertificatesTypeString }}</td> </tr> <tr> <th>Contact ID No</th> <td>{{ orderInfo.contactsCertificatesNo }}</td> <th>Cell Phone </th> <td>{{ orderInfo.contactsPhone }}</td> </tr> <br> <el-row> <el-button @click="back">return</el-button> </el-row> </tbody> </table> </div> </template> <script> // Import components import orderInfoApi from '@/api/order/orderInfo' export default { data() { return { orderInfo: null, patient: null } }, // Life cycle method (it will not be called when the route is switched and the components remain unchanged) created() { console.log('form created ......') this.init() }, methods: { // Form initialization init() { const id = this.$route.params.id this.fetchDataById(id) }, // Query records according to id fetchDataById(id) { orderInfoApi.getById(id).then(response => { this.orderInfo = response.data.orderInfo this.patient = response.data.patient }) }, back() { this.$router.push({ path: '/order/orderInfo/list' }) } } } </script>