quantum.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. <template>
  2. <view>
  3. <u-navbar :title="headline" autoBack placeholder></u-navbar>
  4. <view class="card_stamp">
  5. <view class="title_bluetooth">匹配蓝牙设备</view>
  6. <view class="center_in">
  7. <x-radar :BlueState="BlueState"></x-radar>
  8. </view>
  9. <view class="nearby_title">{{nearbyTitle}}</view>
  10. <view class="search_card">
  11. <u-button style="width: 200rpx;" size="small" type="warning" :text="searchTitle"
  12. @click="openBluetoothAdapter(searchType)"></u-button>
  13. </view>
  14. <view class="waybill_num">运单号: {{waybillNo}}</view>
  15. <view class="waybill_numil" v-if="printType == 'record'">请选择运单温湿度时间段</view>
  16. <view class="card_waybill" v-for="(item,index) in timeQuantumList" :key="index" @click="selectChange(item)">
  17. <x-checkbox :label="item.title" :isChecked="item.isChecked"></x-checkbox>
  18. <view class="time_title">{{item.startTime}}</view>
  19. <view class="time_title">{{item.endTime}}</view>
  20. </view>
  21. <view class="card_bluetooth" v-if="pairedDeviceList.length > 0">
  22. <view class="equipment_title">已配对设备</view>
  23. <view class="card_equipment">
  24. <x-bluetooth :list="pairedDeviceList" text="打印" btnType="success" @connect="getPrint"></x-bluetooth>
  25. </view>
  26. </view>
  27. <view class="card_bluetooth">
  28. <view class="equipment_title">可连接设备</view>
  29. <view class="card_equipment">
  30. <x-bluetooth :list="devices" @connect="connect"></x-bluetooth>
  31. </view>
  32. </view>
  33. </view>
  34. </view>
  35. </template>
  36. <script>
  37. import {
  38. printList
  39. } from './waybill.js'
  40. import PrinterJobs from './gprint/printerjobs.js'
  41. import printerUtil from './gprint/printerutil.js'
  42. import util from './gprint/util.js'
  43. import drawQrcode from './gprint/weapp.qrcode.esm.js'
  44. import getCode128 from './gprint/code128'
  45. export default {
  46. data() {
  47. return {
  48. headline: '',
  49. barCodeShow: false,
  50. pairedDeviceList: [],
  51. matchingUnit: {},
  52. BlueState: true,
  53. nearbyTitle: '使用蓝牙设备打印...',
  54. searchTitle: '开始搜索',
  55. searchType: false,
  56. devices: [],
  57. deviceId: null,
  58. serviceId: null,
  59. characteristicId: null,
  60. waybillNo: '',
  61. printType: '',
  62. waybillList: {},
  63. humitureData: [],
  64. maxData: [],
  65. timeQuantumList: [],
  66. checkboxValue: [],
  67. userInfo: {},
  68. }
  69. },
  70. onLoad(value) {
  71. const arr = this.$cache.getCache('commodity')
  72. this.waybillList = JSON.parse(arr)
  73. var userInfo = this.$cache.getCache('userInfo')
  74. this.userInfo = userInfo
  75. if (value.printType == 'barCode') {
  76. this.headline = '条码打印'
  77. } else if (value.printType == 'record') {
  78. this.headline = '温湿度记录打印'
  79. this.getHumiture(value.waybillNo)
  80. }
  81. this.waybillNo = value.waybillNo
  82. this.printType = value.printType
  83. },
  84. methods: {
  85. openBluetoothAdapter(value) {
  86. var that = this
  87. if (value) {
  88. that.BlueState = true
  89. that.searchTitle = '开始搜索'
  90. that.nearbyTitle = '已停止蓝牙查找附近设备...'
  91. that.searchType = false
  92. } else {
  93. that.BlueState = false
  94. console.log('开始搜索')
  95. that.searchTitle = '停止搜索'
  96. that.nearbyTitle = '正通过蓝牙查找附近设备...'
  97. that.searchType = true
  98. uni.openBluetoothAdapter({ //打开蓝牙适配器接口
  99. success: (res) => { //已打开
  100. that.onDevice() //监听寻找到新设备的事件
  101. uni.getBluetoothAdapterState({ //获取本机蓝牙适配器状态
  102. success: function(res) {
  103. // console.log(res)
  104. if (res.available) {
  105. //搜索蓝牙
  106. //开始搜寻附近的蓝牙外围设备
  107. console.log("开始搜寻附近的蓝牙外围设备")
  108. uni.startBluetoothDevicesDiscovery({
  109. success(res) {
  110. console.log(res)
  111. }
  112. })
  113. } else {
  114. console.log('本机蓝牙不可用')
  115. }
  116. },
  117. })
  118. },
  119. fail: err => { //未打开
  120. uni.showToast({
  121. icon: 'none',
  122. title: '查看手机蓝牙是否打开'
  123. });
  124. }
  125. })
  126. }
  127. },
  128. onDevice() {
  129. var that = this
  130. //监听寻找到新设备的事件
  131. uni.onBluetoothDeviceFound(function(devices) {
  132. var re = JSON.parse(JSON.stringify(devices))
  133. if (re.devices[0].name != '') {
  134. let deviceId = re.devices[0].deviceId
  135. let name = re.devices[0].name
  136. that.devices.push({
  137. name: name,
  138. deviceId: deviceId,
  139. services: []
  140. })
  141. for (let i = 0; i < that.devices.length; i++) {
  142. for (let j = i + 1; j < that.devices.length; j++) {
  143. if (that.devices[i].deviceId == that.devices[j].deviceId) {
  144. that.devices.splice(j, 1);
  145. j--;
  146. }
  147. }
  148. }
  149. that.devices = that.devices
  150. }
  151. })
  152. },
  153. stopFindBule() {
  154. const that = this
  155. uni.stopBluetoothDevicesDiscovery({
  156. success: e => {
  157. that.searchTitle = '开始搜索'
  158. that.nearbyTitle = '已停止蓝牙查找附近设备...'
  159. that.searchType = false
  160. that.BlueState = true
  161. console.log('停止搜索蓝牙设备:' + e.errMsg);
  162. },
  163. fail: e => {
  164. console.log('停止搜索蓝牙设备失败,错误码:' + e.errCode);
  165. }
  166. });
  167. },
  168. connect(value) {
  169. // console.log(value, 66)
  170. this.createBLEConnection(value)
  171. },
  172. // item 是要连接的设备数据
  173. createBLEConnection(item) {
  174. let that = this;
  175. that.matchingUnit.deviceId = item.deviceId
  176. uni.showLoading({
  177. title: "连接中,请稍等",
  178. mask: true,
  179. });
  180. uni.createBLEConnection({
  181. deviceId: item.deviceId,
  182. success(res) {
  183. that.stopFindBule(); // 停止搜索蓝牙
  184. setTimeout(function() {
  185. that.getBLEDeviceServices(item); // 获取蓝牙的服务
  186. }, 2000)
  187. },
  188. fail(res) {
  189. uni.showToast({
  190. title: item.name + "蓝牙连接失败",
  191. icon: "none",
  192. });
  193. uni.hideLoading()
  194. }
  195. });
  196. },
  197. getBLEDeviceServices(item) {
  198. const that = this
  199. setTimeout(() => {
  200. uni.getBLEDeviceServices({
  201. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  202. deviceId: item.deviceId,
  203. complete(res) {
  204. let serviceId = ""
  205. if (res.services.length > 0) {
  206. for (var s = 0; s < res.services.length; s++) {
  207. let serviceId = res.services[s].uuid
  208. that.matchingUnit.serviceId = serviceId
  209. uni.getBLEDeviceCharacteristics({ //获取蓝牙设备某个服务中所有特征值(characteristic)
  210. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  211. deviceId: item.deviceId,
  212. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  213. serviceId: serviceId,
  214. success(res) {
  215. // console.log('获取服务成功')
  216. that.pairedDeviceList = []
  217. that.pairedDeviceList.push(item)
  218. var re = JSON.parse(JSON.stringify(res))
  219. for (var c = 0; c < re.characteristics.length; c++) {
  220. if (re.characteristics[c].properties.write ==
  221. true) {
  222. let uuid = re.characteristics[c].uuid
  223. that.matchingUnit.characteristicId = uuid
  224. break
  225. }
  226. }
  227. uni.hideLoading()
  228. }
  229. })
  230. }
  231. } else {
  232. uni.hideLoading()
  233. }
  234. },
  235. fail(res) {
  236. console.log(res)
  237. },
  238. })
  239. });
  240. },
  241. // 断开连接
  242. closeBLEConnection(item) {
  243. uni.closeBLEConnection({
  244. deviceId: item.deviceId,
  245. success: (res) => {
  246. // res.characteristics 特征值列表
  247. // 读写都需要用到特征值
  248. },
  249. fail: (res) => {
  250. console.log(res);
  251. },
  252. })
  253. },
  254. // 配对设备打印
  255. getPrint(value) {
  256. this.deviceId = this.matchingUnit.deviceId
  257. this.serviceId = this.matchingUnit.serviceId
  258. this.characteristicId = this.matchingUnit.characteristicId
  259. if (this.printType == 'barCode') {
  260. const showFirstName = (name) => {
  261. let newStr;
  262. if (name.length === 2) {
  263. newStr = name.substr(0, 1) + '*';
  264. } else if (name.length > 2) {
  265. let char = '';
  266. for (let i = 0, len = name.length - 1; i < len; i++) {
  267. char += '*';
  268. }
  269. newStr = name.substr(0, 1) + char;
  270. } else {
  271. newStr = name;
  272. }
  273. return newStr;
  274. }
  275. let printerJobs = new PrinterJobs();
  276. let codeValue = this.waybillNo
  277. const ENV = require('../../.env.js')
  278. let logistics = ENV.APP_LINK_URL + '/WaybillInquiry?waybillNo=' + codeValue
  279. let code128 = getCode128(codeValue);
  280. printerJobs
  281. .setSize(1, 1)
  282. .setAlign('LT')
  283. .print('#' + this.userInfo.dept.name)
  284. .setAlign('CT')
  285. .printBarcode(code128)
  286. .setSize(1, 1)
  287. .setAlign('LT')
  288. .text(' ')
  289. .text(codeValue + ' \n')
  290. .print(printerUtil.fillLine())
  291. .setAlign('LT')
  292. .setSize(1, 2)
  293. .setSize(2, 1)
  294. .setBold()
  295. .text('收:')
  296. .setSize(1, 1)
  297. .setBold(false)
  298. .text(' ' + showFirstName(this.waybillList.senderAddressName))
  299. .text(' ' + this.waybillList.senderAddressPhone.substr(0, 3) + "****" + this.waybillList
  300. .senderAddressPhone.substr(7) + ' \n')
  301. .print(' ' + this.waybillList.senderAddressDetails)
  302. .print(printerUtil.fillLine())
  303. .setSize(1, 2)
  304. .setSize(2, 1)
  305. .setBold()
  306. .text('寄:')
  307. .setSize(1, 1)
  308. .setBold(false)
  309. .text(' ' + showFirstName(this.waybillList.consigneeAddressName))
  310. .text(' ' + this.waybillList.consigneeAddressPhone.substr(0, 3) + "****" + this.waybillList
  311. .consigneeAddressPhone.substr(7) + ' \n')
  312. .print(' ' + this.waybillList.consigneeAddressDetails)
  313. .print(printerUtil.fillLine())
  314. .text('备注:')
  315. .text('货物类型:' + this.waybillList.cargoType + ' \n')
  316. .print(' 温度需求:' + this.waybillList.temperatureInterval)
  317. .print(' 配送要求:' + this.waybillList.deliveryCondition)
  318. .setAlign('CT')
  319. .printQrcode(logistics)
  320. .print('扫码查询物流温湿度信息 \n')
  321. .println();
  322. let buffer = printerJobs.buffer();
  323. this.printbuffs(buffer);
  324. } else {
  325. let printerJobs = new PrinterJobs();
  326. printerJobs
  327. .setSize(1, 1)
  328. .setAlign('lt')
  329. .print('#' + this.userInfo.dept.name)
  330. .print('运单号:' + this.waybillNo)
  331. .print('货物类型:' + this.waybillList.cargoType)
  332. .print('温度需求:' + this.waybillList.temperatureInterval)
  333. .print('配送要求:' + this.waybillList.deliveryCondition)
  334. .print('寄件人:' + this.waybillList.senderAddressName)
  335. .print('收件人:' + this.waybillList.consigneeAddressName)
  336. .print(printerUtil.fillLine())
  337. this.humitureData.forEach((item, index) => {
  338. // console.log(item,123)
  339. const exists = this.checkboxValue.some(Tid => Tid === item.id);
  340. if (item.isChecked) {
  341. printerJobs
  342. // .print('设备号:' + item.sn)
  343. // .print('标识名:' + item.title)
  344. // .print('开始时间:' + item.startTime)
  345. // .print('结束时间:' + item.endTime)
  346. // .print(printerUtil.fillLine())
  347. item.arr.forEach((item1, index1) => {
  348. printerJobs
  349. .print('日期:' + item1.time + '单位℃ ')
  350. .text('时间 ')
  351. .text('|')
  352. .text(' ')
  353. .text('T1 ')
  354. .text(' ')
  355. .text('|')
  356. .text(' ')
  357. .text('T2 ')
  358. .text(' ')
  359. .text('|')
  360. .text(' ')
  361. .text('T3 ')
  362. .text(' ')
  363. .text('|')
  364. .text(' ')
  365. .text('T4 \n')
  366. item1.arr.forEach((item2, index2) => {
  367. printerJobs
  368. .text(`${item2[0].time}`)
  369. .text('|')
  370. .text(' ')
  371. .text(
  372. `${item2[0] == '---' ? '----' : character(item2[0].T_t) }`
  373. )
  374. .text(' ')
  375. .text('|')
  376. .text(' ')
  377. .text(
  378. `${item2[1] == '---' ? '----' : character(item2[1].T_t) }`
  379. )
  380. .text(' ')
  381. .text('|')
  382. .text(' ')
  383. .text(
  384. `${item2[2] == '---' ? '----' : character(item2[2].T_t) }`
  385. )
  386. .text(' ')
  387. .text('|')
  388. .text(' ')
  389. .text(
  390. `${item2[3] == '---' ? '----' : character(item2[3].T_t) }`
  391. )
  392. function character(value) {
  393. var arr = value.toFixed(1)
  394. if (arr.length == 3) {
  395. var arr1 = arr + ' '
  396. return arr1
  397. } else {
  398. return arr
  399. }
  400. }
  401. })
  402. })
  403. // printerJobs.println()
  404. }
  405. })
  406. printerJobs.println()
  407. let buffer = printerJobs.buffer();
  408. this.printbuffs(buffer);
  409. }
  410. },
  411. printbuffs(buffer) {
  412. // 1.并行调用多次会存在写失败的可能性
  413. // 2.建议每次写入不超过20字节
  414. // 分包处理,延时调用
  415. const maxChunk = 20;
  416. const delay = 20;
  417. for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
  418. let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
  419. setTimeout(this.printbuff, j * delay, subPackage);
  420. }
  421. },
  422. printbuff(buffer) {
  423. let deviceId = this.deviceId;
  424. let serviceId = this.serviceId;
  425. let characteristicId = this.characteristicId;
  426. // console.log(deviceId, serviceId, characteristicId, 333)
  427. return new Promise((resolve, reject) => {
  428. uni.writeBLECharacteristicValue({
  429. deviceId,
  430. serviceId,
  431. characteristicId,
  432. value: buffer,
  433. success(res) {
  434. //console.log('message发送成功', JSON.stringify(res));
  435. resolve(res);
  436. },
  437. fail(err) {
  438. console.log('message发送失败', JSON.stringify(err));
  439. reject(err);
  440. }
  441. });
  442. });
  443. },
  444. // 获取设备信息探头
  445. getHumiture(waybillNo) {
  446. this.checkboxValue = []
  447. this.$api.get('/api/waybill-task', {
  448. waybillNo: waybillNo,
  449. }).then(res => {
  450. if (res.code == 200) {
  451. const arrlsist = res.data.list
  452. let arrList = []
  453. arrlsist.forEach((item, index) => {
  454. let dataList = {}
  455. dataList.id = item.id
  456. dataList.sn = item.sn
  457. dataList.deviceSensorList = item.deviceSensorList
  458. dataList.startTime = item.startTime
  459. dataList.endTime = item.endTime
  460. if (item.car.id) {
  461. dataList.title = item.car.carNo
  462. } else if (item.warehouse.id) {
  463. dataList.title = item.warehouse.name
  464. }
  465. arrList.push(dataList)
  466. })
  467. this.timeQuantumList = arrList
  468. this.timeQuantumList.forEach((item1, index1) => {
  469. item1.isChecked = true
  470. this.checkboxValue.push(item1.id)
  471. })
  472. this.humitureInfo(arrList)
  473. }
  474. })
  475. },
  476. // 选择打印
  477. selectChange(value) {
  478. this.timeQuantumList.forEach((item, index) => {
  479. if (value.id == item.id) {
  480. if (value.isChecked) {
  481. item.isChecked = false
  482. } else {
  483. item.isChecked = true
  484. }
  485. }
  486. if (item.isChecked) {
  487. this.checkboxValue = []
  488. this.checkboxValue.push(item.id)
  489. }
  490. })
  491. // console.log(this.humitureData,'------')
  492. this.$forceUpdate()
  493. },
  494. // 获取温湿度信息
  495. humitureInfo(value) {
  496. // console.log(printList(), 2666)
  497. // console.log(value, 25)
  498. let arrData = value
  499. let arrData1 = printList()
  500. arrData.forEach((item, index) => {
  501. let arr = []
  502. item.deviceSensorList.forEach((ote, te) => {
  503. arr.push(ote.T_id)
  504. })
  505. let params = {
  506. t_ids: arr,
  507. taskId: item.id,
  508. waybillNo: this.waybillNo,
  509. page: 1,
  510. pageSize: 9999,
  511. }
  512. // console.log(item,999)
  513. item.arr = []
  514. this.getWaybillTask(params).then(res => {
  515. const arrL = JSON.parse(JSON.stringify(res))
  516. const timeList = JSON.parse(JSON.stringify(res))
  517. const arrLil = res
  518. for (let i = 0; i < arrLil.length; i++) {
  519. for (let j = i + 1; j < arrLil.length; j++) {
  520. if (arrLil[i].T_time == arrLil[j].T_time) {
  521. arrLil.splice(j, 1);
  522. j--;
  523. }
  524. }
  525. }
  526. var resultArr = arrLil
  527. let list1 = []
  528. resultArr.forEach(k => {
  529. let arr1 = {
  530. T_sn: k.T_sn,
  531. time: k.T_time,
  532. arr: [],
  533. }
  534. list1.push(arr1)
  535. })
  536. this.maxData = list1
  537. for (let i = 0; i < timeList.length; i++) {
  538. for (let j = i + 1; j < timeList.length; j++) {
  539. if (timeList[i].time == timeList[j].time) {
  540. timeList.splice(j, 1);
  541. j--;
  542. }
  543. }
  544. }
  545. this.maxData.forEach((item3, index3) => {
  546. timeList.forEach((item2, index2) => {
  547. const result1 = arrL.find(fruit => fruit.T_id === 1 &&
  548. fruit.time === item2.time && fruit.T_time === item3
  549. .time)
  550. const result2 = arrL.find(fruit => fruit.T_id === 2 &&
  551. fruit.time === item2.time && fruit.T_time === item3
  552. .time)
  553. const result3 = arrL.find(fruit => fruit.T_id === 3 &&
  554. fruit.time === item2.time && fruit.T_time === item3
  555. .time)
  556. const result4 = arrL.find(fruit => fruit.T_id === 4 &&
  557. fruit.time === item2.time && fruit.T_time === item3
  558. .time)
  559. const flag = areAllUndefined(result1, result2, result3,
  560. result4)
  561. if (!flag) {
  562. let list2 = [
  563. result1 == undefined ? '---' : result1,
  564. result2 == undefined ? '---' : result2,
  565. result3 == undefined ? '---' : result3,
  566. result4 == undefined ? '---' : result4,
  567. ]
  568. item3.arr.push(list2)
  569. }
  570. function areAllUndefined(...args) {
  571. return args.every(arg => arg === undefined);
  572. }
  573. })
  574. })
  575. item.arr = this.maxData
  576. })
  577. })
  578. this.humitureData = arrData
  579. // console.log(this.humitureData, 26)
  580. },
  581. getWaybillTask(params) {
  582. return new Promise((resolve, reject) => {
  583. this.$api.post('/api/waybill-task/data', params).then(res => {
  584. if (res.code == 200) {
  585. let arr1 = res.data.list
  586. if (arr1) {
  587. let arr2 = []
  588. arr1.forEach(item1 => {
  589. const dateString = item1.T_time;
  590. const parts = dateString.split(" ")[0].split("-");
  591. const extractedDate = parts[0] + "-" + parts[1] + "-" + parts[
  592. 2];
  593. const parts1 = dateString.split(" ")[1].split(":");
  594. const extractedTime = parts1[0] + ":" + parts1[1];
  595. let arr3 = {
  596. T_sn: item1.T_sn,
  597. T_id: item1.T_id,
  598. T_time: extractedDate,
  599. T_t: item1.T_t,
  600. T_rh: item1.T_rh,
  601. time: extractedTime
  602. }
  603. arr2.push(arr3)
  604. })
  605. resolve(arr2)
  606. }
  607. }
  608. })
  609. });
  610. },
  611. }
  612. }
  613. </script>
  614. <style lang="scss">
  615. page {
  616. background-color: #fff;
  617. }
  618. .title_bluetooth {
  619. display: flex;
  620. justify-content: center;
  621. align-items: center;
  622. font-size: 40rpx;
  623. margin: 20rpx;
  624. font-weight: 600;
  625. }
  626. .nearby_title {
  627. display: flex;
  628. justify-content: center;
  629. align-items: center;
  630. font-size: 30rpx;
  631. margin: 20rpx;
  632. font-weight: 600;
  633. }
  634. .card_stamp {
  635. display: flex;
  636. flex-direction: column;
  637. padding: 30rpx 20rpx;
  638. }
  639. .search_card {
  640. display: flex;
  641. justify-content: center;
  642. align-items: center;
  643. }
  644. .card_bluetooth {
  645. margin-top: 20rpx;
  646. }
  647. .equipment_title {
  648. font-size: 28rpx;
  649. font-weight: 600;
  650. }
  651. .card_equipment {
  652. margin-top: 20rpx;
  653. min-height: 90rpx;
  654. box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.1);
  655. padding: 10rpx 20rpx;
  656. border-radius: 10rpx;
  657. }
  658. .waybill_num {
  659. margin-top: 20rpx;
  660. font-size: 30rpx;
  661. font-weight: 600;
  662. }
  663. .waybill_numil {
  664. margin-top: 10rpx;
  665. font-size: 28rpx;
  666. color: #767a82;
  667. }
  668. .time_title {
  669. margin-top: 5rpx;
  670. font-size: 28rpx;
  671. }
  672. .card_waybill {
  673. display: flex;
  674. flex-direction: column;
  675. box-shadow: 1rpx 2rpx 14rpx rgba(0, 0, 0, .12);
  676. padding: 20rpx;
  677. border-radius: 10rpx;
  678. margin-top: 20rpx;
  679. }
  680. </style>