選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

activate.vue 33KB

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