2021春节技术比赛之转件存储设计
在2021/02/23 16:43上被z yg修改 编辑 创建Relations:
一、题目背景
由于公司业务发展,不断有新的业务线加入。
新的业务线加入就会有新的配套信息系统来支撑。
目前我们信息部支撑宅急送物流快递业务操作系统,供应链/仓储业务操作系统,领送相关业务操作系统。
三条业务线都有各自的特点,但每条业务线又有相似之处。
作为实现业务信息化的我们要支撑业务需要,同时也在提高自己。
目前三条业务线的相似之处就是都要把货物转给第三方承运商,
我们的下游承运商可能是京东快递,顺丰,申通,圆通,韵达等等,当然也包括宅急送自己在内!
这样就带来的一个问题,我们不可能一直将三条业务线的系统与第三方承运商的物流运输平台进行对接信息。
所以我们要打造一个平台,一个能支撑三条业务线的“转件”平台
二、题目浅析
作为一个所谓的“转件”平台上游可以接收各条业务线产生的订单
下游对接各个承运商。
同时承运商本身也可以是上游订单的生产者。
“转件”平台起到承上启下与资源整合的作用。
所有的订单和状态都要经过“转件”平台,而且一个订单或者运单可能多次经过转件平台。
如下所示
例如仓储产生了一个订单,订单号为C_01,经过转件平台转给领送,领送分配给C_01的订单的运单号为L_01,在我们的转件系统产生如下一条数据
由于领送(我们假设领送有配送能力)配送能力有限会再次进行转件操作
将L_01这个运单再次通过转件平台转给宅急送,宅急送分配给L_01这个订单(下游系统认为领送下的是订单而非运单)的运单号是Z_01
再一次在我们的系统里产生一条如下数据
同样宅急送又一次转给了邮政,同样也产生了如下一条数据
这样就将一个具体的实物订单经过多次转件之后至少再“转件”平台产生了3条数据
接下来说关于订单/运单状态的情况
订单通过“转件”平台传递给下游第三方承运商,同时承运商也要回传订单或运单的状态和跟踪轨迹
上游的业务线需要通过转件平台接收状态和轨迹信息
如果我们的订单或者运单出现了两次以上转件,仓储转给领送,领送又转给了宅急送,宅急送又转给了邮政
仓储系统需要所有的物流跟踪轨迹数据,转件平台会回传所有的数据
宅急送转件给邮政,这个时候邮政需要将状态信息通过“转件”平台回传给宅急送
同样宅急送也需要将领送订单的状态轨迹信息回传给领送
一个订单最后到收货人手里经过了三次转件
每个承运商都负责了其中一段运输路线
上游系统需要下游系统所有的物流跟踪轨迹
到这里“转件”平台出现了两张表 运单表和状态轨迹表
那么问题来了!比赛题目是什么那?如下
三、具体题目
根据上面的业务描述和理解给出具体的下单数据库存储和状态轨迹数据存储的设计并实现对应的微服务
其中微服务API实现包括订单接收、轨迹接收、轨迹查询3个API。
订单接收和状态轨迹数据格式为定义的标准格式(稍后公布)
轨迹查询条件为任意上下游单号(例如:C_01、L_01、Z_01、Y_01)返回全流程按时间升序的轨迹信息
四、技术选型范围
持久性存储选型:mongodb、elasticsearch、mysql
编程语言:JAVA(版本1.8及以上)
五、注意事项及时间安排
仔细理解业务需求,在规定的时间和技术栈完成符合标准的设计和实现
具体API的数据结构稍后给出。可以单人参赛也可以多人组队。
稍后找时间进行统一讲解一下
(具体比赛时间等过了春节之后再定,应该在2021年2月份之前完成)
六、测试评比规则及流程
评比规则:
下单API的平均TPS*30%+状态回传API的平均TPS*30%+状态查询API的平均TPS*40%=最终结果(不使用)
下单API100万条总时长*30%+状态回传API1000万条总时长*30%+状态查询API100万次查询总时长*40%=最终结果(使用)
以最终结果进行排名,TopN名获得相应奖励(TPS是最终结果越大越好,时长是最终结果越小越好)
如果出现比赛结果相同现象将进行复赛
复赛以平均TPS总和优异者获胜
基本比赛流程如下:
1、下单接口的调用执行
2、对应下单数据的状态信息调用执行
3、对应状态信息查询调用执行
数据提前预设好结构一致,请求次数与条数一致
以下情况视为自动退赛:
1、没有充分理解业务需求,开发程序无任何参考价值的
2、没有按时参加比赛的
3、以一切手段作弊的(比如:抄袭其他参赛设计或代码,开源代码不算,主动交流的不算)
4、不按规则流程执行捣乱的
以下2021-02-23日补充
根据昨天(2021-02-22)开会讨论整理了一份比赛流程和具体规则
下单API100万条总时长*30%+状态回传API1000万条总时长*30%+状态查询API100万次查询总时长*40%=最终结果
(实际数据不止100万和1000万这里是大约数字)
每个参赛选手严格按以下流程执行
1、数据预添加(jmeter执行)
2、数据校验(人工对预添加数据进行校验)
1)条数和字段数据是否一致并且正确
(订单API接收的数据和状态API接收的数据是否和请求时的一致,
就是请求给你的字段值数据都要存怎么存不管)
2)查询数据结构是否正确(postman执行,排序并有必须字段)
3、执行正式比赛程序
记录结果数据
4、清理数据
如果出现TopN比赛结果一致情况将启动下一轮比赛
按最终TPS高者获胜
具体API规范(以下样例仅API接口交互规则作为标准,实际请求为以http post请求,json格式,详细数据在body中。更明确的是这里只规定了http协议数据包格式,其他比如序列化等组件,model实体都可以自己设计)
import java.util.ArrayList;import java.util.Date;
import java.util.List;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BiSaiController {
/**
* 创建订单
* 接口实体类为内部类,这里只是做个样例看,实际使用的时候可能调用不到
* @param or
* @return
*/
@PostMapping("/createorder")
public ReturnRoot createOrder(@RequestBody OrderRoot or) {
//解析数据
//保存数据库
//返回必要的信息
return new ReturnRoot();
}
/**
* 创建状态
* 接口实体类为内部类,这里只是做个样例看,实际使用的时候可能调用不到
* @param or
* @return
*/
@PostMapping("/createstatus")
public ReturnStatus createStatus(@RequestBody StatusRoot sr) {
//解析数据
//保存数据库
//返回必要的信息
return new ReturnStatus();
}
/**
* 状态查询
* 接口实体类为内部类,这里只是做个样例看,实际使用的时候可能调用不到
* @param waybillorordernumber 运单号或订单号
* @return
*/
@PostMapping("/querystatus")
public List<Traces> queryStatus(@RequestBody String waybillorordernumber) {
//解析数据
//查询数据库
//返回查询的信息
return new ArrayList<Traces>();
}
//-------订单相关实体类-----------------------------------------------------------------------------------------
class OrderRoot {
private String resourceTypeName;
private AccountInfo accountInfo;
private String sourceCode;
private String orderType;
private String resourceCode;
private String orderNo;
private String mailNo;
private String goodsName;
private String goodsNum;
private String goodsWeight;
private String goodsVolume;
private String remarks;
private String goodsValue;
private String codFlag;
private String codAmount;
private String extendedInfo;
private Sender sender;
private Receiver receiver;
public void setResourceTypeName(String resourceTypeName) {
this.resourceTypeName = resourceTypeName;
}
public String getResourceTypeName() {
return resourceTypeName;
}
public void setAccountInfo(AccountInfo accountInfo) {
this.accountInfo = accountInfo;
}
public AccountInfo getAccountInfo() {
return accountInfo;
}
public void setSourceCode(String sourceCode) {
this.sourceCode = sourceCode;
}
public String getSourceCode() {
return sourceCode;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getOrderType() {
return orderType;
}
public void setResourceCode(String resourceCode) {
this.resourceCode = resourceCode;
}
public String getResourceCode() {
return resourceCode;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public String getOrderNo() {
return orderNo;
}
public void setMailNo(String mailNo) {
this.mailNo = mailNo;
}
public String getMailNo() {
return mailNo;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public String getGoodsName() {
return goodsName;
}
public void setGoodsNum(String goodsNum) {
this.goodsNum = goodsNum;
}
public String getGoodsNum() {
return goodsNum;
}
public void setGoodsWeight(String goodsWeight) {
this.goodsWeight = goodsWeight;
}
public String getGoodsWeight() {
return goodsWeight;
}
public void setGoodsVolume(String goodsVolume) {
this.goodsVolume = goodsVolume;
}
public String getGoodsVolume() {
return goodsVolume;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public String getRemarks() {
return remarks;
}
public void setGoodsValue(String goodsValue) {
this.goodsValue = goodsValue;
}
public String getGoodsValue() {
return goodsValue;
}
public void setCodFlag(String codFlag) {
this.codFlag = codFlag;
}
public String getCodFlag() {
return codFlag;
}
public void setCodAmount(String codAmount) {
this.codAmount = codAmount;
}
public String getCodAmount() {
return codAmount;
}
public void setExtendedInfo(String extendedInfo) {
this.extendedInfo = extendedInfo;
}
public String getExtendedInfo() {
return extendedInfo;
}
public void setSender(Sender sender) {
this.sender = sender;
}
public Sender getSender() {
return sender;
}
public void setReceiver(Receiver receiver) {
this.receiver = receiver;
}
public Receiver getReceiver() {
return receiver;
}
}
class AccountInfo {
private String siteCode;
private String customerName;
public void setSiteCode(String siteCode) {
this.siteCode = siteCode;
}
public String getSiteCode() {
return siteCode;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getCustomerName() {
return customerName;
}
}
class Sender {
private String sendName;
private String sendPro;
private String sendCity;
private String sendDistrict;
private String sendAddress;
private String sendPhone;
private String sendMobile;
public void setSendName(String sendName) {
this.sendName = sendName;
}
public String getSendName() {
return sendName;
}
public void setSendPro(String sendPro) {
this.sendPro = sendPro;
}
public String getSendPro() {
return sendPro;
}
public void setSendCity(String sendCity) {
this.sendCity = sendCity;
}
public String getSendCity() {
return sendCity;
}
public void setSendDistrict(String sendDistrict) {
this.sendDistrict = sendDistrict;
}
public String getSendDistrict() {
return sendDistrict;
}
public void setSendAddress(String sendAddress) {
this.sendAddress = sendAddress;
}
public String getSendAddress() {
return sendAddress;
}
public void setSendPhone(String sendPhone) {
this.sendPhone = sendPhone;
}
public String getSendPhone() {
return sendPhone;
}
public void setSendMobile(String sendMobile) {
this.sendMobile = sendMobile;
}
public String getSendMobile() {
return sendMobile;
}
}
class Receiver {
private String receiveName;
private String receivePro;
private String receiveCity;
private String receiveDistrict;
private String receiveAddress;
private String receivePhone;
private String receiveMobile;
public void setReceiveName(String receiveName) {
this.receiveName = receiveName;
}
public String getReceiveName() {
return receiveName;
}
public void setReceivePro(String receivePro) {
this.receivePro = receivePro;
}
public String getReceivePro() {
return receivePro;
}
public void setReceiveCity(String receiveCity) {
this.receiveCity = receiveCity;
}
public String getReceiveCity() {
return receiveCity;
}
public void setReceiveDistrict(String receiveDistrict) {
this.receiveDistrict = receiveDistrict;
}
public String getReceiveDistrict() {
return receiveDistrict;
}
public void setReceiveAddress(String receiveAddress) {
this.receiveAddress = receiveAddress;
}
public String getReceiveAddress() {
return receiveAddress;
}
public void setReceivePhone(String receivePhone) {
this.receivePhone = receivePhone;
}
public String getReceivePhone() {
return receivePhone;
}
public void setReceiveMobile(String receiveMobile) {
this.receiveMobile = receiveMobile;
}
public String getReceiveMobile() {
return receiveMobile;
}
}
class ReturnRoot {
private String resourceCode;
private String success;
private String reason;
private String orderNo;
private String mailNo;
private String consigneeBranchCode;
private String packageCenterCode;
private String packageCenterName;
private String firstCode;
private String secondCode;
private String thirdCode;
public void setResourceCode(String resourceCode) {
this.resourceCode = resourceCode;
}
public String getResourceCode() {
return resourceCode;
}
public void setSuccess(String success) {
this.success = success;
}
public String getSuccess() {
return success;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getReason() {
return reason;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public String getOrderNo() {
return orderNo;
}
public void setMailNo(String mailNo) {
this.mailNo = mailNo;
}
public String getMailNo() {
return mailNo;
}
public void setConsigneeBranchCode(String consigneeBranchCode) {
this.consigneeBranchCode = consigneeBranchCode;
}
public String getConsigneeBranchCode() {
return consigneeBranchCode;
}
public void setPackageCenterCode(String packageCenterCode) {
this.packageCenterCode = packageCenterCode;
}
public String getPackageCenterCode() {
return packageCenterCode;
}
public void setPackageCenterName(String packageCenterName) {
this.packageCenterName = packageCenterName;
}
public String getPackageCenterName() {
return packageCenterName;
}
public void setFirstCode(String firstCode) {
this.firstCode = firstCode;
}
public String getFirstCode() {
return firstCode;
}
public void setSecondCode(String secondCode) {
this.secondCode = secondCode;
}
public String getSecondCode() {
return secondCode;
}
public void setThirdCode(String thirdCode) {
this.thirdCode = thirdCode;
}
public String getThirdCode() {
return thirdCode;
}
}
//-------订单相关实体类-----------------------------------------------------------------------------------------
//-------状态轨迹相关实体类-----------------------------------------------------------------------------------------
class StatusRoot {
private String sourceNumber;
private String companyCode;
private String companyName;
private String orderNumber;
private String businessType;
private List<Traces> traces;
public void setSourceNumber(String sourceNumber) {
this.sourceNumber = sourceNumber;
}
public String getSourceNumber() {
return sourceNumber;
}
public void setCompanyCode(String companyCode) {
this.companyCode = companyCode;
}
public String getCompanyCode() {
return companyCode;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getCompanyName() {
return companyName;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
public String getOrderNumber() {
return orderNumber;
}
public void setBusinessType(String businessType) {
this.businessType = businessType;
}
public String getBusinessType() {
return businessType;
}
public void setTraces(List<Traces> traces) {
this.traces = traces;
}
public List<Traces> getTraces() {
return traces;
}
}
class Traces {
private String countryCode;
private String timeZone;
private Date operatingTime;
private String statusDesc;
private String action;
private String state;
private String city;
private String district;
private String street;
private String pointType;
private String pointNumber;
private String pointName;
private String pointContact;
private String nextStation;
private String nextType;
private String nextCode;
private String nextName;
private String operator;
private String operatorContact;
private String receiver;
private String exceptDesc;
private String remark;
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getCountryCode() {
return countryCode;
}
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getTimeZone() {
return timeZone;
}
public void setOperatingTime(Date operatingTime) {
this.operatingTime = operatingTime;
}
public Date getOperatingTime() {
return operatingTime;
}
public void setStatusDesc(String statusDesc) {
this.statusDesc = statusDesc;
}
public String getStatusDesc() {
return statusDesc;
}
public void setAction(String action) {
this.action = action;
}
public String getAction() {
return action;
}
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setCity(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setDistrict(String district) {
this.district = district;
}
public String getDistrict() {
return district;
}
public void setStreet(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
public void setPointType(String pointType) {
this.pointType = pointType;
}
public String getPointType() {
return pointType;
}
public void setPointNumber(String pointNumber) {
this.pointNumber = pointNumber;
}
public String getPointNumber() {
return pointNumber;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
public String getPointName() {
return pointName;
}
public void setPointContact(String pointContact) {
this.pointContact = pointContact;
}
public String getPointContact() {
return pointContact;
}
public void setNextStation(String nextStation) {
this.nextStation = nextStation;
}
public String getNextStation() {
return nextStation;
}
public void setNextType(String nextType) {
this.nextType = nextType;
}
public String getNextType() {
return nextType;
}
public void setNextCode(String nextCode) {
this.nextCode = nextCode;
}
public String getNextCode() {
return nextCode;
}
public void setNextName(String nextName) {
this.nextName = nextName;
}
public String getNextName() {
return nextName;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getOperator() {
return operator;
}
public void setOperatorContact(String operatorContact) {
this.operatorContact = operatorContact;
}
public String getOperatorContact() {
return operatorContact;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getReceiver() {
return receiver;
}
public void setExceptDesc(String exceptDesc) {
this.exceptDesc = exceptDesc;
}
public String getExceptDesc() {
return exceptDesc;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getRemark() {
return remark;
}
}
class ReturnStatus {
private int state;
private String reason;
public void setState(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getReason() {
return reason;
}
}
//-------状态轨迹相关实体类-----------------------------------------------------------------------------------------
}
http请求json标准样例
订单
{"resourceTypeName": "快速递",
"accountInfo": {
"siteCode": "A001",
"customerName": "555111"
},
"sourceCode": "801",
"orderType ": "00",
"resourceCode": "JD",
"orderNo": "ZJS861520269945",
"mailNo": "JDVB07604780549",
"goodsName": "服装",
"goodsNum": "999",
"goodsWeight": "50000",
"goodsVolume": null,
"remarks": null,
"goodsValue": "0",
"codFlag": "否",
"codAmount": "0",
"extendedInfo": null,
"sender": {
"sendName": "PQ 金月",
"sendPro": "北京市",
"sendCity": "北京市",
"sendDistrict": "朝阳区",
"sendAddress": "北京市朝阳区三里屯",
"sendPhone": null,
"sendMobile": "325038"
},
"receiver": {
"receiveName": null,
"receivePro": "北京市",
"receiveCity": "北京市",
"receiveDistrict": "东城区",
"receiveAddress": null,
"receivePhone": null,
"receiveMobile": "0000000"
}
}
返回样例
{
"resourceCode": "123",
"success": "true",
"reason": "请求成功",
"orderNo": "ZJS861706963526",
"mailNo": "JDVB07604780549",
"consigneeBranchCode": "B07",
"packageCenterCode": "HB01",
"packageCenterName": "华北运转中心",
"firstCode": "010",
"secondCode": "BB07",
"thirdCode": "1001"
}
状态
{"sourceNumber": "123456789",
"companyCode": "ems",
"companyName": "邮政",
"orderNumber": "ZJS111887059675",
"businessType": "2",
"traces": [
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2019-01-01 00:00:00",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
}
]
}
返回
{"state":0,"reason":""}
查询
{"orderorwillnum": "LS1000000200022"
}
返回
[
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-02-27T19:27:03",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
},
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-03-14T15:19:02",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
},
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-03-15T17:26:54",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
},
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-03-16T03:21:46",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
},
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-03-21T15:08:52",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
},
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-03-26T18:02:58",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
},
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-04-03T20:25:52",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
},
{
"countryCode": "CN",
"timeZone": "8",
"operatingTime": "2021-04-08T11:49:44",
"statusDesc": "",
"action": "T_ARRIVAL",
"state": "浙江省",
"city": "杭州市",
"district": "西湖区",
"street": "五常街道",
"pointType": "2",
"pointNumber": "123",
"pointName": "XX 分拨站",
"pointContact": "",
"nextStation": "上海市",
"nextType": "2",
"nextCode": "456",
"nextName": "XX 分拨站",
"operator": "王 XX",
"operatorContact": "",
"receiver": "王 XX",
"exceptDesc": "",
"remark": ""
}
]
七、奖品
价值1000+RMB的 三星 (SAMSUNG) 27英寸 1800R曲面 FHD高清 爱眼 窄边框 FreeSync 可壁挂游戏电脑显示器
希望牛逼的你快来拿下他
同款链接 https://item.jd.com/100003374425.html
就是下面我用的这款,有兴趣可以来看看