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 35KB

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