Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

activate.vue 32KB

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