_mixins.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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. console.log(send_data['users']);
  112. send_data['_token'] = _data.localData('token');
  113. send_data['_agent_id'] = _data.data('agent_id');
  114. let _this = this;
  115. console.log(url)
  116. console.log(send_data)
  117. uni.request({
  118. url: url,
  119. data: send_data,
  120. method: ('type' in config ? config.type : 'POST'),
  121. header: header,
  122. // dataType: 'json',
  123. success(res) {
  124. console.log(res);
  125. if (res.statusCode == 200) {
  126. if (('success_action' in config) && config.success_action) {
  127. config.success(res.data);
  128. } else {
  129. if (res.data.err) {
  130. /** 不显示未登录提示 */
  131. console.log(config.path);
  132. if (send_data['_token'] || config.path.indexOf('/in/') > -1 || config.path
  133. .indexOf('/App/') > -1) {
  134. //执行错误回调
  135. console.log(JSON.stringify(res));
  136. if (('fail_callback' in config) && config.fail_callback) {
  137. config.fail_callback(res.data);
  138. } else {
  139. uni.showToast({
  140. title: res.data.msg,
  141. duration: 1000,
  142. icon: "none"
  143. });
  144. }
  145. }
  146. } else {
  147. if (config.path.indexOf('/im/video.Share/') > -1) {
  148. config.success(res.data);
  149. return
  150. }
  151. if (config.path.indexOf('/im/remove/del_log') > -1) {
  152. config.success(res.data);
  153. return
  154. }
  155. if (config.path.indexOf('/im/circle/del') > -1) {
  156. config.success(res.data);
  157. return
  158. }
  159. if (config.path.indexOf('/im/remove/del_all') > -1) {
  160. config.success(res.data);
  161. return
  162. }
  163. if (config.path.indexOf('/im/remove/sign_out') > -1) {
  164. config.success(res.data);
  165. return
  166. }
  167. if ('success' in config) {
  168. config.success(res.data.data);
  169. }
  170. }
  171. }
  172. } else {
  173. //TODO websoket 重连
  174. // uni.showToast({
  175. // title: '您的网络好像出了点状况哦',
  176. // duration: 1000,
  177. // icon: "none"
  178. // });
  179. // uni.showModal({
  180. // content: 'server error:' + JSON.stringify(res.data),
  181. // });
  182. // console.log("config", config);
  183. // config.fail(res.data);
  184. }
  185. },
  186. fail(err) {
  187. console.log(err,'链接失败');
  188. if ('fail' in config) {
  189. // config.fail(err);
  190. } else {
  191. return;
  192. uni.showModal({
  193. content: JSON.stringify(err),
  194. });
  195. }
  196. }
  197. });
  198. },
  199. $httpSend(config) {
  200. let _this = this;
  201. _this.$requestSend(config);
  202. },
  203. /**
  204. * 通过 websocket 发送数据,
  205. * 如果还没有连接 websocket 就先连接websocket,过两秒等websocket连接上了发送本次的数据,如果两秒后还是没有连接上,则舍弃这次发送数据,
  206. * 如果发送的值为空则只连接
  207. * @param data object
  208. * {
  209. * action: 'model.controller.action',
  210. * data: {}
  211. * }
  212. */
  213. $socketSend(send_data, cb) {
  214. let self = this;
  215. /** callback1是连接,callback2是发送 */
  216. ((callback1, callback2) => {
  217. if (send_data && _data.data('socket_state')) {
  218. callback2(send_data);
  219. } else {
  220. callback1(callback2, send_data);
  221. }
  222. })((callback, send_data) => {
  223. uni.connectSocket({
  224. url: _data.data('socket_url'),
  225. header: {
  226. 'content-type': 'application/json',
  227. },
  228. // protocols: [ 'protocol1' ],
  229. method: 'GET',
  230. success() {
  231. _data.data('socket_state', 1);
  232. },
  233. fail(err) {
  234. self.$reset().$reconnect();
  235. }
  236. });
  237. uni.onSocketOpen((res) => {
  238. self.$reset().$start();
  239. /** 绑定服务器消息事件 */
  240. uni.onSocketMessage((res) => {
  241. self.$reset().$start();
  242. res = JSON.parse(res.data);
  243. console.log("res其他消息", res);
  244. if (!(res.action in _onSocket)) {
  245. if (res.action != 'ping' && res.type != 'ping') {
  246. // uni.showModal({
  247. // content: '接受到无效的消息',
  248. // });
  249. }
  250. } else {
  251. console.log("接收到消息:", res.action,res)
  252. // console.log(res);
  253. _onSocket[res.action](res.data);
  254. }
  255. return;
  256. /** 下面的写法二进制接收数据不兼容APP */
  257. if (res.data instanceof Blob) {
  258. /** js中的blob没有没有直接读出其数据的方法,通过FileReader来读取相关数据 */
  259. let reader = new FileReader();
  260. reader.readAsDataURL(res.data);
  261. /** 当读取操作成功完成时调用. */
  262. reader.onload = function(evt) {
  263. let data = JSON.parse(((str) => {
  264. /** base64编码解析 */
  265. if (str.indexOf(',') > -1) {
  266. str = str.split(',')[1];
  267. }
  268. return decodeURIComponent(atob(str).split('')
  269. .map((c) => {
  270. return '%' + ('00' + c
  271. .charCodeAt(0).toString(
  272. 16)).slice(-2);
  273. }).join(''));
  274. })(evt.target.result));
  275. if (!(data.action in _onSocket)) {
  276. if (data.action != 'ping') {}
  277. return;
  278. }
  279. _onSocket[data.action](data.data);
  280. }
  281. }
  282. });
  283. /** 这里发送token到服务器验证 */
  284. callback({
  285. action: 'checkToken',
  286. data: _data.localData('token'),
  287. });
  288. /** 这里如果有需要发送的数据,就等待2s再进行发送,如果2s后,token验证还是不合法,就舍弃这次的发送 */
  289. if (send_data) {
  290. if (_data.localData('token')) {
  291. callback(send_data);
  292. } else {
  293. callback({
  294. action: 'checkToken',
  295. data: _data.localData('token'),
  296. });
  297. }
  298. }
  299. });
  300. uni.onSocketClose((err) => {
  301. _data.data('socket_state', 0);
  302. params.lockReconnect = false;
  303. self.$reconnect();
  304. });
  305. uni.onSocketError((err) => {
  306. _data.data('socket_state', 0);
  307. params.lockReconnect = false;
  308. self.$reconnect();
  309. });
  310. },
  311. (send_data) => {
  312. uni.sendSocketMessage({
  313. data: JSON.stringify(send_data),
  314. fail(err) {
  315. return;
  316. uni.showModal({
  317. content: JSON.stringify(err) + '---发送消息失败',
  318. });
  319. },
  320. success(res) {
  321. if (cb != undefined) {
  322. cb();
  323. }
  324. }
  325. });
  326. return true;
  327. });
  328. },
  329. /**
  330. * http发送文件(图片、文件、语音)
  331. * @param json obj
  332. * {
  333. local_url: string * 在不调用上传控件的时候的本地文件地址
  334. data: json obj * 上传的数据
  335. success: function * 上传成功回调
  336. fail: function * 上传失败回调
  337. type: int 0对话上传文件 1上传头像 2朋友圈上传文件 3朋友圈背景图片上传 4群头像上传
  338. onProgressUpdate: function 上传进度监听
  339. }
  340. */
  341. $httpSendFile(config) {
  342. if (!config) {
  343. config = {};
  344. }
  345. let send_data = ('data' in config ? config.data : {});
  346. send_data['_token'] = _data.localData('token');
  347. ((callback) => {
  348. switch (config.type) {
  349. /** 对话上传文件 */
  350. case 0:
  351. callback(config.local_url, '/im/upload/chat');
  352. break;
  353. /** 上传头像 */
  354. case 1:
  355. callback(config.local_url, '/im/upload/photo');
  356. break;
  357. /** 朋友圈上传文件 */
  358. case 2:
  359. callback(config.local_url, '/im/upload/circle');
  360. break;
  361. /** 朋友圈背景图片上传 */
  362. case 3:
  363. callback(config.local_url, '/im/upload/circleImg');
  364. break;
  365. /** 群头像上传 */
  366. case 4:
  367. callback(config.local_url, '/im/upload/groupPhoto');
  368. break;
  369. // 视频上传
  370. case 6:
  371. callback(config.local_url, '/im/video.Share/upload');
  372. break;
  373. default:
  374. // uni.showModal({
  375. // content: '无效的操作',
  376. // });
  377. break;
  378. }
  379. })((local_url, action_path) => {
  380. console.log("local_url", local_url)
  381. let uploadTask = uni.uploadFile({
  382. url: (_data.data('static_url') + action_path),
  383. filePath: local_url,
  384. name: 'file',
  385. /** formData必须要有值,否则会上传失败 */
  386. formData: send_data,
  387. success: (res) => {
  388. if (res.statusCode == 200) {
  389. if ('success' in config) {
  390. console.log(res.data);
  391. res.data = JSON.parse(res.data);
  392. if (res.data.err) {
  393. if ('fail' in config) {
  394. // config.fail(err);
  395. } else {
  396. uni.showModal({
  397. content: res.data.msg,
  398. });
  399. }
  400. } else {
  401. config.success(res.data.data);
  402. }
  403. }
  404. }
  405. },
  406. fail(err) {
  407. if ('fail' in config) {
  408. // config.fail(err);
  409. } else {
  410. uni.showModal({
  411. content: JSON.stringify(err),
  412. });
  413. }
  414. }
  415. });
  416. uploadTask.onProgressUpdate((res) => {
  417. if ('onProgressUpdate' in config) {
  418. config.onProgressUpdate();
  419. }
  420. return;
  421. });
  422. });
  423. },
  424. }
  425. }