您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

activate.vue 32KB

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