_mixins.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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)
  251. _onSocket[res.action](res.data);
  252. }
  253. return;
  254. /** 下面的写法二进制接收数据不兼容APP */
  255. if (res.data instanceof Blob) {
  256. /** js中的blob没有没有直接读出其数据的方法,通过FileReader来读取相关数据 */
  257. let reader = new FileReader();
  258. reader.readAsDataURL(res.data);
  259. /** 当读取操作成功完成时调用. */
  260. reader.onload = function(evt) {
  261. let data = JSON.parse(((str) => {
  262. /** base64编码解析 */
  263. if (str.indexOf(',') > -1) {
  264. str = str.split(',')[1];
  265. }
  266. return decodeURIComponent(atob(str).split('')
  267. .map((c) => {
  268. return '%' + ('00' + c
  269. .charCodeAt(0).toString(
  270. 16)).slice(-2);
  271. }).join(''));
  272. })(evt.target.result));
  273. if (!(data.action in _onSocket)) {
  274. if (data.action != 'ping') {}
  275. return;
  276. }
  277. _onSocket[data.action](data.data);
  278. }
  279. }
  280. });
  281. /** 这里发送token到服务器验证 */
  282. callback({
  283. action: 'checkToken',
  284. data: _data.localData('token'),
  285. });
  286. /** 这里如果有需要发送的数据,就等待2s再进行发送,如果2s后,token验证还是不合法,就舍弃这次的发送 */
  287. if (send_data) {
  288. if (_data.localData('token')) {
  289. callback(send_data);
  290. } else {
  291. callback({
  292. action: 'checkToken',
  293. data: _data.localData('token'),
  294. });
  295. }
  296. }
  297. });
  298. uni.onSocketClose((err) => {
  299. _data.data('socket_state', 0);
  300. params.lockReconnect = false;
  301. self.$reconnect();
  302. });
  303. uni.onSocketError((err) => {
  304. _data.data('socket_state', 0);
  305. params.lockReconnect = false;
  306. self.$reconnect();
  307. });
  308. },
  309. (send_data) => {
  310. uni.sendSocketMessage({
  311. data: JSON.stringify(send_data),
  312. fail(err) {
  313. return;
  314. uni.showModal({
  315. content: JSON.stringify(err) + '---发送消息失败',
  316. });
  317. },
  318. success(res) {
  319. if (cb != undefined) {
  320. cb();
  321. }
  322. }
  323. });
  324. return true;
  325. });
  326. },
  327. /**
  328. * http发送文件(图片、文件、语音)
  329. * @param json obj
  330. * {
  331. local_url: string * 在不调用上传控件的时候的本地文件地址
  332. data: json obj * 上传的数据
  333. success: function * 上传成功回调
  334. fail: function * 上传失败回调
  335. type: int 0对话上传文件 1上传头像 2朋友圈上传文件 3朋友圈背景图片上传 4群头像上传
  336. onProgressUpdate: function 上传进度监听
  337. }
  338. */
  339. $httpSendFile(config) {
  340. if (!config) {
  341. config = {};
  342. }
  343. let send_data = ('data' in config ? config.data : {});
  344. send_data['_token'] = _data.localData('token');
  345. ((callback) => {
  346. switch (config.type) {
  347. /** 对话上传文件 */
  348. case 0:
  349. callback(config.local_url, '/im/upload/chat');
  350. break;
  351. /** 上传头像 */
  352. case 1:
  353. callback(config.local_url, '/im/upload/photo');
  354. break;
  355. /** 朋友圈上传文件 */
  356. case 2:
  357. callback(config.local_url, '/im/upload/circle');
  358. break;
  359. /** 朋友圈背景图片上传 */
  360. case 3:
  361. callback(config.local_url, '/im/upload/circleImg');
  362. break;
  363. /** 群头像上传 */
  364. case 4:
  365. callback(config.local_url, '/im/upload/groupPhoto');
  366. break;
  367. // 视频上传
  368. case 6:
  369. callback(config.local_url, '/im/video.Share/upload');
  370. break;
  371. default:
  372. // uni.showModal({
  373. // content: '无效的操作',
  374. // });
  375. break;
  376. }
  377. })((local_url, action_path) => {
  378. console.log("local_url", local_url)
  379. let uploadTask = uni.uploadFile({
  380. url: (_data.data('static_url') + action_path),
  381. filePath: local_url,
  382. name: 'file',
  383. /** formData必须要有值,否则会上传失败 */
  384. formData: send_data,
  385. success: (res) => {
  386. if (res.statusCode == 200) {
  387. if ('success' in config) {
  388. console.log(res.data);
  389. res.data = JSON.parse(res.data);
  390. if (res.data.err) {
  391. if ('fail' in config) {
  392. // config.fail(err);
  393. } else {
  394. uni.showModal({
  395. content: res.data.msg,
  396. });
  397. }
  398. } else {
  399. config.success(res.data.data);
  400. }
  401. }
  402. }
  403. },
  404. fail(err) {
  405. if ('fail' in config) {
  406. // config.fail(err);
  407. } else {
  408. uni.showModal({
  409. content: JSON.stringify(err),
  410. });
  411. }
  412. }
  413. });
  414. uploadTask.onProgressUpdate((res) => {
  415. if ('onProgressUpdate' in config) {
  416. config.onProgressUpdate();
  417. }
  418. return;
  419. });
  420. });
  421. },
  422. }
  423. }