_mixins.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. import _data from './_data';
  2. import _onSocket from './_onSocket';
  3. /**
  4. * socket 发送用到的一个函数
  5. */
  6. function stringSource(s) {
  7. let i = 0;
  8. return () => {
  9. return i < s.length ? s.charCodeAt(i++) : null;
  10. };
  11. }
  12. let params = {
  13. timeout: 18000,
  14. timeout2: 22000,
  15. timeoutObj: null,
  16. serverTimeoutObj: null,
  17. lockReconnect: false,
  18. tt: false,
  19. maxConnect: 3,
  20. status: false,
  21. lockSend: false
  22. }
  23. export default {
  24. /** 添加方法时,方法name前加$以避免与页面方法冲突 */
  25. methods: {
  26. /**
  27. * http 请求
  28. * config object
  29. * {
  30. * path: string, 请求路径
  31. * data: object, 发送数据
  32. * success: function, 回调
  33. * fail: function, 错误回调
  34. * type: string 请求方式(默认post)
  35. * success_action: boolean err状态不为0时是否执行success回调(默认是err状态不为0就只提示msg而不执行success回调)
  36. * check: false 是否验证登陆默认不验证
  37. * }
  38. */
  39. getCurPage() {
  40. let pages = getCurrentPages();
  41. let curPage = pages[pages.length - 1];
  42. return curPage
  43. },
  44. $reconnect(cb, sendData) {
  45. if (params.lockReconnect || params.maxConnect <= 0 || _data.data("socket_state") > 0) {
  46. return false;
  47. }
  48. _data.data('socket_state', 0);
  49. clearTimeout(params.timeoutObj);
  50. clearTimeout(params.serverTimeoutObj);
  51. uni.closeSocket();
  52. params.lockReconnect = true;
  53. params.status = false;
  54. params.maxConnect--;
  55. if (sendData != undefined) {
  56. this.$socketSend(sendData, cb);
  57. } else {
  58. this.$sendWithPingToken(cb);
  59. }
  60. },
  61. $sendWithPingToken(cb) {
  62. this.$socketSend({
  63. 'action': 'ping',
  64. 'data': _data.localData('token')
  65. }, cb);
  66. },
  67. $reset() {
  68. params.status = false;
  69. params.lockReconnect = false;
  70. params.maxConnect = 3;
  71. params.lockSend = false;
  72. clearTimeout(params.timeoutObj);
  73. clearTimeout(params.serverTimeoutObj);
  74. return this;
  75. },
  76. $sendWithToken(cb) {
  77. if (params.lockSend) {
  78. return false;
  79. }
  80. params.lockSend = true;
  81. this.$socketSend({
  82. action: 'checkToken',
  83. data: _data.localData('token'),
  84. }, cb);
  85. },
  86. $start() {
  87. if (params.status) {
  88. return false;
  89. }
  90. params.status = true;
  91. let self = this;
  92. clearTimeout(params.serverTimeoutObj);
  93. clearTimeout(params.timeoutObj);
  94. params.timeoutObj = setTimeout(function() {
  95. //这里发送一个心跳,后端收到后,返回一个心跳消息,
  96. //onmessage拿到返回的心跳就说明连接正常
  97. self.$sendWithPingToken();
  98. params.serverTimeoutObj = setTimeout(function() { // 如果超过一定时间还没重置,说明后端主动断开了
  99. uni
  100. .closeSocket();; //如果onclose会执行reconnect,我们执行 websocket.close()就行了.如果直接执行 reconnect 会触发onclose导致重连两次
  101. }, params.timeout2)
  102. }, params.timeout)
  103. },
  104. $requestSend(config) {
  105. let header = {
  106. /** 这里设置为简单跨域,只会请求一次 */
  107. 'Content-Type': 'application/x-www-form-urlencoded',
  108. };
  109. let send_data = ('data' in config ? config.data : {}),
  110. url = _data.data('http_url') + config.path;
  111. send_data['_token'] = _data.localData('token');
  112. send_data['_agent_id'] = _data.data('agent_id');
  113. let _this = this;
  114. console.log(url)
  115. console.log(send_data)
  116. uni.request({
  117. url: url,
  118. data: send_data,
  119. method: ('type' in config ? config.type : 'POST'),
  120. header: header,
  121. // dataType: 'json',
  122. success(res) {
  123. console.log(res);
  124. if (res.statusCode == 200) {
  125. if (('success_action' in config) && config.success_action) {
  126. config.success(res.data);
  127. } else {
  128. if (res.data.err) {
  129. /** 不显示未登录提示 */
  130. console.log(config.path);
  131. if (send_data['_token'] || config.path.indexOf('/in/') > -1 || config.path
  132. .indexOf('/App/') > -1) {
  133. //执行错误回调
  134. console.log(JSON.stringify(res));
  135. if (('fail_callback' in config) && config.fail_callback) {
  136. config.fail_callback(res.data);
  137. } else {
  138. uni.showToast({
  139. title: res.data.msg,
  140. duration: 1000,
  141. icon: "none"
  142. });
  143. }
  144. }
  145. } else {
  146. if (config.path.indexOf('/im/video.Share/') > -1) {
  147. config.success(res.data);
  148. return
  149. }
  150. if (config.path.indexOf('/im/remove/del_log') > -1) {
  151. config.success(res.data);
  152. return
  153. }
  154. if (config.path.indexOf('/im/circle/del') > -1) {
  155. config.success(res.data);
  156. return
  157. }
  158. if (config.path.indexOf('/im/remove/del_all') > -1) {
  159. config.success(res.data);
  160. return
  161. }
  162. if (config.path.indexOf('/im/remove/sign_out') > -1) {
  163. config.success(res.data);
  164. return
  165. }
  166. if ('success' in config) {
  167. config.success(res.data.data);
  168. }
  169. }
  170. }
  171. } else {
  172. //TODO websoket 重连
  173. // uni.showToast({
  174. // title: '您的网络好像出了点状况哦',
  175. // duration: 1000,
  176. // icon: "none"
  177. // });
  178. // uni.showModal({
  179. // content: 'server error:' + JSON.stringify(res.data),
  180. // });
  181. // console.log("config", config);
  182. // config.fail(res.data);
  183. }
  184. },
  185. fail(err) {
  186. console.log(err,'链接失败');
  187. if ('fail' in config) {
  188. // config.fail(err);
  189. } else {
  190. return;
  191. uni.showModal({
  192. content: JSON.stringify(err),
  193. });
  194. }
  195. }
  196. });
  197. },
  198. $httpSend(config) {
  199. let _this = this;
  200. _this.$requestSend(config);
  201. },
  202. /**
  203. * 通过 websocket 发送数据,
  204. * 如果还没有连接 websocket 就先连接websocket,过两秒等websocket连接上了发送本次的数据,如果两秒后还是没有连接上,则舍弃这次发送数据,
  205. * 如果发送的值为空则只连接
  206. * @param data object
  207. * {
  208. * action: 'model.controller.action',
  209. * data: {}
  210. * }
  211. */
  212. $socketSend(send_data, cb) {
  213. let self = this;
  214. /** callback1是连接,callback2是发送 */
  215. ((callback1, callback2) => {
  216. if (send_data && _data.data('socket_state')) {
  217. callback2(send_data);
  218. } else {
  219. callback1(callback2, send_data);
  220. }
  221. })((callback, send_data) => {
  222. uni.connectSocket({
  223. url: _data.data('socket_url'),
  224. header: {
  225. 'content-type': 'application/json',
  226. },
  227. // protocols: [ 'protocol1' ],
  228. method: 'GET',
  229. success() {
  230. _data.data('socket_state', 1);
  231. },
  232. fail(err) {
  233. self.$reset().$reconnect();
  234. }
  235. });
  236. uni.onSocketOpen((res) => {
  237. self.$reset().$start();
  238. /** 绑定服务器消息事件 */
  239. uni.onSocketMessage((res) => {
  240. self.$reset().$start();
  241. res = JSON.parse(res.data);
  242. console.log("res其他消息", res);
  243. if (!(res.action in _onSocket)) {
  244. if (res.action != 'ping' && res.type != 'ping') {
  245. // uni.showModal({
  246. // content: '接受到无效的消息',
  247. // });
  248. }
  249. } else {
  250. console.log("接收到消息:", res.action,res)
  251. // console.log(res);
  252. _onSocket[res.action](res.data);
  253. }
  254. return;
  255. /** 下面的写法二进制接收数据不兼容APP */
  256. if (res.data instanceof Blob) {
  257. /** js中的blob没有没有直接读出其数据的方法,通过FileReader来读取相关数据 */
  258. let reader = new FileReader();
  259. reader.readAsDataURL(res.data);
  260. /** 当读取操作成功完成时调用. */
  261. reader.onload = function(evt) {
  262. let data = JSON.parse(((str) => {
  263. /** base64编码解析 */
  264. if (str.indexOf(',') > -1) {
  265. str = str.split(',')[1];
  266. }
  267. return decodeURIComponent(atob(str).split('')
  268. .map((c) => {
  269. return '%' + ('00' + c
  270. .charCodeAt(0).toString(
  271. 16)).slice(-2);
  272. }).join(''));
  273. })(evt.target.result));
  274. if (!(data.action in _onSocket)) {
  275. if (data.action != 'ping') {}
  276. return;
  277. }
  278. _onSocket[data.action](data.data);
  279. }
  280. }
  281. });
  282. /** 这里发送token到服务器验证 */
  283. callback({
  284. action: 'checkToken',
  285. data: _data.localData('token'),
  286. });
  287. /** 这里如果有需要发送的数据,就等待2s再进行发送,如果2s后,token验证还是不合法,就舍弃这次的发送 */
  288. if (send_data) {
  289. if (_data.localData('token')) {
  290. callback(send_data);
  291. } else {
  292. callback({
  293. action: 'checkToken',
  294. data: _data.localData('token'),
  295. });
  296. }
  297. }
  298. });
  299. uni.onSocketClose((err) => {
  300. _data.data('socket_state', 0);
  301. params.lockReconnect = false;
  302. self.$reconnect();
  303. });
  304. uni.onSocketError((err) => {
  305. _data.data('socket_state', 0);
  306. params.lockReconnect = false;
  307. self.$reconnect();
  308. });
  309. },
  310. (send_data) => {
  311. uni.sendSocketMessage({
  312. data: JSON.stringify(send_data),
  313. fail(err) {
  314. return;
  315. uni.showModal({
  316. content: JSON.stringify(err) + '---发送消息失败',
  317. });
  318. },
  319. success(res) {
  320. if (cb != undefined) {
  321. cb();
  322. }
  323. }
  324. });
  325. return true;
  326. });
  327. },
  328. /**
  329. * http发送文件(图片、文件、语音)
  330. * @param json obj
  331. * {
  332. local_url: string * 在不调用上传控件的时候的本地文件地址
  333. data: json obj * 上传的数据
  334. success: function * 上传成功回调
  335. fail: function * 上传失败回调
  336. type: int 0对话上传文件 1上传头像 2朋友圈上传文件 3朋友圈背景图片上传 4群头像上传
  337. onProgressUpdate: function 上传进度监听
  338. }
  339. */
  340. $httpSendFile(config) {
  341. if (!config) {
  342. config = {};
  343. }
  344. let send_data = ('data' in config ? config.data : {});
  345. send_data['_token'] = _data.localData('token');
  346. ((callback) => {
  347. switch (config.type) {
  348. /** 对话上传文件 */
  349. case 0:
  350. callback(config.local_url, '/im/upload/chat');
  351. break;
  352. /** 上传头像 */
  353. case 1:
  354. callback(config.local_url, '/im/upload/photo');
  355. break;
  356. /** 朋友圈上传文件 */
  357. case 2:
  358. callback(config.local_url, '/im/upload/circle');
  359. break;
  360. /** 朋友圈背景图片上传 */
  361. case 3:
  362. callback(config.local_url, '/im/upload/circleImg');
  363. break;
  364. /** 群头像上传 */
  365. case 4:
  366. callback(config.local_url, '/im/upload/groupPhoto');
  367. break;
  368. // 视频上传
  369. case 6:
  370. callback(config.local_url, '/im/video.Share/upload');
  371. break;
  372. default:
  373. // uni.showModal({
  374. // content: '无效的操作',
  375. // });
  376. break;
  377. }
  378. })((local_url, action_path) => {
  379. console.log("local_url", local_url)
  380. let uploadTask = uni.uploadFile({
  381. url: (_data.data('static_url') + action_path),
  382. filePath: local_url,
  383. name: 'file',
  384. /** formData必须要有值,否则会上传失败 */
  385. formData: send_data,
  386. success: (res) => {
  387. if (res.statusCode == 200) {
  388. if ('success' in config) {
  389. console.log(res.data);
  390. res.data = JSON.parse(res.data);
  391. if (res.data.err) {
  392. if ('fail' in config) {
  393. // config.fail(err);
  394. } else {
  395. uni.showModal({
  396. content: res.data.msg,
  397. });
  398. }
  399. } else {
  400. config.success(res.data.data);
  401. }
  402. }
  403. }
  404. },
  405. fail(err) {
  406. if ('fail' in config) {
  407. // config.fail(err);
  408. } else {
  409. uni.showModal({
  410. content: JSON.stringify(err),
  411. });
  412. }
  413. }
  414. });
  415. uploadTask.onProgressUpdate((res) => {
  416. if ('onProgressUpdate' in config) {
  417. config.onProgressUpdate();
  418. }
  419. return;
  420. });
  421. });
  422. },
  423. }
  424. }