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

activate.vue 35KB

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