You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

activate.vue 33KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150
  1. <template>
  2. <view class="containers">
  3. <view class="sec_info">
  4. <view class="info_txt">信息确认</view>
  5. <view class="info_plate">
  6. <text>车牌号码</text>
  7. <text>{{ fileDataStrings.vehiclePlate }}</text>
  8. </view>
  9. <view class="info_plate">
  10. <text>车牌颜色</text>
  11. <text>{{ fileDataStrings.vehiclePlateColorStr }}</text>
  12. </view>
  13. <view class="info_plate">
  14. <text>手机号码</text>
  15. <text>{{ fileDataStrings.customerTel }}</text>
  16. </view>
  17. <view class="info_plate" style="border: none" v-if="fileDataStrings.cardId">
  18. <text>卡号</text>
  19. <text>{{ fileDataStrings.cardId }}</text>
  20. </view>
  21. <view class="info_plate" v-if="fileDataStrings.obuId">
  22. <text>OBU号</text>
  23. <text>{{ fileDataStrings.obuId }}</text>
  24. </view>
  25. <view class="info_plate">
  26. <text>收费车型</text>
  27. <text>{{ fileDataStrings.vehicleClassStr }}</text>
  28. </view>
  29. </view>
  30. <view class="up_btn" v-if="state.showBtn">
  31. <button aria-disabled="true" @click="btn" v-if="!state.isSuccess" :class="state.disabled?'button':'hui'">
  32. 点击开始激活
  33. </button>
  34. <button aria-disabled="true" @click="back" v-else>
  35. 点击返回首页
  36. </button>
  37. </view>
  38. </view>
  39. <!-- 激活成功popup -->
  40. <view v-if="state.showPopup" class="mask">
  41. <piaoyi-progress-bar canvasId="progressCanvas4" :progress="state.progressNum" progressBackgroundColor="#07C160"
  42. :showText="true" textColor="#fff" :textSize="28" :height="22" :isCircular="true"
  43. :diameter="300"></piaoyi-progress-bar>
  44. </view>
  45. </template>
  46. <script setup>
  47. import {
  48. reactive,
  49. ref
  50. } from "vue";
  51. import {
  52. formatTime,
  53. formatTime2,
  54. expireDate,
  55. expireDate2,
  56. getFormatDate,
  57. msg,
  58. navTo
  59. } from "@/utils/utils";
  60. import {
  61. onLoad,
  62. onUnload
  63. } from '@dcloudio/uni-app'
  64. import {
  65. getItem
  66. } from "@/utils/storage";
  67. import {
  68. requestNew,
  69. corefn
  70. } from "@/utils/network/request.js";
  71. import {
  72. IntegerToHexString,
  73. } from "@/utils/util/fileData.js";
  74. import {
  75. issueApply,
  76. issueCallback,
  77. orderDetailQuery,
  78. errorLogAdd,
  79. cardObuQuery,
  80. cardObuQueryinLog,
  81. obuFileDataDecrypt,
  82. vfjObuActive,
  83. saveRecord
  84. } from "@/utils/network/api";
  85. import {
  86. agentId
  87. } from "@/utils/network/difference";
  88. import {
  89. startHeartbeat,
  90. stopHeartbeat
  91. } from "@/pages/bluetooth/heartbeatService"
  92. const cmd = require("../../../static/etcUtil/cmdConfig.js");
  93. const tools = require("../../../static/etcUtil/tools.js");
  94. const bluetoothUtil = require("../../../static/etcUtil/index.js");
  95. import activeSuccess from "./components/popup-device-active-success";
  96. const datas = require("../../../static/etcUtil/datas.js");
  97. import {
  98. getVehicleType
  99. } from "@/subpackage/after-sale/js/vehicleType.js"
  100. import {
  101. getVehiclePlateColor
  102. } from "@/datas/vehiclePlateColor";
  103. import {
  104. searchVehicleInfoQuery
  105. } from "@/subpackage/after-sale/js/publicRequest";
  106. import {
  107. decryptCardVehicleInformation
  108. } from "@/datas/publicRequest";
  109. import {
  110. channelId
  111. } from "@/utils/network/difference";
  112. import {
  113. getCodeName, getDicWithType
  114. } from "@/datas/queryKey.js";
  115. const state = reactive({
  116. orderId: "",
  117. id: "",
  118. cardStatus: "",
  119. obuStatus: "",
  120. isSuccess: false, //是否激活成功
  121. showPopup: false,
  122. transfer: 0, //0 是原来的激活 1 是过户激活
  123. showBtn: true,
  124. disabled: true,
  125. progressNum: 0,
  126. CardVersion: "",
  127. ObuVersion: "",
  128. ChipSn: ""
  129. })
  130. const getCurrentActivateData = () => {
  131. let activateData = getItem('currentActivateData');
  132. if(activateData) {
  133. fileDataStrings.vehiclePlate = activateData.vehiclePlate;
  134. fileDataStrings.vehicleId = activateData.vehicleId;
  135. fileDataStrings.vehiclePlateColorStr = activateData.vehiclePlateColorStr;
  136. fileDataStrings.customerTel = activateData.customerTel;
  137. fileDataStrings.vehicleClass = activateData.vehicleType;
  138. fileDataStrings.vehicleClassStr = getCodeName('VEHICLE_TYPE', activateData.vehicleType);
  139. fileDataStrings.obuId = activateData.obuId;
  140. fileDataStrings.cardId = activateData.cardId;
  141. }
  142. }
  143. onLoad((option) => {
  144. //读取传入 存储的数据orderInfo
  145. getCurrentActivateData()
  146. let orderData = getItem("orderInfo");
  147. state.id = orderData.id;
  148. console.log(state);
  149. state.transfer = Number(option.transfer)
  150. //获取订单详情
  151. if (option.transfer == '1' || !state.transfer) {
  152. getOrderDetails(orderData.orderId);
  153. } else {
  154. getObuId();
  155. }
  156. console.log("state.transfer", state.transfer, state.transfer == 0, state.transfer == 1, getItem(
  157. "orderInfo"))
  158. })
  159. // ====================== 页面卸载时清理资源 ======================
  160. onUnload(() => {
  161. stopHeartbeat();
  162. // 实际项目中需调用 uni.closeBLEConnection 断开连接
  163. console.log('页面卸载,清理资源');
  164. });
  165. const card = reactive({
  166. cardId: "",
  167. cardNo: "",
  168. startTime: "",
  169. endTime: "",
  170. userName: "",
  171. userNameStr: "",
  172. idNum: "",
  173. idNumStr: "",
  174. vehiclePlate: "",
  175. vehiclePlateColor: "",
  176. color: "",
  177. colorStr: "",
  178. version: "",
  179. type: "",
  180. typeStr: "",
  181. favourable: "",
  182. favourableStr: "",
  183. money: "",
  184. v_userType: ""
  185. });
  186. const obu = reactive({
  187. obuId: "",
  188. num: "",
  189. startTime: "",
  190. endTime: "",
  191. version: "",
  192. approvedCount: "",
  193. axleCount: "",
  194. axleDistance: "",
  195. engineNum: "",
  196. type: "",
  197. typeStr: "",
  198. userType: "",
  199. userTypeStr: "",
  200. vehiclePlate: "",
  201. vehiclePlateColor: "",
  202. vehiclePlateColorStr: "",
  203. vin: "",
  204. wheelCount: "",
  205. isJH: "",
  206. isJHStr: "",
  207. outsideDimensions: "",
  208. loadStatus: ""
  209. });
  210. let cmdRandNum = '';
  211. let orderInfo = {};
  212. const fileDataStrings = reactive({
  213. approvedCount: 0, //核载人数
  214. cardId: "", //卡号
  215. obuId: "", //obu号
  216. packageNum: "", //套餐编号
  217. axleCount: 0, //轴数
  218. axleDistance: "", //轴距
  219. engineNum: "", //发动机
  220. vehicleVin: "",
  221. vehicleEngineNum: "",
  222. cardStatus: "",
  223. obuStatus: "",
  224. type: 0, //类型
  225. userType: 0, //用户类型
  226. vehiclePlate: "", //车牌
  227. vehiclePlateColor: 0, //车牌颜色
  228. vehicleDimensions: "",
  229. wheelCount: 0, //车轮数
  230. vehicleIdNo: "", //车牌号
  231. vehiclePlateColorStr: "",
  232. customerTel: "",
  233. customerId: "",
  234. orderId: "",
  235. vehicleType: '',
  236. vehicleClass: '',
  237. vehicleClassStr: "",
  238. vehicleId: '',
  239. });
  240. function cmdResult1() {
  241. console.log("我的orderInfo:",orderInfo)
  242. // tools.showLoadingAlert('正在激活,请等待')
  243. state.progressNum = 100 / 20
  244. state.showPopup = true;
  245. const options = {
  246. type: 2, //type: 2,JSON格式提交数据(默认表单形式提交)
  247. showLoading: false,
  248. data: {
  249. orderNo: orderInfo.orderNo,
  250. issueType: state.transfer ? 2 : 1, //1正常激活 2 过户激活
  251. cardId: card.cardId,
  252. cardVersion: state.CardVersion,
  253. obuVersion: obu.version,
  254. obuId: obu.obuId
  255. }, //请求参数
  256. method: "POST", //提交方式(默认POST)
  257. };
  258. console.log("options==", options)
  259. console.log("二发指令申请==前,/iaw/issue/order/issueApply", new Date(), options)
  260. //BDS-二发指令申请
  261. requestNew(issueApply, options)
  262. .then((res) => {
  263. console.log("在线激活 请求");
  264. console.log(res);
  265. const datas = res;
  266. console.log("二发指令申请==后,/iaw/issue/order/issueApply", new Date(), res)
  267. bluetoothUtil.transCmd(datas.cmd.split(','), datas.cmdType == 'CARD' ? '10' : '20', function(res) {
  268. implementCmd(datas.transOrderId, datas.cmd, res.toString(), datas.stepNo)
  269. }, (err) => {
  270. showModals(err.msg)
  271. console.log("err", err)
  272. errorLog(datas.cmd, JSON.stringify(err), datas.stepNo)
  273. tools.hideLoadingAlert();
  274. state.showPopup = false;
  275. state.disabled = true
  276. });
  277. })
  278. .catch((err) => {
  279. console.log(err);
  280. tools.hideLoadingAlert();
  281. state.showPopup = false;
  282. state.disabled = true
  283. });
  284. }
  285. function implementCmd(transOrderId, cmd, cmdResult, stepNo) {
  286. console.log("datas.stepNo1", stepNo)
  287. if (state.progressNum != 100) {
  288. state.progressNum = Number(stepNo) * 100 / 20
  289. } else {
  290. state.progressNum = 100
  291. }
  292. const options = {
  293. type: 2, //type: 2,JSON格式提交数据(默认表单形式提交)
  294. showLoading: false,
  295. data: {
  296. transOrderId, //步骤号
  297. cmd,
  298. cmdResult,
  299. stepNo,
  300. mpOpenId: getItem('mpOpenId') //公众号openid
  301. }, //请求参数
  302. method: "POST", //提交方式(默认POST)
  303. };
  304. console.log("options2222", options)
  305. console.log("二发指令回传==前,/iaw/issue/order/issueCallback", new Date(), options)
  306. //BDS-二发指令回传
  307. requestNew(issueCallback, options)
  308. .then((res) => {
  309. console.log("BDS-二发指令回传 ", res);
  310. const datas = res;
  311. console.log("二发指令回传==后,/iaw/issue/order/issueCallback", new Date(), res)
  312. console.log("在线激活 请求", datas);
  313. if (datas.stepNo == 100) {
  314. state.disabled = true
  315. tools.hideLoadingAlert();
  316. state.progressNum = 100
  317. setTimeout(() => {
  318. state.showPopup = false
  319. }, 1000)
  320. setTimeout(() => {
  321. msg("激活成功", {
  322. 'icon': 'success',
  323. 'duration': 3000
  324. })
  325. }, 2000)
  326. setTimeout(() => {
  327. getCardIdCommit()
  328. }, 5000)
  329. } else {
  330. console.log("datas.stepNo", datas.stepNo)
  331. bluetoothUtil.transCmd(datas.cmd.split(','), datas.cmdType == 'CARD' ? '10' : '20', function(res) {
  332. implementCmd(transOrderId, datas.cmd, res.toString(), datas.stepNo)
  333. }, (err) => {
  334. console.log("err", err)
  335. state.showPopup = false
  336. state.disabled = true
  337. errorLog(datas.cmd, JSON.stringify(err), datas.stepNo)
  338. showModals(err.msg)
  339. });
  340. }
  341. })
  342. .catch((err) => {
  343. console.log(err);
  344. tools.hideLoadingAlert();
  345. state.showPopup = false
  346. state.disabled = true
  347. });
  348. }
  349. //开始激活 按钮事件
  350. const btn = () => {
  351. console.log('activateBtn', state)
  352. if (!state.disabled) {
  353. return;
  354. }
  355. if (state.CardVersion == '48' || state.CardVersion == '49' || state.ObuVersion == '48' || state.ObuVersion == '49') {
  356. // 是48,49 先密钥升级再激活
  357. obuUpdate();
  358. } else {
  359. // 不是48,49直接激活
  360. activateQuqet()
  361. }
  362. };
  363. const activateQuqet = () => {
  364. state.disabled = false
  365. console.log('orderInfo参数', orderInfo, state.disabled)
  366. stopHeartbeat();
  367. if(state.transfer == '1' || !state.transfer) {
  368. cmdResult1()
  369. } else {
  370. cmdResult2()
  371. }
  372. // cmdResult1()
  373. }
  374. const cmdResult2 = () => {
  375. let cmdArr = [cmd.HOME_DIRECTORY, cmd.RANDOM_NUMBER];
  376. bluetoothUtil.transCmd(cmdArr, '20', function (res) {
  377. var str = res[1].substring(res[1].length - 4, res[1].length);
  378. if (str == "9000") {
  379. let cmdRandNum = res[1].substring(0, res[1].length - 4);
  380. getObuActivation(cmdRandNum);
  381. } else {
  382. tools.alertF("RANDOM_NUMBER指令长度不符" + res[1]);
  383. }
  384. })
  385. }
  386. const getObuActivation = (cmdRandNumSecond) => {
  387. const options = {
  388. type: 2,
  389. data: {
  390. "cardId": card.cardId,
  391. "obuId": obu.obuId,
  392. "random": cmdRandNumSecond,
  393. "vehicleId": fileDataStrings.vehicleId,
  394. "vehicleType": fileDataStrings.vehicleClass
  395. },
  396. method: "POST",
  397. showLoading: false,
  398. }
  399. tools.showLoadingAlert("执行指令");
  400. requestNew(vfjObuActive, options)
  401. .then((res) => {
  402. tools.hideLoadingAlert();
  403. console.log("在线激活 请求");
  404. console.log(res);
  405. const datas = res;
  406. let cmdArr = datas.apdu.split(',')
  407. tools.showLoadingAlert("执行指令");
  408. bluetoothUtil.transCmd(cmdArr, "20", function (res) {
  409. tools.hideLoadingAlert();
  410. console.log(res);
  411. if (res[0] == "9000") {
  412. msg('激活成功');
  413. navTo(`/pages/index/index`);
  414. // uni.switchTab({
  415. // url: '/pages/index/index'
  416. // }).then(res => {
  417. // navTo(`/pages/order/order?index=${0}`)
  418. // })
  419. } else {
  420. msg(`激活失败,提示码:${res[0]}`);
  421. }
  422. });
  423. })
  424. .catch((err) => {
  425. tools.hideLoadingAlert();
  426. });
  427. }
  428. //获取订单详情
  429. const getOrderDetails = (orderId) => {
  430. console.log('======获取订单信息======')
  431. const options = {
  432. type: 2,
  433. data: {
  434. orderNo: orderId
  435. },
  436. method: "POST",
  437. showLoading: false,
  438. };
  439. state.disabled = false
  440. requestNew(orderDetailQuery, options).then((res) => {
  441. console.log("orderInfo", res);
  442. orderInfo = res;
  443. console.log("orderInfores", res);
  444. if (orderInfo) {
  445. fileDataStrings.userType = orderInfo.userType; //用户类型
  446. fileDataStrings.cardId = orderInfo.cardId;
  447. fileDataStrings.packageNum = orderInfo.packageNum;
  448. fileDataStrings.obuId = orderInfo.obuId;
  449. fileDataStrings.customerTel = orderInfo.customerTel;
  450. fileDataStrings.customerId = orderInfo.customerId;
  451. fileDataStrings.orderId = orderInfo.orderNo;
  452. fileDataStrings.vehiclePlateColorStr = getVehiclePlateColor(orderInfo
  453. .vehiclePlateColor);
  454. fileDataStrings.vehiclePlate = orderInfo.vehiclePlate; //车牌
  455. fileDataStrings.vehicleClass = orderInfo.vehicleClass;
  456. fileDataStrings.vehicleClassStr = getCodeName('VEHICLE_TYPE', activateData.vehicleClass);
  457. }
  458. });
  459. getObuId();
  460. };
  461. /**
  462. * 获取OBU号 读OBU
  463. */
  464. const getObuId = () => {
  465. console.log('======获取OBU号======')
  466. let cmdArray = [cmd.HOME_DIRECTORY, cmd.OBU_SYSTEM_FILE, cmd.RANDOM_NUMBER];
  467. bluetoothUtil.transCmd(cmdArray, "20", function(res) {
  468. var status = res[1].substring(res[1].length - 4, res[1].length);
  469. console.log('获取OBU号执行结果' + status, res)
  470. //第一次获取随机数
  471. if (status == "9000") {
  472. state.disabled = true
  473. obu.obuId = res[1].substring(20, 36);
  474. if(state.transfer == '2' && fileDataStrings.obuId && fileDataStrings.obuId != obu.obuId ) {
  475. showModals('车牌obuId与设备obuId不符,请重新选择')
  476. return;
  477. }
  478. // obu.obuId = '5201250802001105';
  479. obu.vin = res[1].substring(18, 20);
  480. obu.version = res[1].substring(18, 20);
  481. state.ObuVersion = res[1].substring(18, 20)
  482. state.ChipSn = res[1].substring(0, 8)
  483. cmdRandNum = res[2].substring(0, res[2].length - 4);
  484. getCardId()
  485. } else {
  486. showModals('获取设备信息错误!')
  487. }
  488. }, () => {
  489. showModals('获取设备信息错误')
  490. });
  491. };
  492. function showModals(msg) {
  493. uni.showModal({
  494. title: '提示',
  495. content: msg,
  496. showCancel: false,
  497. success: function(res) {
  498. if (res.confirm) {
  499. uni.navigateBack()
  500. console.log('用户点击确定1');
  501. } else if (res.cancel) {
  502. console.log('用户点击取消1');
  503. }
  504. }
  505. });
  506. }
  507. const back = () => {
  508. uni.switchTab({
  509. url: "/pages/index/index"
  510. });
  511. }
  512. const getCardId = () => {
  513. //执行0015文件
  514. tools.showLoadingAlert("执行指令");
  515. let cmdArr = [cmd.HOME_DIRECTORY, cmd.APPLICATION_DIRECTORY, cmd.CMD_READBINARY, cmd.CMD_GETBALANCE];
  516. console.log(cmdArr);
  517. console.log(bluetoothUtil);
  518. bluetoothUtil.transCmd(cmdArr, '10', function(res) { //10:写卡 20:写OBU
  519. console.log("5201", res)
  520. let str = res[2].substring(res[2].length - 4, res[2].length); //判断是否为9000
  521. let str3 = res[3].substring(res[3].length - 4, res[3].length); //判断是否为9000
  522. if (str == "9000" || str3 == "9000") {
  523. if (res[2].length > 86 || res[3] >= 12) {
  524. card.cardId = res[2].substring(20, 40);
  525. if(state.transfer == '2' && fileDataStrings.cardId && fileDataStrings.cardId != card.cardId ) {
  526. showModals('车牌cardId与设备cardId不符,请重新选择')
  527. return;
  528. }
  529. // card.cardId = '52012511110201724155';
  530. state.CardVersion = res[2].substring(18, 20),
  531. tools.hideLoadingAlert();
  532. state.showBtn = true
  533. startHeartbeat()
  534. } else {
  535. alertF("CMD_READBINARY指令长度不符" + res[2]);
  536. }
  537. return;
  538. }
  539. alertF("CMD_READBINARY指令长度不符" + res[2]);
  540. })
  541. };
  542. const errorLog = (cmd, error, step) => {
  543. console.log('激活异常提交')
  544. const options = {
  545. type: 2,
  546. data: {
  547. cardId: card.cardId,
  548. obuId: obu.obuId,
  549. orderType: "1",
  550. factory: datas.getData("deviceName") + "_" + datas.getData("deviceNameZW"),
  551. orderNo: orderInfo.orderNo,
  552. cmd,
  553. error,
  554. step
  555. },
  556. method: "POST",
  557. showLoading: false,
  558. };
  559. requestNew(errorLogAdd, options).then((res) => {
  560. console.log("错误提交成功", res);
  561. });
  562. };
  563. /**
  564. * 获取卡号
  565. */
  566. const getCardIdCommit = () => {
  567. //执行0015文件
  568. tools.showLoadingAlert("执行指令");
  569. let cmdArr = [cmd.HOME_DIRECTORY, cmd.APPLICATION_DIRECTORY, cmd.CMD_READBINARY, cmd.CMD_GETBALANCE];
  570. console.log(cmdArr);
  571. console.log(bluetoothUtil);
  572. bluetoothUtil.transCmd(cmdArr, '10', function(res) { //10:写卡 20:写OBU
  573. console.log("5201", res)
  574. let str = res[2].substring(res[2].length - 4, res[2].length); //判断是否为9000
  575. let str3 = res[3].substring(res[3].length - 4, res[3].length); //判断是否为9000
  576. if (str == "9000" || str3 == "9000") {
  577. if (res[2].length > 86 || res[3] >= 12) {
  578. console.log("res[2]", res[2].substring(84, 86), getVehiclePlateColor(parseInt(res[2]
  579. .substring(82, 84), 16)), res[2].substring(18, 19))
  580. card.cardNo = res[2].substring(20, 40);
  581. card.startTime = res[2].substring(40, 48);
  582. card.endTime = res[2].substring(48, 56);
  583. card.version = res[2].substring(18, 20);
  584. card.money = res[3].substring(0, 8);
  585. card.v_userType = parseInt(res[2].substring(80, 82), 16);
  586. console.log("card.v_userType", card.v_userType)
  587. decryptCardVehicleInformation(res[2].substring(56, 80), function(res) {
  588. card.vehiclePlate = res;
  589. });
  590. console.log("res[2].substring(18, 19)", res[2].substring(18, 20))
  591. if (res[2].substring(18, 19) >= 4) {
  592. //4x卡
  593. card.type = parseInt(res[2].substring(84, 86), 16);
  594. card.typeStr = getVehicleType(parseInt(res[2].substring(84, 86), 16));
  595. card.color = parseInt(res[2].substring(82, 84), 16)
  596. card.colorStr = getVehiclePlateColor(parseInt(res[2].substring(82, 84), 16))
  597. } else {
  598. //2x卡--获取车牌颜色
  599. card.type = "--";
  600. card.color = parseInt(res[2].substring(82, 84), 16)
  601. card.colorStr = getVehiclePlateColor(parseInt(res[2].substring(82, 84), 16))
  602. card.typeStr = getVehicleType(parseInt(res[2].substring(84, 86), 16));
  603. }
  604. state.vehicleId = card.vehiclePlate + "_" + parseInt(res[2].substring(82, 84), 16)
  605. // 读卡信息
  606. //执行0016文件
  607. let arr = [cmd.HOME_DIRECTORY, cmd.PERSONAL_INFORMATION]
  608. bluetoothUtil.transCmd(arr, '10', function(res) {
  609. let str2 = res[1].substring(res[1].length - 4, res[1].length);
  610. if (str2 == "9000") {
  611. if (res[1].length > 108) {
  612. console.log("res====", res)
  613. decryptCardVehicleInformation(res[1].substring(4, 44), function(res) {
  614. card.userName = res; //姓名
  615. card.userNameStr = card.userName[0] + '*'.repeat(card
  616. .userName.length - 1)
  617. });
  618. decryptCardVehicleInformation(res[1].substring(44, 108), function(
  619. res) {
  620. card.idNum = res; //身份证号码
  621. card.idNumStr = res.replace(/^\d{14}/, '**************')
  622. });
  623. //获取是否有优惠
  624. let cmdArr3 = [cmd.HOME_DIRECTORY, cmd.APPLICATION_DIRECTORY, cmd
  625. .CMD_00B08E0000
  626. ];
  627. bluetoothUtil.transCmd(cmdArr3, '10', function(res) {
  628. let str3 = res[2].substring(res[2].length - 4, res[2]
  629. .length);
  630. if (str3 == "9000") {
  631. if (res[2].length > 131) {
  632. let _str = parseInt(res[2].substring(129, 130),
  633. 16);
  634. card.favourable = _str
  635. switch (_str) {
  636. case 0:
  637. card.favourableStr = "否";
  638. break;
  639. case 1:
  640. card.favourableStr = "是";
  641. break;
  642. default:
  643. card.favourableStr = '未知' + "_" + _str;
  644. break;
  645. }
  646. //回调读取OBU指令
  647. getObuIdCommit()
  648. tools.hideLoadingAlert();
  649. } else {
  650. alertF("CMD_00B08E0000指令长度不符" + res[2]);
  651. }
  652. return;
  653. }
  654. alertF(cmd.PERSONAL_INFORMATION + "_" + str);
  655. })
  656. } else {
  657. alertF("PERSONAL_INFORMATION指令长度不符" + res[1]);
  658. }
  659. return;
  660. }
  661. alertF("PERSONAL_INFORMATION指令长度不符" + res[1]);
  662. })
  663. } else {
  664. alertF("CMD_READBINARY指令长度不符" + res[2]);
  665. }
  666. return;
  667. }
  668. alertF("CMD_READBINARY指令长度不符" + res[2]);
  669. })
  670. };
  671. /**
  672. * 获取OBU号
  673. */
  674. const getObuIdCommit = () => {
  675. tools.showLoadingAlert("执行指令");
  676. let cmdArr = [cmd.HOME_DIRECTORY, cmd.OBU_SYSTEM_FILE];
  677. bluetoothUtil.transCmd(cmdArr, '20', function(res) {
  678. let str = res[1].substring(res[1].length - 4, res[1].length);
  679. if (str == "9000") {
  680. if (res[1].length > 52) {
  681. obu.num = res[1].substring(20, 36);
  682. obu.startTime = res[1].substring(36, 44);
  683. obu.endTime = res[1].substring(44, 52);
  684. obu.version = res[1].substring(18, 20);
  685. obu.isJH = res[1].substring(53, 54)
  686. obu.isJHStr = res[1].substring(53, 54) == "1" ? "是" : res[1].substring(53, 54) == "0" ?
  687. "否" : "其他:" + res[1].substring(53, 54);
  688. obu.loadStatus = res[1].substring(52, 54) == '01' ? '正常' : '已拆卸',
  689. console.log("开始执行车辆信息识读");
  690. let rand = res[1].substring(18, 20) >= 50 ? '40' : '00';
  691. var arr = [cmd.OBU_DF01, '00B400000A000000000000000045' + rand];
  692. bluetoothUtil.transCmd(arr, '20', function(res) {
  693. console.log(res);
  694. console.log("开始执行车辆信息识读成功");
  695. let str2 = res[1].substring(res[1].length - 4, res[1].length);
  696. let obuVersion = res[1].substring(18, 20);
  697. let keyIndex = obuVersion > 50 ? '40' : '00';
  698. let reqType = '00';
  699. let proviceCode = '5201';
  700. if (str2 == "9000") {
  701. console.log("===========", obu.num, res[1].substring(0, res[1].length - 4))
  702. decryptObuVehicleInfo(obu.num, res[1].substring(0, res[1].length - 4),
  703. obuVersion, rand, reqType, proviceCode,
  704. function(res) {
  705. obu.approvedCount = res.approvedCount;
  706. obu.axleCount = res.axleCount;
  707. obu.axleDistance = res.axleDistance;
  708. obu.engineNum = res.engineNumber.replace(/\u0000/g, '');
  709. obu.type = res.collectionType;
  710. obu.typeStr = getVehicleType(res.collectionType);
  711. obu.userType = res.userType;
  712. if (res.userType == 0) {
  713. obu.userTypeStr = "普通车";
  714. } else if (res.userType == 6) {
  715. obu.userTypeStr = "公务车";
  716. }
  717. obu.vehiclePlate = res.vehiclePlate.replace(/\u0000/g, '');
  718. //获取车牌颜色
  719. obu.vehiclePlateColor = res.vehiclePlateColor;
  720. obu.vehiclePlateColorStr = getVehiclePlateColor(res
  721. .vehiclePlateColor);
  722. obu.vin = res.vin.replace(/\u0000/g, '');
  723. obu.wheelCount = res.wheelsCount;
  724. obu.outsideDimensions = res.carLong + "x" + res.carWidth +
  725. "x" + res.carHeight
  726. saveRecordApi();
  727. tools.hideLoadingAlert();
  728. });
  729. //断开蓝牙
  730. bluetoothUtil.disconnectDevice();
  731. tools.showToastAlert("蓝牙已断开");
  732. console.log('蓝牙已断开=========')
  733. return;
  734. }
  735. alertF("OBU_00B400000A+rand+OBU_4F00指令长度不符" + res[1]);
  736. })
  737. } else {
  738. alertF("OBU_SYSTEM_FILE指令长度不符" + res[1]);
  739. }
  740. return;
  741. }
  742. alertF("OBU_SYSTEM_FILE指令长度不符" + res[1]);
  743. })
  744. };
  745. // 签信息提交日志记录
  746. const saveRecordApi = () => {
  747. const options = {
  748. type: 2,
  749. data: {
  750. approvedCount: obu.approvedCount, // 核定载人数
  751. axleCount: obu.axleCount, // 车轴数
  752. axleDistance: obu.axleDistance, // 轴距
  753. bindingFinishStatus: card.favourableStr, // 卡签绑定完成状态
  754. cardEnableTime: card.startTime, // 卡启用时间
  755. cardExpireTime: card.endTime, // 卡过期时间
  756. cardId: card.cardNo, // 卡号
  757. cardVehiclePlate: card.vehiclePlate, // 车牌号码
  758. cardVehiclePlateColor: card.colorStr, // 车牌颜色
  759. cardVehicleType: card.typeStr, // 行驶证车辆类型
  760. cardVersion: card.version, // 卡版本号
  761. checksums: card.money, // 校验值
  762. customerIdNum: card.idNumStr, // 身份证号
  763. customerName: card.userNameStr, // 用户姓名
  764. isActive: obu.isJHStr, // 是否激活
  765. loadStatus: obu.loadStatus, // 拆卸状态
  766. obuEnableTime: obu.startTime, // 启用时间
  767. obuExpireTime: obu.endTime, // 到期时间
  768. obuId: obu.num, // obu编号
  769. obuVehicleCustomerType: obu.userTypeStr, // 车辆用户类型
  770. obuVehiclePlate: obu.vehiclePlate, // 车牌号码
  771. obuVehiclePlateColor: obu.vehiclePlateColorStr, // 车牌颜色
  772. obuVehicleType: obu.typeStr, // 行驶证车辆类型
  773. obuVersion: obu.version ,// obu版本号
  774. vehicleDimensions: obu.outsideDimensions, // 外廓尺寸
  775. vehicleEngineNum: obu.engineNum, // 发动机号码
  776. vin: obu.vin, // 车辆识别代码
  777. wheelCount: obu.wheelCount, // 车轮数
  778. },
  779. method: "POST",
  780. showLoading: false,
  781. };
  782. requestNew(saveRecord, options).then((res) => {
  783. console.log("saveRecord", card, obu, state)
  784. msg('激活完成');
  785. navTo(`navTo(`/pages/order/order?index=${0}`)`)
  786. console.log("提交成功")
  787. });
  788. }
  789. /**
  790. * 解密OBU车辆信息
  791. */
  792. const decryptObuVehicleInfo = (num, data, obuVersion, keyIndex, reqType, proviceCode, func) => {
  793. const options = {
  794. type: 2,
  795. data: {
  796. contractSN: num,
  797. cipherData: data,
  798. reqType: reqType,
  799. keyIndex: keyIndex,
  800. proviceCode: proviceCode
  801. },
  802. method: "POST",
  803. showLoading: true,
  804. };
  805. requestNew(obuFileDataDecrypt, options).then((res) => {
  806. console.log("obuFileDataDecrypt", res)
  807. const data = res
  808. func(data)
  809. });
  810. };
  811. //提示对话框
  812. const alertF = (msg) => {
  813. //隐藏加载框
  814. tools.hideLoadingAlert();
  815. //提示对话框
  816. tools.showModalAlert(msg);
  817. stopHeartbeat();
  818. }
  819. async function obuUpdate() {
  820. tools.showLoadingAlert('升级中');
  821. //升级类OBU
  822. const applyData = await apply4Upgrade({
  823. contractSn: obu.obuId, //OBU合同序列号 16位
  824. chipSn: state.ChipSn, //OBU晶片序列号 8位
  825. issueMode: 'UPG', //发行模式
  826. issueType: 'SCOBU', //发行发行类型
  827. cardVersion: state.CardVersion, //卡版本号
  828. obuVersion: state.ObuVersion //OBU版本号
  829. });
  830. if (!applyData) return false;
  831. console.log("applyData", applyData)
  832. if (state.CardVersion == '48' || state.CardVersion == '49') {
  833. const updateEsDat = await updateEs('GEN_OBEIC_UPG', applyData);
  834. if (!updateEsDat) return false;
  835. }
  836. if (state.ObuVersion == '48' || state.ObuVersion == '49') {
  837. const updateEsDatTwo = await updateEs('GEN_OBESAM_UPG', applyData);
  838. if (!updateEsDatTwo) return false;
  839. }
  840. const upgradeDoneData = await upgradeDone({
  841. issueSerialNo: applyData.issueSerialNo, //发行订单号
  842. });
  843. if (!upgradeDoneData) return false;
  844. connectPrefixName = datas.getData("connectPrefixName");
  845. console.log(connectPrefixName);
  846. activateQuqet();
  847. }
  848. function apply4Upgrade(params) {
  849. return new Promise((resolve) => {
  850. corefn('IF01001202504281152', params, function(res) {
  851. console.log("成功1", res)
  852. if (res.rc != "00") {
  853. tools.alertF(res.rm);
  854. return;
  855. }
  856. console.log("成功", res)
  857. resolve(res.rd)
  858. })
  859. })
  860. }
  861. //获取发行脚本指令
  862. async function updateEs(type, applyData) {
  863. console.log('------updateEs------');
  864. tools.showLoadingAlert('升级中');
  865. //获取发行脚本指令
  866. const getCommanData = await getCommands({
  867. cardNo: applyData.cardNo, //卡片序列号
  868. wareId: type, //OBU的物料代码 OBE-SAM通道 GEN_OBESAM_UPG OBE-IC通道 GEN_OBEIC_UPG
  869. issueSerialNo: applyData.issueSerialNo, //发行订单号
  870. });
  871. if (!getCommanData) return false;
  872. //指令解析
  873. const result = getCommanData.commands;
  874. const array = result.split('~');
  875. let cmdType = type == 'GEN_OBESAM_UPG' ? '20' : '10';
  876. for (const element of array) {
  877. console.log('updateEs', element, cmdType);
  878. tools.showLoadingAlert('升级中');
  879. // 让出主线程,确保UI更新
  880. await new Promise(resolve => setTimeout(resolve, 0));
  881. console.log("进来了", element.charAt(0), )
  882. if (element.charAt(0) === 'D' || element.charAt(0) === 'R') {
  883. await processDirectCommand(element, cmdType);
  884. } else if (element.charAt(0) === 'K') {
  885. await processKeyExchange(element, cmdType, applyData);
  886. } else if (element.charAt(0) === 'E') {
  887. await processExtAuth(element, cmdType, applyData);
  888. } else if (element === 'SESAM') {
  889. cmdType = '20';
  890. } else {
  891. cmdType = '10';
  892. }
  893. }
  894. return true;
  895. }
  896. function getCommands(params) {
  897. return new Promise((resolve, reject) => {
  898. corefn('IF01001202504281153', params, function(res) {
  899. console.log("成功1", res)
  900. if (res.rc != "00") {
  901. tools.alertF(res.rm);
  902. return;
  903. }
  904. console.log("成功", res)
  905. resolve(res.rd)
  906. })
  907. })
  908. }
  909. // 提取出来的子函数
  910. async function processDirectCommand(element, cmdType) {
  911. // 添加随机延迟,避免连续请求
  912. return bluetoothUtil.transCmdArrAfter(element.substring(1), cmdType);
  913. }
  914. async function processKeyExchange(element, cmdType, applyData) {
  915. const ranData = await bluetoothUtil.transCmdArrAfter('0084000004', cmdType);
  916. console.log("ranData", ranData)
  917. const exchangeKeyData = await exchangeKey({
  918. key: element.substring(1),
  919. random: ranData['0084000004'][0].substring(0, 8),
  920. issueSerialNo: applyData.issueSerialNo
  921. });
  922. if (!exchangeKeyData) throw new Error('密钥置换失败');
  923. console.log("exchangeKeyData", exchangeKeyData)
  924. return bluetoothUtil.transCmdArrAfter(exchangeKeyData.apdu, cmdType);
  925. }
  926. async function processExtAuth(element, cmdType, applyData) {
  927. const ranData = await bluetoothUtil.transCmdArrAfter('0084000004', cmdType);
  928. const extAuth4IssData = await extAuth4Iss({
  929. keyType: element.substring(1),
  930. random: ranData['0084000004'][0].substring(0, 8),
  931. issueSerialNo: applyData.issueSerialNo,
  932. });
  933. console.log("extAuth4IssData", extAuth4IssData)
  934. if (!extAuth4IssData) throw new Error('外部认证失败');
  935. return bluetoothUtil.transCmdArrAfter(extAuth4IssData.apdu, cmdType);
  936. }
  937. function extAuth4Iss(params) {
  938. console.log("params", params)
  939. return new Promise((resolve) => {
  940. corefn('IF01001202504281156', params, function(res) {
  941. console.log("成功1", res)
  942. if (res.rc != "00") {
  943. tools.alertF(res.rm);
  944. return;
  945. }
  946. console.log("成功", res)
  947. resolve(res.rd)
  948. })
  949. })
  950. }
  951. function exchangeKey(params) {
  952. return new Promise((resolve) => {
  953. corefn('IF01001202504281154', params, function(res) {
  954. console.log("成功1", res)
  955. if (res.rc != "00") {
  956. tools.alertF(res.rm);
  957. return;
  958. }
  959. console.log("成功", res)
  960. resolve(res.rd)
  961. })
  962. })
  963. }
  964. function upgradeDone(params) {
  965. return new Promise((resolve) => {
  966. corefn('IF01001202504281155', params, function(res) {
  967. console.log("成功1", res)
  968. if (res.rc != "00") {
  969. tools.alertF(res.rm);
  970. return;
  971. }
  972. console.log("成功", res)
  973. resolve(res.rd)
  974. })
  975. })
  976. }
  977. </script>
  978. <style>
  979. .containers {
  980. height: 100%;
  981. display: flex;
  982. flex-direction: column;
  983. align-items: center;
  984. justify-content: space-between;
  985. box-sizing: border-box;
  986. }
  987. .sec_info {
  988. width: 90%;
  989. height: auto;
  990. margin: 0 auto;
  991. box-shadow: 0rpx 6rpx 25rpx 0rpx rgba(0, 0, 0, 0.2);
  992. margin-top: 50rpx;
  993. border-radius: 20rpx;
  994. }
  995. .info_txt {
  996. width: 100%;
  997. height: 120rpx;
  998. line-height: 120rpx;
  999. text-align: center;
  1000. color: #000;
  1001. font-size: 36rpx;
  1002. margin-bottom: 20rpx;
  1003. }
  1004. .info_plate {
  1005. display: flex;
  1006. flex-direction: row;
  1007. width: 94%;
  1008. height: 100rpx;
  1009. margin: 0 auto;
  1010. border-bottom: 2rpx solid #f2f2f2;
  1011. }
  1012. .info_plate text:nth-child(1) {
  1013. height: 100rpx;
  1014. text-align: left;
  1015. line-height: 100rpx;
  1016. font-size: 32rpx;
  1017. color: #999;
  1018. }
  1019. .info_plate text:nth-child(2) {
  1020. flex: 1;
  1021. height: 100rpx;
  1022. line-height: 100rpx;
  1023. font-size: 32rpx;
  1024. color: #333;
  1025. margin-left: 50rpx;
  1026. text-align: right;
  1027. }
  1028. /*提交按钮样式*/
  1029. .up_btn {
  1030. width: 85%;
  1031. height: 100rpx;
  1032. margin: 0 auto;
  1033. margin-top: 50rpx;
  1034. margin-bottom: 100rpx;
  1035. }
  1036. .up_btn button {
  1037. width: 100%;
  1038. height: 80rpx;
  1039. line-height: 80rpx;
  1040. color: white;
  1041. font-size: 32rpx;
  1042. text-align: center;
  1043. background: linear-gradient(to right, #01243A, #004576);
  1044. border-radius: 40rpx;
  1045. outline: none;
  1046. border: #4cd95f;
  1047. }
  1048. .button {
  1049. width: 100%;
  1050. height: 80rpx;
  1051. line-height: 80rpx;
  1052. color: white;
  1053. font-size: 32rpx;
  1054. text-align: center;
  1055. background: linear-gradient(to left, #43a1e0 0%, #13e7c1 100%);
  1056. border-radius: 40rpx;
  1057. outline: none;
  1058. border: #4cd95f;
  1059. }
  1060. .hui {
  1061. width: 100%;
  1062. height: 80rpx;
  1063. line-height: 80rpx;
  1064. color: white;
  1065. font-size: 32rpx;
  1066. text-align: center;
  1067. background: linear-gradient(to left, #b9b9b9 0%, #e7e7e7 100%) !important;
  1068. border-radius: 40rpx;
  1069. outline: none;
  1070. border: #4cd95f;
  1071. }
  1072. .up_btn button[disabled] {
  1073. background-color: rgba(0, 191, 112, 0.5);
  1074. color: white;
  1075. font-size: 34rpx;
  1076. border-radius: 20rpx;
  1077. }
  1078. .mask {
  1079. width: 100%;
  1080. height: 100vh;
  1081. background: rgba(0, 0, 0, 0.63);
  1082. position: fixed;
  1083. left: 0;
  1084. top: 0;
  1085. right: 0;
  1086. bottom: 0;
  1087. z-index: 999;
  1088. display: flex;
  1089. align-items: center;
  1090. justify-content: center;
  1091. }
  1092. </style>