pushMessage.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. import Common from './Common.js';
  2. import { h } from 'vue';
  3. import { Notify } from 'pc-component-v3';
  4. import TaskOpenUtil from '../workflow/TaskOpenUtil';
  5. import { Modal, notification } from 'ant-design-vue';
  6. import { MessageTwoTone } from '@ant-design/icons-vue';
  7. import WindowService from './WindowService.js';
  8. export default {
  9. flag: false,
  10. timer: null,
  11. source: null,
  12. isSound: false,
  13. allMessage: [],
  14. webSocket: null,
  15. notificationId: null,
  16. // 触发通知
  17. triggerNotification: function () {
  18. const _self = this;
  19. let token = localStorage.getItem('#token');
  20. if (!token) {
  21. _self.timer = null;
  22. _self.allMessage.splice(0, _self.allMessage.length);
  23. notification.close(_self.notificationId);
  24. return;
  25. }
  26. _self.timer = setInterval(function () {
  27. let allowSound = localStorage.getItem('allowSound');
  28. if (_self.allMessage.length > 0) {
  29. let index = Math.floor(Math.random() * _self.allMessage.length);
  30. let item = _self.allMessage[index];
  31. notification.close(_self.notificationId);
  32. _self.openNotification(item);
  33. _self.isShowNotification(item);
  34. if (_self.JudgmentDomain() && allowSound === 'true') {
  35. _self.playSound(true);
  36. }
  37. _self.allMessage.splice(index, 1);
  38. } else {
  39. clearInterval(_self.timer);
  40. _self.timer = null;
  41. }
  42. }, 5000);
  43. },
  44. // 判断域名是否相同如果不同才播放声音
  45. JudgmentDomain: function () {
  46. const prevUrl = localStorage.getItem('#prevUrl');
  47. if (prevUrl) {
  48. const currentUrl = window.location.hostname;
  49. if (prevUrl === currentUrl) {
  50. return false;
  51. } else {
  52. return true;
  53. }
  54. } else {
  55. return true;
  56. }
  57. },
  58. // 播放声音
  59. playSound: async function (isPlay) {
  60. const _self = this;
  61. if (_self.flag && isPlay) {
  62. return;
  63. }
  64. let ctx = new (window.AudioContext || window.webkitAudioContext)();
  65. const audioUrl = '/static/assets/client-base-v4/sound/sound.mp3';
  66. const res = await fetch(audioUrl);
  67. const arrayBuffer = await res.arrayBuffer();
  68. ctx.decodeAudioData(
  69. arrayBuffer,
  70. function (buffer) {
  71. //处理成功返回的数据类型为AudioBuffer
  72. //创建AudioBufferSourceNode对象
  73. _self.source = ctx.createBufferSource();
  74. _self.source.buffer = buffer;
  75. _self.source.connect(ctx.destination);
  76. _self.source.currentTime = 0;
  77. if (isPlay) {
  78. _self.source.start(0);
  79. setTimeout(() => {
  80. _self.source.stop();
  81. _self.flag = false;
  82. }, 5000);
  83. _self.flag = true;
  84. }
  85. },
  86. function (e) {
  87. console.info('处理出错');
  88. },
  89. );
  90. },
  91. // 检验是否支持系统提示
  92. isShowNotification: function (message) {
  93. const _self = this;
  94. // 检查浏览器是否支持 Notification API
  95. if (!('Notification' in window)) {
  96. alert('此浏览器不支持桌面通知');
  97. return;
  98. }
  99. // 检查用户是否已经允许显示通知
  100. if (Notification.permission === 'granted') {
  101. // 如果已经允许,直接显示通知
  102. _self.showNotification(message);
  103. } else if (Notification.permission !== 'denied') {
  104. // 否则,请求用户允许显示通知
  105. Notification.requestPermission().then(permission => {
  106. // 如果用户允许,显示通知
  107. if (permission === 'granted') {
  108. _self.showNotification(message);
  109. }
  110. });
  111. }
  112. },
  113. // 进行系统提示
  114. showNotification: function (message) {
  115. // 创建一个新的 Notification 对象
  116. if (message.type == 'NEW_TASK') {
  117. const notification = new Notification('待处理消息', {
  118. body: message.content.title,
  119. });
  120. // 监听通知的点击事件
  121. notification.onclick = () => {
  122. TaskOpenUtil.openTask(message.content).then(
  123. successData => {
  124. if (successData.type === 'newWindow') {
  125. WindowService.open(successData.url, '待处理');
  126. }
  127. },
  128. errorData => {
  129. if (errorData != null) {
  130. Notify.error(errorData.title, errorData.message, false);
  131. }
  132. },
  133. );
  134. };
  135. } else if (message.type == 'NEW_UserReadDocument') {
  136. const notification = new Notification('待审阅消息', {
  137. body: message.content.title,
  138. });
  139. notification.onclick = () => {
  140. TaskOpenUtil.openTask(message.content).then(
  141. successData => {
  142. if (successData.type === 'newWindow') {
  143. WindowService.open(successData.url, '待处理');
  144. }
  145. },
  146. errorData => {
  147. if (errorData != null) {
  148. Notify.error(errorData.title, errorData.message, false);
  149. }
  150. },
  151. );
  152. };
  153. }
  154. },
  155. // 打开消息提示框
  156. openNotification: function (messageData) {
  157. const _self = this;
  158. _self.notificationId = messageData.uuid;
  159. if (messageData.type == 'NEW_TASK') {
  160. notification.open({
  161. key: messageData.uuid,
  162. message: messageData.content.title,
  163. description: '您有一条待处理消息',
  164. icon: () =>
  165. h(MessageTwoTone, {
  166. style: 'color: #108ee9',
  167. }),
  168. duration: 5,
  169. style: {
  170. marginTop: '30px',
  171. },
  172. onClick: () => {
  173. notification.close(messageData.uuid);
  174. // _self.replyMessage(messageData.content.id);
  175. TaskOpenUtil.openTask(messageData.content).then(
  176. successData => {
  177. if (successData.type === 'newWindow') {
  178. WindowService.open(successData.url, '待处理');
  179. }
  180. },
  181. errorData => {
  182. if (errorData != null) {
  183. Notify.error(errorData.title, errorData.message, false);
  184. }
  185. },
  186. );
  187. },
  188. });
  189. } else if (messageData.type == 'NEW_UserReadDocument') {
  190. notification.open({
  191. key: messageData.uuid,
  192. message: messageData.content.title,
  193. description: '您有一条待审阅消息',
  194. icon: () =>
  195. h(MessageTwoTone, {
  196. style: 'color: #108ee9',
  197. }),
  198. duration: 5,
  199. onClick: () => {
  200. notification.close(messageData.uuid);
  201. // _self.replyDocument(messageData.content.id);
  202. TaskOpenUtil.openCopyTask(messageData.content).then(
  203. successData => {
  204. if (successData.type === 'newWindow') {
  205. WindowService.open(successData.url, '抄送我的', function () {
  206. console.log('打开审阅单');
  207. });
  208. }
  209. },
  210. errorData => {
  211. if (errorData != null) {
  212. Notify.error(errorData.title, errorData.message, false);
  213. }
  214. },
  215. );
  216. },
  217. });
  218. }
  219. },
  220. // 确认收到待处理消息
  221. replyMessage: function (id) {
  222. let requestUrl = 'UnPushTaskResource/Task?id=' + id;
  223. $.ajax({
  224. url: Common.getApiURL(requestUrl),
  225. type: 'get',
  226. dataType: 'json',
  227. beforeSend: function (request) {
  228. Common.addTokenToRequest(request);
  229. },
  230. success: function (data) {
  231. // console.log(data, 'data---------');
  232. },
  233. error: function (XMLHttpRequest, textStatus, errorThrown) {
  234. Common.processException(XMLHttpRequest, textStatus, errorThrown);
  235. },
  236. });
  237. },
  238. // 确认收到待审阅消息
  239. replyDocument: function (id) {
  240. let requestUrl = 'UnPushTaskResource/UserReadDocument?id=' + id;
  241. $.ajax({
  242. url: Common.getApiURL(requestUrl),
  243. type: 'get',
  244. dataType: 'json',
  245. beforeSend: function (request) {
  246. Common.addTokenToRequest(request);
  247. },
  248. success: function (data) {
  249. // console.log(data, 'data---------');
  250. },
  251. error: function (XMLHttpRequest, textStatus, errorThrown) {
  252. Common.processException(XMLHttpRequest, textStatus, errorThrown);
  253. },
  254. });
  255. },
  256. // 弹出打开声音提示框
  257. messageModal: function () {
  258. const _self = this;
  259. Modal.warning({
  260. okText: '确认',
  261. title: '温馨提示',
  262. content: '您的浏览器设置,提示音无法自动播放,请您点击【确认】按钮,可以自动播放提示音。',
  263. onOk() {
  264. _self.playSound(false);
  265. localStorage.setItem('allowSound', true);
  266. },
  267. });
  268. },
  269. // 触发仪表盘数量更新事件
  270. executionEvent: function () {
  271. // 获取刷新元素
  272. const refreshElement = document.querySelector('#refreshCount');
  273. // 自定义事件
  274. const customEvent = new CustomEvent('evt');
  275. // 触发事件
  276. window.refreshTimer = setInterval(function () {
  277. refreshElement.dispatchEvent(customEvent);
  278. clearInterval(window.refreshTimer);
  279. window.refreshTimer = null;
  280. }, 10000);
  281. },
  282. // 打开websocket
  283. openWebSocket: function () {
  284. const _self = this;
  285. // 如果websocket已连接就不在连接
  286. if (_self.webSocket && _self.webSocket.readyState == 1) {
  287. return;
  288. }
  289. let token = localStorage.getItem('#token');
  290. let websocketUrl = Common.getHostPageBaseURL() + '/WebSocket/MessageQueue';
  291. if (websocketUrl.indexOf('https') == 0) {
  292. websocketUrl = websocketUrl.replace('https', 'wss').replace('/api', '');
  293. } else if (websocketUrl.indexOf('http') == 0) {
  294. websocketUrl = websocketUrl.replace('http', 'ws').replace('/api', '');
  295. }
  296. _self.webSocket = new WebSocket(websocketUrl, [token]);
  297. _self.webSocket.onopen = function () {
  298. console.log('websocket打开');
  299. };
  300. _self.webSocket.onmessage = function (message) {
  301. let taskData = JSON.parse(message.data);
  302. console.log('websocket 收到信息 : ' + taskData);
  303. if (taskData) {
  304. _self.allMessage.push(taskData);
  305. }
  306. if (_self.timer == null) {
  307. _self.triggerNotification();
  308. }
  309. if (!window.refreshTimer) {
  310. _self.executionEvent();
  311. }
  312. _self.webSocket.send(message.data);
  313. };
  314. _self.webSocket.onclose = function () {
  315. console.log('websocket关闭');
  316. _self.webSocket = null;
  317. };
  318. _self.webSocket.onerror = function (event) {
  319. console.log('websocket异常');
  320. _self.webSocket.close();
  321. };
  322. },
  323. // 注销后关闭websocket和循环
  324. closeWebsocket: function () {
  325. const _self = this;
  326. if (_self.webSocket) {
  327. _self.webSocket.close();
  328. clearInterval(_self.timer);
  329. clearInterval(window.refreshTimer);
  330. _self.timer = null;
  331. _self.webSocket = null;
  332. window.refreshTimer = null;
  333. _self.allMessage.splice(0, _self.allMessage.length);
  334. notification.close(_self.notificationId);
  335. }
  336. },
  337. };