电脑版淘宝网页,seo单页快速排名,公司网站建设怎么入账,国内建站平台排名基本预定车票功能的开发 对于乘客购票来说#xff0c;需要有每一个车次的余票信息#xff0c;展示给乘客#xff0c;供乘客选择#xff0c;因此首个功能是余票的初始化#xff0c;之后是余票查询#xff0c;这两个都是控台端。对于会员端的购票#xff0c;需要有余票查询…基本预定车票功能的开发 对于乘客购票来说需要有每一个车次的余票信息展示给乘客供乘客选择因此首个功能是余票的初始化之后是余票查询这两个都是控台端。对于会员端的购票需要有余票查询以及乘客的选择不仅仅支持给自己买票还可以给其他人买票而且还可以选择座位类型是一等座还是二等座可以选择座位最后是下单购票。
余票信息表
对于购票表来说最为重要的字段是售卖字段对于这个字段来说将经过的车站用0和1拼接如果是0表示可卖1表示不可卖。例如有ABCD四个站那么000表示这四个站都可以买最终是可以通过售卖信息来计算出余票的信息。余票查询会显示还有多少张票票数如果通过实时计算会影响性能所以应该另外做张表余票信息表直接存储余票数这张表通过购票表的售卖字段定时的更新此表的信息。这张表是火车的一个子表可以看作用余票的角度观察火车因此需要包含id日期车次以及出发站和到达站的信息。对于出发站和到达站来说重要的是这个站在整个车次是第几站以及每一个站站记录它的余票信息。唯一键是日期车次出发站和终点站。 为什么时日期车次出发站和终点站呢首先是日期同一个车次每天会运行一次余票需要按天来划分车次是列车的唯一标识不同的车次余票应该进行隔离对于出发站和终点站举个例子现在有100张票有5个区间A-B-C-D-E现在小刚买了A-C的票他影响了A-C,A-B,B-C这三个区间进行库存扣减但是对于D-E并不影响还是100张这中间有座位复用的问题因此需要加上出发站和终点站座位唯一键。 构建余票表完成后有两个问题这张表应该如何初始化初始化的数据从何而来首先第一个问题什么时候初始化当一辆火车准备开始卖票时就可以初始化了。对于车站数据来说是一个嵌套循环例如ABCD四个车站用户可以查AB,AC,AD,BC,BD,CD这样子就可以得到车次所有的出发站和到达站的站站组合。对于余票信息来说可以查询座位数这张表查询车次以及座位类型就可以得到余票的信息。 落实到具体的代码上首先是删除要生成某日车次的余票信息使其支持重复生成之后是查询这个车次的所有车站信息根据车站的信息进行嵌套循环先生成一个余票对象然后根据车站进行数据的填充最后将实体保存到数据库
Transactionalpublic void genDaily(Date date, String trainCode) {LOG.info(生成日期【{}】车次【{}】的余票信息开始, DateUtil.formatDate(date), trainCode);// 删除某日某车次的余票信息DailyTrainTicketExample dailyTrainTicketExample new DailyTrainTicketExample();dailyTrainTicketExample.createCriteria().andDateEqualTo(date).andTrainCodeEqualTo(trainCode);dailyTrainTicketMapper.deleteByExample(dailyTrainTicketExample);// 查出某车次的所有车站信息ListTrainStation stationList trainStationService.selectByTrainCode(trainCode);if(CollUtil.isEmpty(stationList)) {LOG.info(该车次信息没有车站基础数据生成该车次的余票信息失败);return;}DateTime now DateTime.now();for (int i 0; i stationList.size(); i) {// 得到出发站TrainStation trainStationStart stationList.get(i);for (int j i 1; j stationList.size(); j) {TrainStation trainStationEnd stationList.get(j);DailyTrainTicket dailyTrainTicket new DailyTrainTicket();dailyTrainTicket.setId(SnowUtil.getSnowflakeNextId());dailyTrainTicket.setDate(date);dailyTrainTicket.setTrainCode(trainCode);dailyTrainTicket.setStart(trainStationStart.getName());dailyTrainTicket.setStartPinyin(trainStationStart.getNamePinyin());dailyTrainTicket.setStartTime(trainStationStart.getOutTime());dailyTrainTicket.setStartIndex(trainStationStart.getIndex());dailyTrainTicket.setEnd(trainStationEnd.getName());dailyTrainTicket.setEndPinyin(trainStationEnd.getNamePinyin());dailyTrainTicket.setEndTime(trainStationEnd.getInTime());dailyTrainTicket.setEndIndex(trainStationEnd.getIndex());dailyTrainTicket.setYdz(0);dailyTrainTicket.setYdzPrice(BigDecimal.ZERO);dailyTrainTicket.setEdz(0);dailyTrainTicket.setEdzPrice(BigDecimal.ZERO);dailyTrainTicket.setRw(0);dailyTrainTicket.setRwPrice(BigDecimal.ZERO);dailyTrainTicket.setYw(0);dailyTrainTicket.setYwPrice(BigDecimal.ZERO);dailyTrainTicket.setCreateTime(now);dailyTrainTicket.setUpdateTime(now);dailyTrainTicketMapper.insert(dailyTrainTicket);}}LOG.info(生成日期【{}】车次【{}】的余票信息结束, DateUtil.formatDate(date), trainCode);}
现在发现对于座位类型的个数和票价还是未知因此接下来解决这个方面的信息。求某个车次的某类型的票数需要知道的是座位数。因此应该在每日座位表中查某个日期某个车次某个座位类型的票数。由于在每日座位表已经有了这些信息因此只需要填写好信息去查询就可以得到初始化的余票信息对于无票的时候如果设置为0用户可以以为卖光了其实想要表达的是改车次没有这种类型的票因此可以设置为-1.
public int countSeat(Date date, String trainCode,String seatType){DailyTrainSeatExample example new DailyTrainSeatExample();example.createCriteria().andDateEqualTo(date).andTrainCodeEqualTo(trainCode).andSeatTypeEqualTo(seatType);long l dailyTrainSeatMapper.countByExample(example);if(l 0L) {return -1;}return (int)l;}
接下来是计算票价票价和火车类型以及座位类型有关票价里程之和*座位类型的票价*车次类型系数。计算里程时从初始站加上每一次到达站的距离即
sumKM sumKM.add(trainStationEnd.getKm());最终的总计算公式如下
// 票价里程之和*座位类型的票价*车次类型系数
String trainType dailyTrain.getType();
// 计算票价系数TrainTypeEnum.priceRate
BigDecimal priceRate EnumUtil.getFieldBy(TrainTypeEnum::getPriceRate,TrainTypeEnum::getCode,trainType);
余票查询
对于余票的查询设置查询条件为日期火车车次起始站和终点站。对于会员端的车票界面来说它不支持增加和修改和删除只是支持查询因此后端对于会员端增加车票查询的接口。
RestController
RequestMapping(/daily-train-ticket)
public class DailyTrainTicketController {Resourceprivate DailyTrainTicketService dailyTrainTicketService;GetMapping(/query-list)public CommonRespPageRespDailyTrainTicketQueryResp queryList(Valid DailyTrainTicketQueryReq req) {PageRespDailyTrainTicketQueryResp list dailyTrainTicketService.queryList(req);return new CommonResp(list);}
}
由于进行查询时需要选择车站以及火车车次而且为了进行分离之前在控制台界面统一增加了admin为了使会员端实现相同的查询因此需要重新写controller层的车次和车票查询它和控台的功能相同只是url不同。至此会员端和控制台界面开发完毕。
选座功能 首先是预定的按钮在点击按钮之后需要跳转到order界面因此需要在router增加一个路由那用什么取传递参数呢session就是一个很好的选择在order界面打开时执行setup(),定义一个参数dailyTrainTicket从缓存中获取dailyTrainTicket如果没有给一个空对象避免空指针异常之后进行返回在html部分进行显示出来。在点击时利用自定义的toOrder,首先是把record放入Session中之后进行路由跳转。现在是每次查询之后返回选择框不会保存之前选择的值为了增强用户体验可以为余票查询页面缓存查询参数方便用户使用将session key写成常量,方便统一维护可以避免多个功能使用同一个key。当用户选择之后将用户的选择缓存到一个session key中然后在公共区添加不同的session key避免混用。之后修改onMounted(),它表示页面打开先进性缓存的获取之后不为空是进行查询。
// order.vuetemplatediv{{dailyTrainTicket}}/div
/templatescriptimport {defineComponent} from vue;export default defineComponent({name: order-view,setup() {const dailyTrainTicket SessionStorage.get(dailyTrainTicket) || {};console.log(下单的车次信息, dailyTrainTicket);return {dailyTrainTicket,};},
});
/script// ticket.vue// 保存查询参数
SessionStorage.set(SESSION_TICKET_PARAMS, params.value);onMounted(() {params.value SessionStorage.get(SESSION_TICKET_PARAMS) || {};if(Tool.isNotEmpty(params.value)) {handleQuery({page: 1,pageSize: pagination.value.pageSize});}});
最后的是在order界面的展示优化得到从出发站到终点站以及座位类型和价格以及票数的展示。 接下来是真正的选择座位功能首先是后端去查找我的所有乘客接口在order界面调用接口在搜索的service层需要获取当前登录者的id然后根据登录者的id去库中搜索出为那些乘客购票如果乘客太多可以增加一个功能当乘客数量大于50时就不拿增加乘客了controller直接增加接口查询即可。对于前端增加一个响应式变量passenger,增加一个handleQueryPassen-ger,方法这个方法调用后端接口得到后给响应式变量赋值即初始化时直接查询。 对于选择乘客在js部分增加了const passengerOptions ref([]); const passengerChecks ref([]);表示选项和选择由于乘客带有的属性过多因此可以在handleQueryPassenger方法中增加lable和value分别表示看到的值以及实际操作的值。勾选完乘客后需要为乘客构造购票数据。由于一次不仅仅勾选一个乘客因此可以引入watch实时监控勾选的变化用来显示购票的界面。
// 购票列表用于界面展示并传递到后端接口用来描述哪个乘客购买什么座位的票const tickets ref([]);// 勾选或去掉某个乘客时在购票列表中加上或去掉一张表watch(() passengerChecks.value, (newVal, oldVal){console.log(勾选乘客发生变化, newVal, oldVal)// 每次有变化时把购票列表清空重新构造列表tickets.value [];passengerChecks.value.forEach((item) tickets.value.push({passengerId: item.id,passengerType: item.type,seatTypeCode: seatTypes[0].code,passengerName: item.name,passengerIdCard: item.idCard}))}, {immediate: true});
最后选择是勾选乘客后提交显示购票列表确认框进行最后的核对。此时购票的选座展示效果完毕。 选座规则
只有全部是一等座或全部是二等座才支持选座余票小于20张时不允许选座
选座效果
显示两排一等座每排4个二等座每排5个为什么是两排只是一个自定义的规则可以3排进行显示由自己规定。每排的座位是由枚举座位类型得到的对于12等座的划分根据枚举中的type值即可进行得到。之后构造两个响应式变量chooseSeatType和chooseSeatObj,其中chooseSeatType是表示是否支持选座以及选择的类型chooseSeatObj表示用户选择的座位是那些默认为false选择之后为true,通过读这个对象就知道用户选择了什么座位。经过选座就可以得到tickets其中有乘客id,乘客类型座位类型乘客姓名身份证实际座位。当没有选座时实际座位为空由系统来分配从一号开始找未被购买就选座。选座以购买两张一等座AC为例:遍历一等座车厢每个车厢从1号座位开始找A列座位未被购买的就预选中它;再挑它旁边的C如果也未被购买则最终选中这两个座位如果B已被购买则回到第一步继续找未被购买的A座。再挑它旁边的C这个应该怎么写可以从第二个座位开始需要计算和第一个座位的偏移值不需要再从1位置开始找提高选座效率。
前端的选座效果
首先是要考虑这个车票能不能选例如现在还有5张票共有7个人来买票这肯定是不行的因此可以在前端增加一层校验来检验余票是否足够可以减小后端的压力。这步是预扣减库存只是用来校验所有拷贝出临时变量来扣减即点击提交是预扣减库存实际提交才是真正扣减库存 // 校验余票是否充足购票列表中的每个座位类型都去车次座位余票信息中看余票是否充足// 前端校验不一定准但前端校验可以减轻后端很多压力// 注意这段只是校验必须copy出seatTypesTemp变量来扣减用原始的seatTypes去扣减会影响真实的库存let seatTypesTemp Tool.copy(seatTypes);for (let i 0; i tickets.value.length; i) {let ticket tickets.value[i];for (let j 0; j seatTypesTemp.length; j) {let seatType seatTypesTemp[j];// 同类型座位余票-1这里扣减的是临时copy出来的库存不是真正的库存只是为了校验if (ticket.seatTypeCode seatType.code) {seatType.count--;if (seatType.count 0) {notification.error({description: seatType.desc 余票不足});return;}}}}console.log(前端余票校验通过);
开始选座
响应式变量chooseSeatType首先是0表示不支持选座然后根据座位类型选择对应的列赋值给SEAT_COL_ARRAY之后对两排的座位进行初始化赋值为false由于规定不能同时选择1和2等座所有开始选座之前先进行去重如果多于1中返回选座不成功否则的话根据类型进行选座。最后进行界面优化增加选座的按钮这里注意如果是选择一个人进行购票这里采用只显示一排按钮。回到选择的函数中来增加一个约定余票小于20张时不允许选座。最后提交时计算出每个用户的座位选择代码如下
const handleOk () {console.log(选好的座位, chooseSeatObj.value);// 设置每张票的座位// 先清空购票列表的座位有可能之前选了并设置座位了但选座数不对被拦截了又重新选一遍for (let i 0; i tickets.value.length; i) {tickets.value[i].seat null;}let i -1;// 要么不选座位要么所选座位应该等于购票数即i (tickets.value.length - 1)for (let key in chooseSeatObj.value) {if (chooseSeatObj.value[key]) {i;if (i tickets.value.length - 1) {notification.error({description: 所选座位数大于购票数});return;}// 实际的赋值tickets.value[i].seat key;}}if (i -1 i (tickets.value.length - 1)) {notification.error({description: 所选座位数小于购票数});return;}console.log(最终购票, tickets.value);}
后端选座接口 前面的余票信息表是根据购票表来进行得到的但是购买完成票之后还需要进行落表无论是否成功。需要哪一个人购的票表示当前访问这个接口的是哪一个会员还需要日期车次出发站和到达站以及这些基础信息这些信息就可以唯一定位到余票信息这张表就可以判断它的一等座二等座等的余票信息了。余票id字段也可以和上面的余票表进行关联。由于订单状态不一定成功因此需要订单的状态车票可以做成json,也可以做成子表。 开发接口的话那么传入的参数是什么可以参考设计的表接口进来之后就应该数据落表那么表中的数据如何来其中member_id可以从线程本地变量获取日期车次出发站到达站和车票都可以从前端获取其中车票可以把json映射成Java类这样子操作更加的方便。因为需要车票进行选座用json操作不太方便。订单状态是由程序根据不同的步骤进行落库因此不用管。首先要做的是添加车票类ConfrimOrderTicketReq即购买车票的信息接受前端传来的对象。之后要构造一个订单类方便入库。之后在controller层增加doConfirm接口最后在service层增加相关保存购票信息的方法。最后前端调用后端接口。 重点的话是会员模块的service层的保存订单方法doConfirm如何实现。
保存确认订单表状态初始对于id,直接使用雪花算法时间使用当前的时间memberid使用登录人的id,像traincode,date,start和end一次ticket都是从前端获取的之前保存到了ConfirmOrderReq从这里直接获取即可注意对于ticket来说需要将json字符串转化为车票类查出余票记录得到真实的库存。由于唯一键是日期车次起始和终点站这样子构造号条件进行查询。 public DailyTrainTicket selectByUnique(Date date, String trainCode,String start,String end) {DailyTrainTicketExample dailyTrainTicketExample new DailyTrainTicketExample();dailyTrainTicketExample.createCriteria().andDateEqualTo(date).andTrainCodeEqualTo(trainCode).andStartEqualTo(start).andEndEqualTo(end);ListDailyTrainTicket list dailyTrainTicketMapper.selectByExample(dailyTrainTicketExample);if(CollUtil.isNotEmpty(list)) {return list.get(0);}else {return null;}} 进行票数的预扣减由于前端的是实时显示到界面上因此需要一个变量而这里只要不更新到数据库怎么扣减都可以因此可以之间操作查出的库存记录。一张票一张票的循环进行扣减由于选择的可能是不同的座位类型不同的人因此不能按照列表进行扣票应该按照不同的座位类型进行扣票。 private static void reduceTickets(ConfirmOrderDoReq req, DailyTrainTicket dailyTrainTicket) {for (ConfirmOrderTicketReq ticketReq : req.getTickets()) {String seatTypeCode ticketReq.getSeatTypeCode();SeatTypeEnum seatTypeEnum EnumUtil.getBy(SeatTypeEnum::getCode, seatTypeCode);switch (seatTypeEnum) {case YDZ - {int countLeft dailyTrainTicket.getYdz() - 1;if(countLeft 0) {throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_TICKET_COUNT_ERROR);}dailyTrainTicket.setYdz(countLeft);}case EDZ - {int countLeft dailyTrainTicket.getEdz() - 1;if(countLeft 0) {throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_TICKET_COUNT_ERROR);}dailyTrainTicket.setEdz(countLeft);}case RW - {int countLeft dailyTrainTicket.getRw() - 1;if(countLeft 0) {throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_TICKET_COUNT_ERROR);}dailyTrainTicket.setRw(countLeft);}case YW - {int countLeft dailyTrainTicket.getYw() - 1;if(countLeft 0) {throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_TICKET_COUNT_ERROR);}dailyTrainTicket.setYw(countLeft);}}}} 偏移值的计算这里的偏移值指的是相对于第一个选座位置的偏移值这样子可以一次循环找到所有位置的值假设一个车厢50个座位A,B,C,D,E各10个现在A全部被买了如果现在选座A,C那么不会选座成功。对于第一个购票来说要么是成功要么不成功因此就可以根据第一个张票成功与否的情况判断后面的票是否能选即本次购票是否有选座。对于有选座的功能还需要偏移值进行计算得到的结果有空位算是选座成功。由于一等座和二等座每排位置不同还需要知道座位的类型之后组成和前端两排选座一样的列表用于作参照的座位列表需要两次循环因为有两排这一步就是座位的初始化。之后计算绝对的偏移值再根据第一个位置计算相对的偏移值 挑车厢对于购票没有选座的来说比较简单只要这个座位是可选的即可需要一张票一张票的去挑选。在买票之前首先要知道购买票的类型在哪一个车厢中因此需要是要写一个寻找车厢的方法根据日期车次和车票类型然后把上面的当作传入的参数就可以得到符合条件的车厢了之后在得到的车厢列表中一个个的寻找。 根据车厢挑座位根据获取车厢的方法获得符合条件的车厢之后现在得到的车厢都是一种票型了先获取起始车厢以及进入车厢前的座位列表座位列表可以根据日期车次以及车厢位置来获取因为一个车厢的座位类型是相同的然后就一个车厢一个车厢的寻找。下面的选座就是调用了本段写的getSeat方法在有选座的情况下需要知道第一个选座的实际列以及得到的偏移值根据这两个参数进行选座。在没有选座的情况并没有特定的列号也没有偏移值那就传null只是一个座位一个座位的选座。对于座位还应该进行排序根据座位索引进行排序。现如今插入车厢的座位后第一次需要一个座位一个座位的挑选写个循环看每个座位是否可卖可卖的话之间返回否则跳过。 判断是否可卖1表示在这个区间买过票了就不能够售票了。0表示在这个给区间没有卖票。例如sell10001本次购买的区间是1~4则区间应该售000这里是10001中间的三个0000要变成111那么之后可以根据或运算变成11111即10001|0111011111如果sell00001,那么按位或得到01111之后转为数字是15但再转成二进制是1111不是01111因此需要补0。 private boolean calSell(DailyTrainSeat dailyTrainSeat,Integer startIndex,Integer endIndex) {String sell dailyTrainSeat.getSell();String sellPart sell.substring(startIndex, endIndex);if(Integer.parseInt(sellPart) 0) {LOG.info(座位{}在本车站区间{}--{}已售过票不可选中该座位,dailyTrainSeat.getCarriageSeatIndex(),startIndex,endIndex);return false;}else {LOG.info(座位{}在本车站区间{}--{}未售过票可选中该座位,dailyTrainSeat.getCarriageSeatIndex(),startIndex,endIndex);// 111String curSell sellPart.replace(0, 1);// 0111curSell StrUtil.fillBefore(curSell,0, endIndex);curSell StrUtil.fillAfter(curSell,0,sell.length());// 当前区间售票信息curSell与库里的已售信息sell按位与即可得到该座位卖出此票后的售票详情// 32int newSellInt NumberUtil.binaryToInt(curSell) | NumberUtil.binaryToInt(sell);// 11111String newSell NumberUtil.getBinaryStr(newSellInt);newSell StrUtil.fillBefore(newSell,0,sell.length());LOG.info(座位{}在本车站区间{}--{}卖出该票后最终售票详情{},dailyTrainSeat.getCarriageSeatIndex(),startIndex,endIndex,newSell);dailyTrainSeat.setSell(newSell);return true;} 优化getSeat方法首先判断传入的column和拿到的col进行比较如果无值表示无选座有值需要判断是否可以匹配不匹配的话跳过。现在选完第一个座位后接下来根据偏移值选则后面几人的座位偏移值可能有多个从索引1开始0是以及选完的第一个座位进行循环下一个位置是索引偏移量然后根据是否超卖判断是否可选。还要注意选座是在同一个车厢根据下一个索引是否大于车厢座位数 保存最终的选座结果但不是更新到数据库中。此时用一个临时变量保存选择的座位当下一个选座时应该看这个选座的结果以及最终的选座结果这个最终结果是之前的结果如果此次选座成功那么就更新最终选座否则就出现挑选同一个座位的情况。例如系统分配座位的时候先分配座位3由于同一个人为不同人买多张票在进行第二张票购买前没有更新到数据库中导致下一个分配的还是3号座位这显然是不合理的因此需要对每一次选择的座位进行保存为了让下一次正确的挑选座位。对于选座的情况由于第一次选座成功的情况下可能之后根据偏移值选择的其他座位不成功如果直接保存的最终结果可能导致结果和符合的不一致因此也是需要保存到临时变量中注意没有成功选座时清空临时变量当两种情况都成功选座后才真正的保存到最终选座的变量中。 根据售卖信息更新座位售卖情况就是更新数据库的售卖信息例如从000更新到101.就是选好座位后将座位信息更新到日常座位表中。由于后面还需要涉及到修改余票为会员增加购票记录更新订单状态因此可以把他们称为选座后的事务处理。可以在最后修改数据库的时候增加事务这样子占用事务的时间较少否则的话占用大量的数据库资源。由于本垒方法间的调用事务不生效因此增加一个类专门进行处理。根据最终选票结果来处理。此时需要更新的是id以及售卖票的信息还要更新时间不必要更新表中所有的字段。 Transactionalpublic void afterDoConfirm(ListDailyTrainSeat finalSeatList) {for (DailyTrainSeat dailyTrainSeat: finalSeatList){DailyTrainSeat seatForUpdate new DailyTrainSeat();seatForUpdate.setId(dailyTrainSeat.getId());seatForUpdate.setSell(dailyTrainSeat.getSell());seatForUpdate.setUpdateTime(new Date());dailyTrainSeatMapper.updateByPrimaryKeySelective(seatForUpdate);}} 扣减库存很重要售卖一张票影响的是多个区间的库存就是本次选座之前没卖过票的并且本次购买的区间有交集的区间怎么理解如下图 由于座位区间2没有卖过票而且AD和AE与购买的CD区间有交集因此减库存。 由于 座位区间1已经卖过票了因此不需要减库存。
因此先计算区间然后根据区间来进行扣减库存。需要计算出最大最小开始结束的影响区间4个参数。 这里买了4(startIndex)到7(endIndex)站的票购买区间下标7不更新是因为在第七站下车不会影响第七站的购票首先看最小开始影响的下标这里是3因此minStartIndex startIndex - 往前碰0到的最后一个0由于这里购买7往后不会前面的影响库存因此maxStratIndex endIndex - 1表示在[minStartIndex,maxStartIndex]这个区间开始的都会影响其他库存。如果是在3下标结束不会影响其他库存但是4下标开始有影响即minEndIndex startIndex1,同理maxEndIndexendIndex 往后碰0到的最后一个0表示在[minEndIndex,maxEndIndex]这个区间结束都会影响库存。
Integer startIndex dailyTrainTicket.getStartIndex();
Integer endIndex dailyTrainTicket.getEndIndex();
char[] chars seatForUpdate.getSell().toCharArray();
Integer maxStartIndex endIndex - 1;
Integer minEndIndex startIndex 1;
Integer minStartIndex 0;
for (int i startIndex - 1; i 0; i--) {char aChar chars[i];if(aChar 1) {minStartIndex i 1;break;}
}
LOG.info(影响出发站区间minStartIndex-maxStartIndex);
Integer maxEndIndex seatForUpdate.getSell().length();
for (int i endIndex; i seatForUpdate.getSell().length(); i) {char aChar chars[i];if(aChar 1) {maxEndIndex i;break;}
}
LOG.info(影响结束站区间minEndIndex-maxEndIndex);
dailyTrainTicketMapperCust.updateCountBySell(dailyTrainSeat.getDate(),dailyTrainSeat.getTrainCode(),dailyTrainSeat.getSeatType(),minStartIndex,maxStartIndex,minEndIndex,maxEndIndex);
之后根据这四个值进行库存的更新。
对乘客增加车票表由于之前的购票表订单状态由可能为失败而且信息不容易搜索因此新建一张表用来保存乘客购买车票成功的信息由于每个会员经常查自己购买的车票因此可以把会员id当作索引。由于生成的表在member模块购票业务在business模块当business模块购票成功后调用member模块的接口把数据传入这里使用的了feign。对于会员车票参数来说在business模块需要调用它进行车票的构造number模块需要调用它进行入库因此可以放到common模块。要启用feign需要在调用方buiness增加依赖之后在启动类配置路径表示哪个包是属于feign的之后在相关的路径增加一个接口路径配置是调用的哪个包下的接口。
之后在business模块就可以调用member的接口为会员乘客增加一张票。之后可以为会员段增加我的车票方便查看车票。但这里需要根据会员的id查看只能够查看自己买的车票。
最后更新订单状态为成功根据id更新 更新时间以及状态