util.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. import {
  2. getStorage,
  3. setStorage
  4. } from '@/utils/localStorage';
  5. window.sessionTime = new Date();
  6. var socketTaskList = []; //websocket 待发送任务列表
  7. var socketInter = null;
  8. /**
  9. * websocket配置项
  10. * @type {{serverTimeoutObj: null, timeoutObj: null, timeoutnum: null, lockReconnect: boolean, ws: null, params: {houseId: null, openid: null, userid: null}, timeout: number}}
  11. */
  12. let wsConfig = {
  13. ws: null,
  14. lockReconnect: false, //是否真正建立连接
  15. interval: null,
  16. timeoutObj: null, //心跳心跳倒计时
  17. serverTimeoutObj: null, // 服务连接超时时间
  18. timeoutnum: null, // 断开重连倒计时
  19. timeout: 58 * 1000, // 58秒一次心跳
  20. // 建立ws连接时,所需参数
  21. params: {
  22. openid: null,
  23. userid: null,
  24. houseId: null
  25. }
  26. }
  27. /**
  28. * 初始化websocket
  29. */
  30. function initWebsocket() {
  31. let str1 = parseInt(Math.random() * 10);
  32. let str2 = parseInt(Math.random() * 10);
  33. let str3 = parseInt(Math.random() * 10);
  34. let str4 = "" + str1 + str2 + str3;
  35. //初始化weosocket
  36. let websocketUrl = $config.ws_url;
  37. const wsuri =
  38. `${websocketUrl}gs-guide-websocket/` +
  39. str4 +
  40. "/shi23jfrw" +
  41. "/websocket";
  42. wsConfig.ws = new WebSocket(wsuri);
  43. // 连接建立时触发
  44. wsConfig.ws.onopen = websocketonopen;
  45. // 客户端接收服务端数据时触发
  46. wsConfig.ws.onmessage = websocketonmessage;
  47. // 通信发生错误时触发
  48. wsConfig.ws.onerror = websocketonerror;
  49. // 连接关闭时触发
  50. wsConfig.ws.onclose = websocketclose;
  51. return wsConfig.ws;
  52. }
  53. /**
  54. * 连接建立时触发
  55. */
  56. function websocketonopen() {
  57. let data = initPage();
  58. console.log('建立ws连接', data)
  59. start();
  60. //发送链接身份数据
  61. connectSend(data.openId, data.userId, data.houseId);
  62. }
  63. /**
  64. * 客户端接收服务端数据时触发
  65. * @param e
  66. */
  67. function websocketonmessage(e) {
  68. console.log('客户端接收服务端数据时触发', e);
  69. //收到服务器信息,心跳重置
  70. // reset();
  71. }
  72. /**
  73. * 通信发生错误时触发
  74. */
  75. function websocketonerror() {
  76. console.log("出现错误");
  77. reconnect();
  78. }
  79. /**
  80. * 连接关闭时触发
  81. * @param e
  82. */
  83. function websocketclose(e) {
  84. //关闭
  85. console.log("断开连接", e);
  86. socketInter && clearInterval(socketInter);//清空心跳发送
  87. socketInter = null;
  88. //重连
  89. reconnect();
  90. }
  91. function websocketsend(Data) {
  92. console.log('ws状态', wsConfig.ws)
  93. if(wsConfig.ws && wsConfig.ws.readyState==1){
  94. let param = [
  95. "SEND" +
  96. "\nproject:" +
  97. "elab-marketing-system" +
  98. "\nmethod:" +
  99. "POST" +
  100. "\npath:" +
  101. "/behavior/brandMiniWeb/upload" +
  102. "\ndestination:" +
  103. "/ws/remote/invoke" +
  104. "\n\n" +
  105. JSON.stringify(Data) +
  106. "\u0000",
  107. ];
  108. //数据发送
  109. wsConfig.ws.send(JSON.stringify(param));
  110. }else{
  111. // 如果还没有创建好socket链接或者链接还没打开,则放到待发送列表中
  112. if(Data){
  113. socketTaskList.push(Data);
  114. }
  115. console.log("***ws-socketTaskList列表count***", socketTaskList.length)
  116. return
  117. }
  118. }
  119. /**
  120. * 解析页面路由参数
  121. * @param name
  122. * @returns {null}
  123. */
  124. function getQueryString(name) {
  125. let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
  126. let arr = window.location.href.split('?');
  127. let result = null;
  128. arr.forEach((item, index) => {
  129. let res = item.match(reg);
  130. if (res != null) {
  131. result = unescape(res[2]);
  132. }
  133. })
  134. return result
  135. }
  136. /**
  137. * 初始进入页面参数
  138. */
  139. function initPage(){
  140. let userInfo = getStorage('userInfo') ? JSON.parse(getStorage('userInfo')) : null;
  141. let queryObj = getStorage('queryObj') ? JSON.parse(getStorage('queryObj')) : null;
  142. let urlObj = queryObj || util.getUrlParams(location.href) || {};
  143. let brandId = urlObj.brandId || urlObj.special_ID || $config.brandId || '';
  144. let userId = urlObj.leavePhoneCustomerId ? urlObj.leavePhoneCustomerId : (userInfo?userInfo.userId:'');
  145. return {
  146. session: urlObj.session || '',
  147. // 项目id,默认仙女山项目
  148. houseId: urlObj.xcxHouseId || '',
  149. userId: userId || '',
  150. openId: urlObj.openid || (userInfo ? userInfo.openId : ''),
  151. brandId: brandId || '',
  152. product: urlObj.xcxHouseId || '',
  153. fromPlatform: urlObj.fromProduce || '',
  154. platform: urlObj.platform || '',
  155. scene: urlObj.scene1 || '',
  156. layoutName: urlObj.layoutName || '',
  157. }
  158. }
  159. /**
  160. * 发送ws连接请求
  161. */
  162. function connectSend(openid, userid, houseId) {
  163. console.log('建立ws通信', openid, userid, houseId)
  164. //发送堆积的待发送消息
  165. const param = [
  166. "CONNECT" +
  167. "\nopenId:" +
  168. openid +
  169. "\nplatform:" +
  170. "1" +
  171. "\nhouseId:" +
  172. houseId +
  173. "\nuserId:" +
  174. userid +
  175. "\naccept-version:1.1,1.0\nheart-beat:5000,5000\n\n\u0000",
  176. ];
  177. websocketsend(JSON.stringify(param));
  178. if (socketTaskList && socketTaskList.length > 0) {
  179. for (var i = 0; i < socketTaskList.length; i++) {
  180. if(socketTaskList[i]){
  181. // wsConfig.ws.send(socketTaskList[i]);
  182. if(!socketTaskList[i].userId){
  183. socketTaskList[i].userId = userid;
  184. socketTaskList[i].brandUserId = userid;
  185. }
  186. if(!socketTaskList[i].openId){
  187. socketTaskList[i].openId = openid;
  188. }
  189. // console.log("***ws-socketTaskList列表***", socketTaskList[i])
  190. let param = [
  191. "SEND" +
  192. "\nproject:" +
  193. "elab-marketing-system" +
  194. "\nmethod:" +
  195. "POST" +
  196. "\npath:" +
  197. "/behavior/brandMiniWeb/upload" +
  198. "\ndestination:" +
  199. "/ws/remote/invoke" +
  200. "\n\n" +
  201. JSON.stringify(socketTaskList[i]) +
  202. "\u0000",
  203. ];
  204. // 发送堆积的待发送消息
  205. wsConfig.ws.send(JSON.stringify(param));
  206. socketTaskList[i] = null;
  207. }
  208. }
  209. for (var i = 0; i < socketTaskList.length; i++) {
  210. if(!socketTaskList[i]){
  211. socketTaskList.splice(i,1);
  212. }
  213. }
  214. }
  215. }
  216. /**
  217. * 重新连接ws
  218. */
  219. function reconnect() {
  220. console.log('重新连接ws');
  221. //重新连接
  222. if (wsConfig.lockReconnect) {
  223. return;
  224. }
  225. wsConfig.lockReconnect = true;
  226. //没连接上会一直重连,设置延迟避免请求过多
  227. wsConfig.timeoutnum && clearTimeout(wsConfig.timeoutnum);
  228. wsConfig.timeoutnum = setTimeout(() => {
  229. //新连接
  230. initWebsocket()
  231. wsConfig.lockReconnect = false
  232. }, 5000)
  233. socketInter && clearInterval(socketInter);//清空心跳发送
  234. socketInter = null;
  235. }
  236. /**
  237. * 重置ws连接
  238. */
  239. function reset() {
  240. console.log('重启心跳')
  241. //重置心跳
  242. // clearTimeout(wsConfig.timeoutObj);
  243. // //清除时间
  244. // clearTimeout(wsConfig.serverTimeoutObj);
  245. //重启心跳
  246. wsSendHeartBeat();
  247. }
  248. // socket 心跳发送
  249. function wsSendHeartBeat() {
  250. let ws = wsConfig.ws;
  251. // var data = ["\n"];//心跳的数据格式
  252. if(!socketInter){
  253. console.warn('***ws-开启WebSocket心跳***');
  254. //5秒钟发送一次心跳
  255. socketInter = setInterval(()=>{
  256. // console.warn("***ws-SendHeartBeat-尝试心跳发送:");
  257. //这里发送一个心跳,后端收到后,返回一个心跳消息,
  258. console.warn('***ws-心跳***');
  259. if (ws.readyState == 1) {
  260. //如果连接正常
  261. ws.send("heartCheck"); //这里可以自己跟后端约定
  262. } else {
  263. //否则重连
  264. reconnect();
  265. }
  266. },5000)
  267. }
  268. }
  269. /**
  270. * 开启ws连接
  271. */
  272. function start() {
  273. let ws = wsConfig.ws;
  274. //开启心跳
  275. // console.log("开启心跳", wsConfig,ws.readyState);
  276. wsConfig.timeoutObj && clearTimeout(wsConfig.timeoutObj);
  277. wsConfig.serverTimeoutObj && clearTimeout(wsConfig.serverTimeoutObj);
  278. wsConfig.timeoutObj = setTimeout(function() {
  279. wsConfig.serverTimeoutObj = setTimeout(function() {
  280. //超时关闭
  281. ws.close();
  282. }, wsConfig.timeout);
  283. }, wsConfig.timeout);
  284. wsSendHeartBeat();//开始心跳
  285. }
  286. var util = {
  287. dateFormat(date, fmt) {
  288. let ret
  289. const opt = {
  290. 'y+': date.getFullYear().toString(), // 年
  291. 'M+': (date.getMonth() + 1).toString(), // 月
  292. 'd+': date.getDate().toString(), // 日
  293. 'H+': date.getHours().toString(), // 时
  294. 'm+': date.getMinutes().toString(), // 分
  295. 's+': date.getSeconds().toString(), // 秒
  296. // 有其他格式化字符需求可以继续添加,必须转化成字符串
  297. }
  298. for (let k in opt) {
  299. ret = new RegExp('(' + k + ')').exec(fmt)
  300. if (ret) {
  301. fmt = fmt.replace(
  302. ret[1],
  303. ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
  304. )
  305. }
  306. }
  307. return fmt
  308. },
  309. formatDate: function(date, fmt) {
  310. if (/(y+)/.test(fmt)) {
  311. fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  312. }
  313. let o = {
  314. 'M+': date.getMonth() + 1,
  315. 'd+': date.getDate(),
  316. 'h+': date.getHours(),
  317. 'm+': date.getMinutes(),
  318. 's+': date.getSeconds()
  319. }
  320. for (let k in o) {
  321. if (new RegExp(`(${k})`).test(fmt)) {
  322. let str = o[k] + ''
  323. fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : this.padLeftZero(str))
  324. }
  325. }
  326. return fmt
  327. },
  328. padLeftZero: function(str) {
  329. return ('00' + str).substr(str.length)
  330. },
  331. formatDatetime(val, format) {
  332. const year = val.getFullYear();
  333. const month = val.getMonth() + 1;
  334. const day = val.getDate();
  335. const hour = val.getHours();
  336. const minute = val.getMinutes();
  337. const second = val.getSeconds();
  338. return year + '-' + (month > 9 ? month : '0' + month) + '-' + day + ' ' + hour + ':' + (minute > 9 ?
  339. minute : '0' + minute) + ':' + (second > 9 ? second : '0' + second);
  340. },
  341. formatDayTime(val) {
  342. const year = val.getFullYear();
  343. const month = val.getMonth() + 1;
  344. const day = val.getDate();
  345. const hour = val.getHours();
  346. const minute = val.getMinutes();
  347. const second = val.getSeconds();
  348. return year + '-' + (month > 9 ? month : '0' + month) + '-' + day + ' ' + hour + ':' + (minute > 9 ?
  349. minute : '0' + minute);
  350. },
  351. formatTodayTime(val) {
  352. const year = val.getFullYear();
  353. const month = val.getMonth() + 1;
  354. const day = val.getDate();
  355. const hour = val.getHours();
  356. const minute = val.getMinutes();
  357. if (month == new Date().getMonth() + 1 && day + 1 == new Date().getDate()) {
  358. return '昨天' + hour + ':' + (minute > 9 ? minute : '0' + minute);
  359. } else if (month == new Date().getMonth() + 1 && day == new Date().getDate()) {
  360. return hour + ':' + (minute > 9 ? minute : '0' + minute);
  361. } else {
  362. return year + '-' + (month > 9 ? month : '0' + month) + '-' + day + ' ' + hour + ':' + (minute > 9 ?
  363. minute : '0' + minute);
  364. }
  365. },
  366. /**
  367. * 计算天数
  368. * @param date1
  369. * @param date2
  370. * @returns {number}
  371. * @constructor
  372. */
  373. getNumberOfDays(date1, date2) { //获得天数
  374. if (!date1 || !date2) {
  375. return 0;
  376. }
  377. //date1:开始日期,date2结束日期
  378. var a1 = Date.parse(new Date(date1));
  379. var a2 = Date.parse(new Date(date2));
  380. var day = parseInt((a2 - a1) / (1000 * 60 * 60 * 24)) + 1; //核心:时间戳相减,然后除以天数
  381. return day
  382. },
  383. getUrlParams(url) {
  384. url = url == null ? window.location.href : url;
  385. var search = url.substring(url.lastIndexOf("?") + 1);
  386. var obj = {};
  387. var reg = /([^?&=]+)=([^?&=]*)/g;
  388. // [^?&=]+表示:除了?、&、=之外的一到多个字符
  389. // [^?&=]*表示:除了?、&、=之外的0到多个字符(任意多个)
  390. search.replace(reg, function(rs, $1, $2) {
  391. var name = decodeURIComponent($1);
  392. var val = decodeURIComponent($2);
  393. val = String(val);
  394. obj[name] = val;
  395. return rs;
  396. });
  397. return obj;
  398. },
  399. formatTime(date) {
  400. var year = date.getFullYear()
  401. var month = date.getMonth() + 1
  402. var day = date.getDate()
  403. var hour = date.getHours()
  404. var minute = date.getMinutes()
  405. var second = date.getSeconds()
  406. return [year, month, day].map(this.formatNumber).join('-') + ' ' + [hour, minute, second].map(this
  407. .formatNumber).join(
  408. ':')
  409. },
  410. formatNumber(n) {
  411. n = n.toString()
  412. return n[1] ? n : '0' + n
  413. },
  414. trackRequest(para, app = null) {
  415. if ((para.type && para.type.includes('Error'))) {
  416. //所有报错埋点以及曝光埋点不再发送至服务器
  417. return
  418. }
  419. try {
  420. if(typeof (para.clkParams) == 'object'){
  421. let obj = {
  422. locusBehaviorName: para.locusBehaviorName ? para.locusBehaviorName : ''
  423. }
  424. para.clkParams = Object.assign(obj,para.clkParams)
  425. }
  426. let pvCurPageParams = "";//字符串string对象
  427. if(para.pvCurPageParams){//调用的时候传递进来的-先转为对象
  428. pvCurPageParams = typeof para.pvCurPageParams === 'object' ? para.pvCurPageParams : JSON.parse(para.pvCurPageParams)
  429. }else{
  430. pvCurPageParams = {};
  431. }
  432. let queryObj = getStorage('queryObj') ? JSON.parse(getStorage('queryObj')) : null;
  433. let urlObj = queryObj || util.getUrlParams(location.href) || {};
  434. let userInfo = getStorage('userInfo') ? JSON.parse(getStorage('userInfo')) : null;
  435. let userId = urlObj.leavePhoneCustomerId ? urlObj.leavePhoneCustomerId : (userInfo?userInfo.userId:'');
  436. let brandId = urlObj.special_ID || $config.brandId || ''
  437. //在页面参数里面手动添加path参数
  438. pvCurPageParams.brandId = brandId;
  439. pvCurPageParams.locusBehaviorName = para.locusBehaviorName || '';
  440. pvCurPageParams.locusValue = para.locusValue || '';
  441. pvCurPageParams.locusName = para.locusName || '';
  442. let data = {
  443. session: '',
  444. userAgent: navigator.userAgent.substring(0, 255) || '',
  445. browserName: navigator.appName || '',
  446. browserVersion: navigator.appVersion.substring(0, 255) || '',
  447. platform: 'h5', //iframeUrl代表是顾问分享的外链
  448. fromPlatform: urlObj.fromPlatform || urlObj.fromProduce || 'h5',
  449. ip: window.ip || '',
  450. cookieId: from_cookie || getStorage("cookie_id") || '',
  451. openId: urlObj.openid || (userInfo ? userInfo.openId : ''),
  452. userId: userId,
  453. brandUserId: userId,
  454. createTime: this.formatTime(new Date()),
  455. uploadTime: this.formatTime(new Date()),
  456. product: 'h5', //iframeUrl代表是顾问分享的外链
  457. project: para.project || urlObj.xcxHouseId || $config.xcxHouseId || '',
  458. brandId: brandId,
  459. expand: JSON.stringify(urlObj), //扩展字段
  460. imTalkId: para.imTalkId || '', //IM对话编号
  461. imTalkType: para.imTalkType || '', //IM对话类型
  462. eventName: para.eventName || '', //事件名称
  463. clkDesPage: para.clkDesPage || '', //点击前往的页面名称
  464. clkId: para.clkId || '', //点击ID
  465. clkName: para.clkName || '',
  466. pvId: para.pvId || '', //PV埋点ID
  467. clkParams: typeof para.clkParams === 'object' ? JSON.stringify(para.clkParams) : (para.clkParams || ''), //点击参数
  468. pvCurPageName: para.pvCurPageName || '', //当前页面名称
  469. pvCurPageParams: typeof pvCurPageParams === 'object' ? JSON.stringify(pvCurPageParams) : (pvCurPageParams ||''), //当前页面参数
  470. pvLastPageName: para.pvLastPageName || '', //上一页页面名称
  471. pvLastPageParams: para.pvLastPageParams || '', //上一页页面参数
  472. pvPageLoadTime: para.pvPageLoadTime || '', //加载时间
  473. type: para.type || '', //埋点类型
  474. reserve1: urlObj.channel || '', //来源平台,抖音百度微信
  475. }
  476. let timeNow = new Date().getTime();
  477. let session = getStorage('sessionNumber') ? Number(getStorage('sessionNumber')) : timeNow;
  478. if (timeNow - sessionTime > 180000 && !urlObj.session) {
  479. // session++;
  480. session = timeNow;
  481. setStorage('sessionNumber', session)
  482. }
  483. data.session = urlObj.session || data.userId + "_" + session || '';
  484. sessionTime = timeNow;
  485. // return data;
  486. // app.globalData.session_id = data.session
  487. // app.globalData.sessionTime = timeNow;
  488. // requestConfig('upload', data, true);
  489. // let param = ["SEND" +
  490. // "\nproject:" + "elab-marketing-system" +
  491. // "\nmethod:" + 'POST' +
  492. // "\npath:" + '/behavior/brandMiniWeb/upload' +
  493. // "\ndestination:" + '/ws/remote/invoke' +
  494. // "\n\n" + JSON.stringify(data) +
  495. // "\u0000"
  496. // ];
  497. // app.wsSendOrder(param,data);//socket 消息发送
  498. console.warn("***mook***", (data.pvId || data.clkId || data.eventId), data)
  499. // let param = [
  500. // "SEND" +
  501. // "\nproject:" +
  502. // "elab-marketing-system" +
  503. // "\nmethod:" +
  504. // "POST" +
  505. // "\npath:" +
  506. // "/behavior/brandMiniWeb/upload" +
  507. // "\ndestination:" +
  508. // "/ws/remote/invoke" +
  509. // "\n\n" +
  510. // JSON.stringify(data) +
  511. // "\u0000",
  512. // ];
  513. // console.log("上报埋点数据", param);
  514. // websocketsend(JSON.stringify(param));
  515. websocketsend(data);
  516. } catch (e) {
  517. console.warn("***util.js-onError***", e);
  518. }
  519. },
  520. getSession() { //获取session
  521. let timeNow = new Date().getTime();
  522. let session = uni.getStorageSync('sessionNumber') || timeNow; //session具体的值
  523. uni.setStorage({
  524. key: "sessionNumber",
  525. data: session
  526. })
  527. return session;
  528. },
  529. initWebsocket:initWebsocket,
  530. };
  531. window.from_session = util.getUrlParams(location.href).session || '';
  532. window.from_cookie = util.getUrlParams(location.href).cookie || '';
  533. export default util;
  534. // module.exports = util;