diff --git a/resources/assets/js/components/UserAvatar.vue b/resources/assets/js/components/UserAvatar.vue index 138fe7ee..40b2eacc 100755 --- a/resources/assets/js/components/UserAvatar.vue +++ b/resources/assets/js/components/UserAvatar.vue @@ -122,7 +122,7 @@ if (!this.userid) { return; } - this.$store.commit('getUserBasic', { + this.$store.dispatch('userBasic', { userid: this.userid, success: (user) => { this.user = user; @@ -132,7 +132,7 @@ openDialog() { this.goForward({path: '/manage/messenger'}); - this.$store.commit("openDialogUser", this.userid); + this.$store.dispatch("openDialogUserid", this.userid); } } }; diff --git a/resources/assets/js/components/UserInput.vue b/resources/assets/js/components/UserInput.vue index 6b4561cf..5f50c893 100755 --- a/resources/assets/js/components/UserInput.vue +++ b/resources/assets/js/components/UserInput.vue @@ -119,7 +119,7 @@ userids.push(value); }); // - this.$store.commit('getUserBasic', { + this.$store.dispatch('userBasic', { userid: userids, complete: () => { this.initialized = true; diff --git a/resources/assets/js/pages/login.vue b/resources/assets/js/pages/login.vue index db864348..f996aed5 100644 --- a/resources/assets/js/pages/login.vue +++ b/resources/assets/js/pages/login.vue @@ -80,7 +80,7 @@ export default { }, }).then((data, msg) => { this.loadIng--; - this.$store.commit('setUserInfo', data); + this.$store.dispatch('saveUserInfo', data); this.goNext(); }).catch((data, msg) => { this.loadIng--; diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue index 8e1ad407..7f52c239 100644 --- a/resources/assets/js/pages/manage.vue +++ b/resources/assets/js/pages/manage.vue @@ -161,7 +161,7 @@ export default { }, mounted() { - this.$store.commit('getUserInfo'); + this.$store.dispatch('userInfo'); }, deactivated() { @@ -212,7 +212,7 @@ export default { title: '退出登录', content: '你确定要登出系统?', onOk: () => { - this.$store.commit("logout") + this.$store.dispatch("logout") } }); return; @@ -279,7 +279,7 @@ export default { this.addShow = false; this.$refs.addProject.resetFields(); this.$set(this.addData, 'template', 0); - this.$store.commit('saveProjectData', data); + this.$store.dispatch('saveProject', data); this.toggleRoute('project/' + data.id) }).catch((data, msg) => { this.loadIng--; diff --git a/resources/assets/js/pages/manage/components/DialogView.vue b/resources/assets/js/pages/manage/components/DialogView.vue index af2cf2ec..03438687 100644 --- a/resources/assets/js/pages/manage/components/DialogView.vue +++ b/resources/assets/js/pages/manage/components/DialogView.vue @@ -96,7 +96,7 @@ export default { methods: { msgRead() { - this.$store.commit('wsMsgRead', this.msgData); + this.$store.dispatch('dialogMsgRead', this.msgData); }, popperShow() { diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 6572694a..d716e397 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -124,13 +124,13 @@ export default { text: this.msgText, }, }).then((data, msg) => { - this.$store.commit('spliceDialogMsg', {id: tempId, data}); + this.$store.dispatch('dialogMsgSplice', {id: tempId, data}); }).catch((data, msg) => { $A.modalWarning({ title: '发送失败', content: msg }); - this.$store.commit('spliceDialogMsg', {id: tempId}); + this.$store.dispatch('dialogMsgSplice', {id: tempId}); }); // this.msgText = ''; @@ -197,11 +197,11 @@ export default { break; case 'error': - this.$store.commit('spliceDialogMsg', {id: file.tempId}); + this.$store.dispatch('dialogMsgSplice', {id: file.tempId}); break; case 'success': - this.$store.commit('spliceDialogMsg', {id: file.tempId, data: file.data}); + this.$store.dispatch('dialogMsgSplice', {id: file.tempId, data: file.data}); break; } }, diff --git a/resources/assets/js/pages/manage/components/ProjectDialog.vue b/resources/assets/js/pages/manage/components/ProjectDialog.vue index c126c749..f66cce1c 100644 --- a/resources/assets/js/pages/manage/components/ProjectDialog.vue +++ b/resources/assets/js/pages/manage/components/ProjectDialog.vue @@ -54,7 +54,7 @@ export default { methods: { getMsg() { if (this.projectChatShow && this.projectDetail.dialog_id) { - this.$store.commit('getDialogMsgList', this.projectDetail.dialog_id); + this.$store.dispatch('dialogMsgList', this.projectDetail.dialog_id); } } } diff --git a/resources/assets/js/pages/manage/components/ProjectList.vue b/resources/assets/js/pages/manage/components/ProjectList.vue index e06ed702..62361e95 100644 --- a/resources/assets/js/pages/manage/components/ProjectList.vue +++ b/resources/assets/js/pages/manage/components/ProjectList.vue @@ -582,7 +582,7 @@ export default { $A.messageSuccess(msg); }).catch((data, msg) => { this.sortDisabled = false; - this.$store.commit('getProjectDetail', this.projectDetail.id); + this.$store.dispatch('projectDetail', this.projectDetail.id); $A.modalError(msg); }); }, @@ -606,7 +606,7 @@ export default { p_name: '', p_color: '', }; - this.$store.commit('getProjectOne', data.project_id); + this.$store.dispatch('projectOne', data.project_id); this.addTaskSuccess(data) }).catch((data, msg) => { this.taskLoad--; @@ -762,7 +762,7 @@ export default { if (index > -1) { this.projectDetail.project_column.splice(index, 1); } - this.$store.commit('getProjectDetail', this.projectDetail.id); + this.$store.dispatch('projectDetail', this.projectDetail.id); }).catch((data, msg) => { this.$set(column, 'loading', false); this.$Modal.remove(); @@ -837,7 +837,7 @@ export default { this.$store.dispatch('taskOne', data.parent_id); } if (typeof updata.complete_at !== "undefined") { - this.$store.commit('getProjectOne', data.project_id); + this.$store.dispatch('projectOne', data.project_id); } }).catch((data, msg) => { this.$set(task, 'loading', false); @@ -868,7 +868,7 @@ export default { column.project_task.splice(index, 1); } } - this.$store.commit('getProjectDetail', this.projectDetail.id); + this.$store.dispatch('projectDetail', this.projectDetail.id); }).catch((data, msg) => { this.$Modal.remove(); $A.modalError(msg, 301); @@ -884,7 +884,7 @@ export default { this.settingLoad--; $A.messageSuccess(msg); this.settingShow = false; - this.$store.commit("saveProjectData", data) + this.$store.dispatch("saveProject", data) }).catch((data, msg) => { this.settingLoad--; $A.modalError(msg); @@ -902,7 +902,7 @@ export default { }).then((data, msg) => { this.userLoad--; $A.messageSuccess(msg); - this.$store.commit('getProjectDetail', this.userData.project_id); + this.$store.dispatch('projectDetail', this.userData.project_id); this.userShow = false; }).catch((data, msg) => { this.userLoad--; @@ -921,7 +921,7 @@ export default { }).then((data, msg) => { this.transferLoad--; $A.messageSuccess(msg); - this.$store.commit('getProjectDetail', this.transferData.project_id); + this.$store.dispatch('projectDetail', this.transferData.project_id); this.transferShow = false; }).catch((data, msg) => { this.transferLoad--; @@ -943,7 +943,7 @@ export default { }).then((data, msg) => { this.$Modal.remove(); $A.messageSuccess(msg); - this.$store.commit('removeProjectData', this.projectDetail.id); + this.$store.dispatch('removeProject', this.projectDetail.id); const project = this.projectList.find(({id}) => id); if (project) { this.goForward({path: '/manage/project/' + project.id}, true); @@ -972,7 +972,7 @@ export default { }).then((data, msg) => { this.$Modal.remove(); $A.messageSuccess(msg); - this.$store.commit('removeProjectData', this.projectDetail.id); + this.$store.dispatch('removeProject', this.projectDetail.id); const project = this.projectList.find(({id}) => id); if (project) { this.goForward({path: '/manage/project/' + project.id}, true); @@ -1020,7 +1020,7 @@ export default { }, toggleBoolean(type) { - this.$store.commit('toggleBoolean', type); + this.$store.dispatch('toggleBoolean', type); }, formatTime(date) { diff --git a/resources/assets/js/pages/manage/components/TaskAdd.vue b/resources/assets/js/pages/manage/components/TaskAdd.vue index e7d2ca52..e94fb0ad 100644 --- a/resources/assets/js/pages/manage/components/TaskAdd.vue +++ b/resources/assets/js/pages/manage/components/TaskAdd.vue @@ -160,7 +160,7 @@ export default { } }, mounted() { - this.$store.commit('getTaskPriority', () => { + this.$store.dispatch('taskPriority').then(() => { if (!this.value.p_name && this.taskPriority.length > 0) { this.choosePriority(this.taskPriority[0]) } diff --git a/resources/assets/js/pages/manage/components/TaskAddSimple.vue b/resources/assets/js/pages/manage/components/TaskAddSimple.vue index fe8ede48..9ed035e5 100644 --- a/resources/assets/js/pages/manage/components/TaskAddSimple.vue +++ b/resources/assets/js/pages/manage/components/TaskAddSimple.vue @@ -107,7 +107,7 @@ export default { this.active = true; this.$nextTick(() => { if (this.taskPriority.length === 0) { - this.$store.commit('getTaskPriority', () => { + this.$store.dispatch('taskPriority').then(() => { if (!this.addData.p_name && this.taskPriority.length > 0) { this.choosePriority(this.taskPriority[0]) } @@ -168,7 +168,7 @@ export default { p_name: '', p_color: '', } - this.$store.commit('getProjectOne', data.project_id); + this.$store.dispatch('projectOne', data.project_id); this.$emit("on-success", data) }).catch((data, msg) => { this.loadIng--; diff --git a/resources/assets/js/pages/manage/messenger.vue b/resources/assets/js/pages/manage/messenger.vue index a5c9d4f7..a6ed4a74 100644 --- a/resources/assets/js/pages/manage/messenger.vue +++ b/resources/assets/js/pages/manage/messenger.vue @@ -81,7 +81,7 @@ export default { mounted() { this.dialogLoad++; - this.$store.commit("getDialogList", () => { + this.$store.dispatch("dialogList", () => { this.dialogLoad--; this.openDialogStorage(); }); @@ -122,7 +122,7 @@ export default { methods: { openDialog(dialog) { this.$store.state.method.setStorage('messengerDialogId', dialog.id) - this.$store.commit('getDialogMsgList', dialog.id); + this.$store.dispatch('dialogMsgList', dialog.id); }, openDialogStorage() { @@ -134,7 +134,7 @@ export default { }, openContacts(user) { - this.$store.commit("openDialogUser", user.userid); + this.$store.dispatch("openDialogUserid", user.userid); this.tabActive = 'dialog'; }, diff --git a/resources/assets/js/pages/manage/project.vue b/resources/assets/js/pages/manage/project.vue index 49a55fcb..15377c11 100644 --- a/resources/assets/js/pages/manage/project.vue +++ b/resources/assets/js/pages/manage/project.vue @@ -24,7 +24,7 @@ export default { this.project_id = route.params.id; }, project_id(id) { - this.$store.commit('getProjectDetail', id); + this.$store.dispatch('projectDetail', id); } }, } diff --git a/resources/assets/js/pages/manage/setting/password.vue b/resources/assets/js/pages/manage/setting/password.vue index 6257894c..e684c878 100644 --- a/resources/assets/js/pages/manage/setting/password.vue +++ b/resources/assets/js/pages/manage/setting/password.vue @@ -85,7 +85,7 @@ export default { }).then((data, msg) => { this.loadIng--; $A.messageSuccess('修改成功'); - this.$store.commit('setUserInfo', data); + this.$store.dispatch('saveUserInfo', data); this.$refs.formDatum.resetFields(); }).catch((data, msg) => { this.loadIng--; diff --git a/resources/assets/js/pages/manage/setting/personal.vue b/resources/assets/js/pages/manage/setting/personal.vue index 4f2eba2d..7cd52e9d 100644 --- a/resources/assets/js/pages/manage/setting/personal.vue +++ b/resources/assets/js/pages/manage/setting/personal.vue @@ -78,7 +78,7 @@ export default { }).then((data, msg) => { this.loadIng--; $A.messageSuccess('修改成功'); - this.$store.commit('getUserInfo'); + this.$store.dispatch('userInfo'); }).catch((data, msg) => { this.loadIng--; $A.modalError(msg); diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index c7f2ae6f..6af5974c 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -1,11 +1,12 @@ export default { /** - * @param context + * 访问接口 + * @param state + * @param dispatch * @param params // {url,data,method,timeout,header,spinner,websocket, before,complete,success,error,after} * @returns {Promise} */ - call(context, params) { - const {state, commit} = context; + call({state, dispatch}, params) { if (!state.method.isJson(params)) params = {url: params} if (!state.method.isJson(params.header)) params.header = {} params.url = state.method.apiUrl(params.url); @@ -48,7 +49,7 @@ export default { $A.modalError({ content: msg, onOk: () => { - commit("logout") + dispatch("logout") } }); return; @@ -90,7 +91,7 @@ export default { // if (state.ajaxWsReady === false) { state.ajaxWsReady = true; - commit("wsMsgListener", { + dispatch("websocketMsgListener", { name: "apiWebsocket", callback: (msg) => { switch (msg.type) { @@ -120,6 +121,258 @@ export default { }) }, + /** + * 切换Boolean变量 + * @param state + * @param key + */ + toggleBoolean({state}, key) { + state[key] = !state[key] + state.method.setStorage('boolean:' + key, state[key]); + }, + + /** + * 获取/更新会员信息 + * @param dispatch + * @returns {Promise} + */ + userInfo({dispatch}) { + return new Promise(function (resolve, reject) { + dispatch("call", { + url: 'users/info', + }).then((data, msg) => { + dispatch('saveUserInfo', data); + resolve(data, msg) + }).catch((data, msg) => { + dispatch("logout"); + reject(data, msg) + }); + }); + }, + + /** + * 更新会员信息 + * @param state + * @param dispatch + * @param info + * @returns {Promise} + */ + saveUserInfo({state, dispatch}, info) { + return new Promise(function (resolve) { + const userInfo = state.method.cloneJSON(info); + userInfo.userid = state.method.runNum(userInfo.userid); + userInfo.token = userInfo.userid > 0 ? (userInfo.token || state.userToken) : ''; + state.userInfo = userInfo; + state.userId = userInfo.userid; + state.userToken = userInfo.token; + state.userIsAdmin = state.method.inArray('admin', userInfo.identity); + state.method.setStorage('userInfo', state.userInfo); + dispatch('projectList'); + dispatch('dialogMsgUnread'); + dispatch('websocketConnection'); + resolve() + }); + }, + + /** + * 更新会员在线 + * @param state + * @param info {userid,online} + */ + saveUserOnlineStatus({state}, info) { + const {userid, online} = info; + if (state.userOnline[userid] !== online) { + state.userOnline = Object.assign({}, state.userOnline, {[userid]: online}); + } + }, + + /** + * 获取用户基本信息 + * @param state + * @param dispatch + * @param params {userid, success, complete} + */ + userBasic({state, dispatch}, params) { + if (!state.method.isJson(params)) { + return; + } + const {userid, success, complete} = params; + if (userid === state.userId) { + typeof success === "function" && success(state.userInfo, true); + return; + } + const time = Math.round(new Date().getTime() / 1000); + const array = []; + (state.method.isArray(userid) ? userid : [userid]).some((uid) => { + if (state.cacheUserBasic[uid]) { + typeof success === "function" && success(state.cacheUserBasic[uid].data, false); + if (time - state.cacheUserBasic[uid].time <= 30) { + return false; + } + } + array.push(uid); + }); + if (array.length === 0) { + typeof complete === "function" && complete() + return; + } + // + if (state.cacheUserBasic["::load"] === true) { + setTimeout(() => { + dispatch('userBasic', params); + }, 20); + return; + } + state.cacheUserBasic["::load"] = true; + dispatch("call", { + url: 'users/basic', + data: { + userid: array + }, + }).then((data, msg) => { + state.cacheUserBasic["::load"] = false; + typeof complete === "function" && complete() + data.forEach((item) => { + state.cacheUserBasic[item.userid] = { + time, + data: item + }; + state.method.setStorage("cacheUserBasic", state.cacheUserBasic); + dispatch('saveUserOnlineStatus', item); + typeof success === "function" && success(item, true) + }); + }).catch((data, msg) => { + state.cacheUserBasic["::load"] = false; + typeof complete === "function" && complete() + $A.modalError(msg); + }); + }, + + /** + * 登出(打开登录页面) + * @param dispatch + */ + logout({dispatch}) { + dispatch('saveUserInfo', {}).then(() => { + const from = window.location.pathname == '/' ? '' : encodeURIComponent(window.location.href); + $A.goForward({path: '/login', query: from ? {from: from} : {}}, true); + }); + }, + + /** + * 获取项目列表 + * @param state + * @param dispatch + */ + projectList({state, dispatch}) { + if (state.userId === 0) { + state.projectList = []; + return; + } + if (state.cacheProjectList.length > 0) { + state.projectList = state.cacheProjectList; + } + dispatch("call", { + url: 'project/lists', + }).then((data, msg) => { + dispatch('saveProject', data.data); + }).catch((data, msg) => { + $A.modalError(msg); + }); + }, + + /** + * 获取项目信息 + * @param state + * @param dispatch + * @param project_id + */ + projectOne({state, dispatch}, project_id) { + if (state.method.runNum(project_id) === 0) { + return; + } + dispatch("call", { + url: 'project/one', + data: { + project_id: project_id, + }, + }).then((data, msg) => { + dispatch('saveProject', data); + }); + }, + + /** + * 获取项目详情 + * @param state + * @param dispatch + * @param project_id + */ + projectDetail({state, dispatch}, project_id) { + if (state.method.runNum(project_id) === 0) { + return; + } + const project = state.cacheProjectList.find(({id}) => id == project_id); + if (project) { + state.projectDetail = Object.assign({project_column: [], project_user: []}, project); + } + state.projectDetail.id = project_id; + // + state.projectLoad++; + dispatch("call", { + url: 'project/detail', + data: { + project_id: project_id, + }, + }).then((data, msg) => { + state.projectLoad--; + dispatch('saveProject', data); + }).catch((data, msg) => { + state.projectLoad--; + $A.modalError(msg); + }); + }, + + /** + * 保存项目信息 + * @param state + * @param data + */ + saveProject({state}, data) { + if (state.method.isArray(data)) { + if (state.projectDetail.id) { + const project = data.find(({id}) => id == state.projectDetail.id); + if (project) { + state.projectDetail = Object.assign({}, state.projectDetail, project) + } + } + state.projectList = data; + } else if (state.method.isJson(data)) { + if (data.id == state.projectDetail.id) { + state.projectDetail = Object.assign({}, state.projectDetail, data) + } + let index = state.projectList.findIndex(({id}) => id == data.id); + if (index > -1) { + state.projectList.splice(index, 1, Object.assign({}, state.projectList[index], data)); + } else { + state.projectList.unshift(data); + } + } + state.method.setStorage("cacheProjectList", state.projectList); + }, + + /** + * 删除项目信息 + * @param state + * @param project_id + */ + removeProject({state}, project_id) { + let index = state.projectList.findIndex(({id}) => id == project_id); + if (index > -1) { + state.projectList.splice(index, 1); + state.method.setStorage("cacheProjectList", state.projectList); + } + }, + /** * 获取任务信息 * @param state @@ -256,4 +509,427 @@ export default { dispatch("taskFiles", task_id); dispatch("subTask", task_id); }, + + /** + * 获取任务优先级预设数据 + * @param state + * @param dispatch + * @returns {Promise} + */ + taskPriority({state, dispatch}) { + return new Promise(function (resolve, reject) { + dispatch("call", { + url: 'system/priority', + }).then((data, msg) => { + state.taskPriority = data; + resolve(data, msg) + }).catch((data, msg) => { + reject(data, msg) + }); + }); + }, + + /** + * 获取会话列表 + * @param state + * @param dispatch + * @param afterCallback + */ + dialogList({state, dispatch}, afterCallback) { + dispatch("call", { + url: 'dialog/lists', + }).then((data, msg) => { + state.dialogList = data.data; + typeof afterCallback === "function" && afterCallback(); + }).catch((data, msg) => { + typeof afterCallback === "function" && afterCallback(); + }); + }, + + /** + * 更新会话数据 + * @param state + * @param dispatch + * @param data + */ + dialogUpdate({state, dispatch}, data) { + let splice = false; + state.dialogList.some(({id, unread}, index) => { + if (id == data.id) { + unread !== data.unread && dispatch('dialogMsgUnread'); + state.dialogList.splice(index, 1, data); + return splice = true; + } + }); + !splice && state.dialogList.unshift(data) + }, + + /** + * 获取单个会话 + * @param state + * @param dispatch + * @param dialog_id + */ + dialogOne({state, dispatch}, dialog_id) { + dispatch("call", { + url: 'dialog/one', + data: { + dialog_id, + }, + }).then((data, msg) => { + dispatch('dialogUpdate', data); + }); + }, + + /** + * 打开个人会话 + * @param state + * @param dispatch + * @param userid + */ + openDialogUserid({state, dispatch}, userid) { + if (userid === state.userId) { + return; + } + dispatch("call", { + url: 'dialog/open/user', + data: { + userid, + }, + }).then((data, msg) => { + state.method.setStorage('messengerDialogId', data.id) + dispatch('dialogMsgList', data.id); + dispatch('dialogUpdate', data); + }).catch((data, msg) => { + $A.modalError(msg); + }); + }, + + /** + * 获取会话消息 + * @param state + * @param dispatch + * @param dialog_id + */ + dialogMsgList({state, dispatch}, dialog_id) { + if (state.method.runNum(dialog_id) === 0) { + return; + } + if (state.dialogId == dialog_id) { + return; + } + // + state.dialogMsgList = []; + if (state.method.isJson(state.cacheDialogList[dialog_id])) { + let length = state.cacheDialogList[dialog_id].data.length; + if (length > 50) { + state.cacheDialogList[dialog_id].data.splice(0, length - 50); + } + state.dialogDetail = state.cacheDialogList[dialog_id].dialog + state.dialogMsgList = state.cacheDialogList[dialog_id].data + } + state.dialogId = dialog_id; + // + if (state.cacheDialogList[dialog_id + "::load"]) { + return; + } + state.cacheDialogList[dialog_id + "::load"] = true; + // + state.dialogMsgLoad++; + dispatch("call", { + url: 'dialog/msg/lists', + data: { + dialog_id: dialog_id, + }, + }).then((data, msg) => { + state.dialogMsgLoad--; + state.cacheDialogList[dialog_id + "::load"] = false; + const dialog = data.dialog; + const reverse = data.data.reverse(); + // 更新缓存 + state.cacheDialogList[dialog_id] = { + dialog, + data: reverse, + }; + state.method.setStorage("cacheDialogList", state.cacheDialogList); + // 更新当前会话消息 + if (state.dialogId == dialog_id) { + state.dialogDetail = dialog; + reverse.forEach((item) => { + let index = state.dialogMsgList.findIndex(({id}) => id == item.id); + if (index === -1) { + state.dialogMsgList.push(item); + } else { + state.dialogMsgList.splice(index, 1, item); + } + }) + } + // 更新会话数据 + dispatch('dialogUpdate', dialog); + }).catch((data, msg) => { + state.dialogMsgLoad--; + state.cacheDialogList[dialog_id + "::load"] = false; + }); + }, + + /** + * 获取未读信息 + * @param state + * @param dispatch + */ + dialogMsgUnread({state, dispatch}) { + if (state.userId === 0) { + state.dialogMsgUnread = 0; + return; + } + const unread = state.dialogMsgUnread; + dispatch("call", { + url: 'dialog/msg/unread', + }).then((data, msg) => { + if (unread == state.dialogMsgUnread) { + state.dialogMsgUnread = data.unread; + } else { + setTimeout(() => { + dispatch('dialogMsgUnread'); + }, 200); + } + }); + }, + + /** + * 根据消息ID 删除 或 替换 会话数据 + * @param state + * @param params {id, data} + */ + dialogMsgSplice({state}, params) { + let {id, data} = params; + if (!id) { + return; + } + if (state.method.isJson(data)) { + if (data.id && state.dialogMsgList.find(m => m.id == data.id)) { + data = null; + } + } + let index = state.dialogMsgList.findIndex(m => m.id == id); + if (index > -1) { + if (data) { + state.dialogMsgList.splice(index, 1, state.method.cloneJSON(data)); + // 是最后一条消息时更新会话 last_msg + if (state.dialogMsgList.length - 1 == index) { + const dialog = state.dialogList.find(({id}) => id == data.dialog_id); + if (dialog) dialog.last_msg = data; + } + } else { + state.dialogMsgList.splice(index, 1); + } + } + }, + + /** + * 发送已阅消息 + * @param state + * @param dispatch + * @param msgData + */ + dialogMsgRead({state, dispatch}, msgData) { + if (msgData.userid == state.userId) return; + if (typeof msgData.r === "undefined") msgData.r = {}; + // + const {id, dialog_id, r} = msgData; + if (!r.read_at) { + r.read_at = state.method.formatDate('Y-m-d H:i:s'); + let dialog = state.dialogList.find(({id}) => id == dialog_id); + if (dialog && dialog.unread > 0) { + dialog.unread-- + state.dialogMsgUnread--; + } + } + // + state.wsReadWaitList.push(id); + clearTimeout(state.wsReadTimeout); + state.wsReadTimeout = setTimeout(() => { + dispatch('websocketSend', { + type: 'readMsg', + data: { + id: state.method.cloneJSON(state.wsReadWaitList) + } + }); + state.wsReadWaitList = []; + }, 10); + }, + + /** + * 初始化 websocket + * @param state + * @param dispatch + */ + websocketConnection({state, dispatch}) { + clearTimeout(state.wsTimeout); + if (state.userId === 0) { + if (state.ws) { + state.ws.close(); + state.ws = null; + } + return; + } + let url = window.webSocketConfig.URL; + if (!url) { + url = window.location.origin; + url = url.replace("https://", "wss://"); + url = url.replace("http://", "ws://"); + url += "/ws"; + } + url += "?action=web&token=" + state.userToken; + // + state.ws = new WebSocket(url); + state.ws.onopen = (e) => { + console.log("[WS] Open", e) + }; + state.ws.onclose = (e) => { + console.log("[WS] Close", e); + state.ws = null; + // + clearTimeout(state.wsTimeout); + state.wsTimeout = setTimeout(() => { + dispatch('websocketConnection'); + }, 3000); + }; + state.ws.onerror = (e) => { + console.log("[WS] Error", e); + state.ws = null; + // + clearTimeout(state.wsTimeout); + state.wsTimeout = setTimeout(() => { + dispatch('websocketConnection'); + }, 3000); + }; + state.ws.onmessage = (e) => { + console.log("[WS] Message", e); + const msgDetail = state.method.jsonParse(event.data); + const {type, msgId} = msgDetail; + switch (type) { + case "open": + state.method.setStorage("userWsFd", msgDetail.data.fd) + break + + case "receipt": + typeof state.wsCall[msgId] === "function" && state.wsCall[msgId](msgDetail.body, true); + delete state.wsCall[msgId]; + break + + case "line": + dispatch('saveUserOnlineStatus', msgDetail.data); + break + + default: + msgId && dispatch('websocketSend', {type: 'receipt', msgId}); + state.wsMsg = msgDetail; + Object.values(state.wsListener).forEach((call) => { + if (typeof call === "function") { + try { + call(msgDetail); + } catch (err) { + console.log("[WS] Callerr", err); + } + } + }); + if (type === "dialog") { + // 更新消息 + (function (msg) { + const {data} = msg; + const {dialog_id} = data; + if (dialog_id == state.dialogId) { + let index = state.dialogMsgList.findIndex(({id}) => id == data.id); + if (index === -1) { + state.dialogMsgList.push(data); + } else { + state.dialogMsgList.splice(index, 1, data); + } + } + })(msgDetail); + // 更新会话 + (function (msg) { + const {mode, data} = msg; + const {dialog_id} = data; + // 更新最后消息 + let dialog = state.dialogList.find(({id}) => id == dialog_id); + if (dialog) { + dialog.last_msg = data; + } else { + dispatch('dialogOne', dialog_id); + } + if (mode === "add") { + if (dialog) { + // 新增未读数 + if (data.userid !== state.userId) dialog.unread++; + // 移动到首位 + const index = state.dialogList.findIndex(({id}) => id == dialog_id); + if (index > -1) { + const tmp = state.dialogList[index]; + state.dialogList.splice(index, 1); + state.dialogList.unshift(tmp); + } + } + // 新增总未读数 + if (data.userid !== state.userId) state.dialogMsgUnread++; + } + })(msgDetail); + } + break + } + } + }, + + /** + * 发送 websocket 消息 + * @param state + * @param params {type, data, callback, msgId} + */ + websocketSend({state}, params) { + if (!state.method.isJson(params)) { + return; + } + const {type, data, callback} = params; + let msgId = params.msgId; + if (!state.ws) { + typeof callback === "function" && callback(null, false) + return; + } + if (typeof callback === "function") { + msgId = state.method.randomString(16) + state.wsCall[msgId] = callback; + } + try { + state.ws.send(JSON.stringify({ + type, + msgId, + data + })); + } catch (e) { + typeof callback === "function" && callback(null, false) + } + }, + + /** + * 监听消息 + * @param state + * @param params {name, callback} + */ + websocketMsgListener({state}, params) { + const {name, callback} = params; + if (typeof callback === "function") { + state.wsListener[name] = callback; + } else { + state.wsListener[name] && delete state.wsListener[name]; + } + }, + + /** + * 关闭 websocket + * @param state + */ + websocketClose({state}) { + state.ws && state.ws.close(); + }, } diff --git a/resources/assets/js/store/mutations.js b/resources/assets/js/store/mutations.js index dca74506..03048022 100644 --- a/resources/assets/js/store/mutations.js +++ b/resources/assets/js/store/mutations.js @@ -1,645 +1,3 @@ export default { - /** - * 切换Boolean变量 - * @param state - * @param key - */ - toggleBoolean(state, key) { - state[key] = !state[key] - state.method.setStorage('boolean:' + key, state[key]); - }, - /** - * 获取任务优先级预设数据 - * @param state - * @param callback - */ - getTaskPriority(state, callback) { - this.dispatch("call", { - url: 'system/priority', - }).then((data, msg) => { - state.taskPriority = data; - typeof callback === "function" && callback(data); - }); - }, - - /** - * 获取/更新会员信息 - * @param state - * @param callback - */ - getUserInfo(state, callback) { - this.dispatch("call", { - url: 'users/info', - }).then((data, msg) => { - this.commit('setUserInfo', data); - typeof callback === "function" && callback(data); - }).catch((data, msg) => { - this.commit("logout"); - }); - }, - - /** - * 更新会员信息 - * @param state - * @param info - */ - setUserInfo(state, info) { - const userInfo = state.method.cloneJSON(info); - userInfo.userid = state.method.runNum(userInfo.userid); - userInfo.token = userInfo.userid > 0 ? (userInfo.token || state.userToken) : ''; - state.userInfo = userInfo; - state.userId = userInfo.userid; - state.userToken = userInfo.token; - state.userIsAdmin = state.method.inArray('admin', userInfo.identity); - state.method.setStorage('userInfo', state.userInfo); - this.commit('getDialogMsgUnread'); - this.commit('getProjectList'); - this.commit('wsConnection'); - }, - - /** - * 更新会员在线 - * @param state - * @param info {userid,online} - */ - setUserOnlineStatus(state, info) { - const {userid, online} = info; - if (state.userOnline[userid] !== online) { - state.userOnline = Object.assign({}, state.userOnline, {[userid]: online}); - } - }, - - /** - * 获取项目列表 - * @param state - */ - getProjectList(state) { - if (state.userId === 0) { - state.projectList = []; - return; - } - if (state.cacheProjectList.length > 0) { - state.projectList = state.cacheProjectList; - } - this.dispatch("call", { - url: 'project/lists', - }).then((data, msg) => { - this.commit('saveProjectData', data.data); - }).catch((data, msg) => { - $A.modalError(msg); - }); - }, - - /** - * 获取项目信息 - * @param state - * @param project_id - */ - getProjectOne(state, project_id) { - if (state.method.runNum(project_id) === 0) { - return; - } - this.dispatch("call", { - url: 'project/one', - data: { - project_id: project_id, - }, - }).then((data, msg) => { - this.commit('saveProjectData', data); - }); - }, - - /** - * 获取项目详情 - * @param state - * @param project_id - */ - getProjectDetail(state, project_id) { - if (state.method.runNum(project_id) === 0) { - return; - } - const project = state.cacheProjectList.find(({id}) => id == project_id); - if (project) { - state.projectDetail = Object.assign({project_column: [], project_user: []}, project); - } - state.projectDetail.id = project_id; - // - state.projectLoad++; - this.dispatch("call", { - url: 'project/detail', - data: { - project_id: project_id, - }, - }).then((data, msg) => { - state.projectLoad--; - this.commit('saveProjectData', data); - }).catch((data, msg) => { - state.projectLoad--; - $A.modalError(msg); - }); - }, - - /** - * 保存项目信息 - * @param state - * @param data - */ - saveProjectData(state, data) { - if (state.method.isArray(data)) { - if (state.projectDetail.id) { - const project = data.find(({id}) => id == state.projectDetail.id); - if (project) { - state.projectDetail = Object.assign({}, state.projectDetail, project) - } - } - state.projectList = data; - } else if (state.method.isJson(data)) { - if (data.id == state.projectDetail.id) { - state.projectDetail = Object.assign({}, state.projectDetail, data) - } - let index = state.projectList.findIndex(({id}) => id == data.id); - if (index > -1) { - state.projectList.splice(index, 1, Object.assign({}, state.projectList[index], data)); - } else { - state.projectList.unshift(data); - } - } - state.method.setStorage("cacheProjectList", state.projectList); - }, - - /** - * 删除项目信息 - * @param state - * @param project_id - */ - removeProjectData(state, project_id) { - let index = state.projectList.findIndex(({id}) => id == project_id); - if (index > -1) { - state.projectList.splice(index, 1); - state.method.setStorage("cacheProjectList", state.projectList); - } - }, - - /** - * 获取用户基本信息 - * @param state - * @param params {userid, success, complete} - */ - getUserBasic(state, params) { - if (!state.method.isJson(params)) { - return; - } - const {userid, success, complete} = params; - if (userid === state.userId) { - typeof success === "function" && success(state.userInfo, true); - return; - } - const time = Math.round(new Date().getTime() / 1000); - const array = []; - (state.method.isArray(userid) ? userid : [userid]).some((uid) => { - if (state.cacheUserBasic[uid]) { - typeof success === "function" && success(state.cacheUserBasic[uid].data, false); - if (time - state.cacheUserBasic[uid].time <= 30) { - return false; - } - } - array.push(uid); - }); - if (array.length === 0) { - typeof complete === "function" && complete() - return; - } - // - if (state.cacheUserBasic["::load"] === true) { - setTimeout(() => { - this.commit('getUserBasic', params); - }, 20); - return; - } - state.cacheUserBasic["::load"] = true; - this.dispatch("call", { - url: 'users/basic', - data: { - userid: array - }, - }).then((data, msg) => { - state.cacheUserBasic["::load"] = false; - typeof complete === "function" && complete() - data.forEach((item) => { - state.cacheUserBasic[item.userid] = { - time, - data: item - }; - state.method.setStorage("cacheUserBasic", state.cacheUserBasic); - this.commit('setUserOnlineStatus', item); - typeof success === "function" && success(item, true) - }); - }).catch((data, msg) => { - state.cacheUserBasic["::load"] = false; - typeof complete === "function" && complete() - $A.modalError(msg); - }); - }, - - /** - * 获取会话列表 - * @param state - * @param afterCallback - */ - getDialogList(state, afterCallback) { - this.dispatch("call", { - url: 'dialog/lists', - }).then((data, msg) => { - state.dialogList = data.data; - typeof afterCallback === "function" && afterCallback(); - }).catch((data, msg) => { - typeof afterCallback === "function" && afterCallback(); - }); - }, - - /** - * 更新会话数据 - * @param state - * @param data - */ - getDialogUpdate(state, data) { - let splice = false; - state.dialogList.some(({id, unread}, index) => { - if (id == data.id) { - unread !== data.unread && this.commit('getDialogMsgUnread'); - state.dialogList.splice(index, 1, data); - return splice = true; - } - }); - !splice && state.dialogList.unshift(data) - }, - - /** - * 获取单个会话 - * @param state - * @param dialog_id - */ - getDialogOne(state, dialog_id) { - this.dispatch("call", { - url: 'dialog/one', - data: { - dialog_id, - }, - }).then((data, msg) => { - this.commit('getDialogUpdate', data); - }); - }, - - /** - * 打开个人会话 - * @param state - * @param userid - */ - openDialogUser(state, userid) { - if (userid === state.userId) { - return; - } - this.dispatch("call", { - url: 'dialog/open/user', - data: { - userid, - }, - }).then((data, msg) => { - state.method.setStorage('messengerDialogId', data.id) - this.commit('getDialogMsgList', data.id); - this.commit('getDialogUpdate', data); - }).catch((data, msg) => { - $A.modalError(msg); - }); - }, - - /** - * 获取会话消息 - * @param state - * @param dialog_id - */ - getDialogMsgList(state, dialog_id) { - if (state.method.runNum(dialog_id) === 0) { - return; - } - if (state.dialogId == dialog_id) { - return; - } - // - state.dialogMsgList = []; - if (state.method.isJson(state.cacheDialogList[dialog_id])) { - let length = state.cacheDialogList[dialog_id].data.length; - if (length > 50) { - state.cacheDialogList[dialog_id].data.splice(0, length - 50); - } - state.dialogDetail = state.cacheDialogList[dialog_id].dialog - state.dialogMsgList = state.cacheDialogList[dialog_id].data - } - state.dialogId = dialog_id; - // - if (state.cacheDialogList[dialog_id + "::load"]) { - return; - } - state.cacheDialogList[dialog_id + "::load"] = true; - // - state.dialogMsgLoad++; - this.dispatch("call", { - url: 'dialog/msg/lists', - data: { - dialog_id: dialog_id, - }, - }).then((data, msg) => { - state.dialogMsgLoad--; - state.cacheDialogList[dialog_id + "::load"] = false; - const dialog = data.dialog; - const reverse = data.data.reverse(); - // 更新缓存 - state.cacheDialogList[dialog_id] = { - dialog, - data: reverse, - }; - state.method.setStorage("cacheDialogList", state.cacheDialogList); - // 更新当前会话消息 - if (state.dialogId == dialog_id) { - state.dialogDetail = dialog; - reverse.forEach((item) => { - let index = state.dialogMsgList.findIndex(({id}) => id == item.id); - if (index === -1) { - state.dialogMsgList.push(item); - } else { - state.dialogMsgList.splice(index, 1, item); - } - }) - } - // 更新会话数据 - this.commit('getDialogUpdate', dialog); - }).catch((data, msg) => { - state.dialogMsgLoad--; - state.cacheDialogList[dialog_id + "::load"] = false; - }); - }, - - /** - * 获取未读信息 - * @param state - */ - getDialogMsgUnread(state) { - const unread = state.dialogMsgUnread; - this.dispatch("call", { - url: 'dialog/msg/unread', - }).then((data, msg) => { - if (unread == state.dialogMsgUnread) { - state.dialogMsgUnread = data.unread; - } else { - setTimeout(() => { - this.commit('getDialogMsgUnread'); - }, 200); - } - }); - }, - - /** - * 根据消息ID 删除 或 替换 会话数据 - * @param state - * @param params {id, data} - */ - spliceDialogMsg(state, params) { - let {id, data} = params; - if (!id) { - return; - } - if (state.method.isJson(data)) { - if (data.id && state.dialogMsgList.find(m => m.id == data.id)) { - data = null; - } - } - let index = state.dialogMsgList.findIndex(m => m.id == id); - if (index > -1) { - if (data) { - state.dialogMsgList.splice(index, 1, state.method.cloneJSON(data)); - // 是最后一条消息时更新会话 last_msg - if (state.dialogMsgList.length - 1 == index) { - const dialog = state.dialogList.find(({id}) => id == data.dialog_id); - if (dialog) dialog.last_msg = data; - } - } else { - state.dialogMsgList.splice(index, 1); - } - } - }, - - /** - * 初始化 websocket - * @param state - */ - wsConnection(state) { - clearTimeout(state.wsTimeout); - if (state.userId === 0) { - if (state.ws) { - state.ws.close(); - state.ws = null; - } - return; - } - let url = window.webSocketConfig.URL; - if (!url) { - url = window.location.origin; - url = url.replace("https://", "wss://"); - url = url.replace("http://", "ws://"); - url += "/ws"; - } - url += "?action=web&token=" + state.userToken; - // - state.ws = new WebSocket(url); - state.ws.onopen = (e) => { - console.log("[WS] Open", e) - }; - state.ws.onclose = (e) => { - console.log("[WS] Close", e); - state.ws = null; - // - clearTimeout(state.wsTimeout); - state.wsTimeout = setTimeout(() => { - this.commit('wsConnection'); - }, 3000); - }; - state.ws.onerror = (e) => { - console.log("[WS] Error", e); - state.ws = null; - // - clearTimeout(state.wsTimeout); - state.wsTimeout = setTimeout(() => { - this.commit('wsConnection'); - }, 3000); - }; - state.ws.onmessage = (e) => { - console.log("[WS] Message", e); - const msgDetail = state.method.jsonParse(event.data); - const {type, msgId} = msgDetail; - switch (type) { - case "open": - state.method.setStorage("userWsFd", msgDetail.data.fd) - break - - case "receipt": - typeof state.wsCall[msgId] === "function" && state.wsCall[msgId](msgDetail.body, true); - delete state.wsCall[msgId]; - break - - case "line": - this.commit('setUserOnlineStatus', msgDetail.data); - break - - default: - msgId && this.commit('wsSend', {type: 'receipt', msgId}); - state.wsMsg = msgDetail; - Object.values(state.wsListener).forEach((call) => { - if (typeof call === "function") { - try { - call(msgDetail); - } catch (err) { - console.log("[WS] Callerr", err); - } - } - }); - if (type === "dialog") { - // 更新消息 - (function (msg) { - const {data} = msg; - const {dialog_id} = data; - if (dialog_id == state.dialogId) { - let index = state.dialogMsgList.findIndex(({id}) => id == data.id); - if (index === -1) { - state.dialogMsgList.push(data); - } else { - state.dialogMsgList.splice(index, 1, data); - } - } - })(msgDetail); - // 更新会话 - (function (msg, that) { - const {mode, data} = msg; - const {dialog_id} = data; - // 更新最后消息 - let dialog = state.dialogList.find(({id}) => id == dialog_id); - if (dialog) { - dialog.last_msg = data; - } else { - that.commit('getDialogOne', dialog_id); - } - if (mode === "add") { - if (dialog) { - // 新增未读数 - if (data.userid !== state.userId) dialog.unread++; - // 移动到首位 - const index = state.dialogList.findIndex(({id}) => id == dialog_id); - if (index > -1) { - const tmp = state.dialogList[index]; - state.dialogList.splice(index, 1); - state.dialogList.unshift(tmp); - } - } - // 新增总未读数 - if (data.userid !== state.userId) state.dialogMsgUnread++; - } - })(msgDetail, this); - } - break - } - } - }, - - /** - * 发送 websocket 消息 - * @param state - * @param params {type, data, callback, msgId} - */ - wsSend(state, params) { - if (!state.method.isJson(params)) { - return; - } - const {type, data, callback} = params; - let msgId = params.msgId; - if (!state.ws) { - typeof callback === "function" && callback(null, false) - return; - } - if (typeof callback === "function") { - msgId = state.method.randomString(16) - state.wsCall[msgId] = callback; - } - try { - state.ws.send(JSON.stringify({ - type, - msgId, - data - })); - } catch (e) { - typeof callback === "function" && callback(null, false) - } - }, - - /** - * 发送已阅消息 - * @param state - * @param msgData - */ - wsMsgRead(state, msgData) { - if (msgData.userid == state.userId) return; - if (typeof msgData.r === "undefined") msgData.r = {}; - // - const {id, dialog_id, r} = msgData; - if (!r.read_at) { - r.read_at = state.method.formatDate('Y-m-d H:i:s'); - let dialog = state.dialogList.find(({id}) => id == dialog_id); - if (dialog && dialog.unread > 0) { - dialog.unread-- - state.dialogMsgUnread--; - } - } - // - state.wsReadWaitList.push(id); - clearTimeout(state.wsReadTimeout); - state.wsReadTimeout = setTimeout(() => { - this.commit('wsSend', { - type: 'readMsg', - data: { - id: state.method.cloneJSON(state.wsReadWaitList) - } - }); - state.wsReadWaitList = []; - }, 10); - }, - - /** - * 监听消息 - * @param state - * @param params {name, callback} - */ - wsMsgListener(state, params) { - const {name, callback} = params; - if (typeof callback === "function") { - state.wsListener[name] = callback; - } else { - state.wsListener[name] && delete state.wsListener[name]; - } - }, - - /** - * 关闭 websocket - * @param state - */ - wsClose(state) { - state.ws && state.ws.close(); - }, - - /** - * 登出(打开登录页面) - */ - logout() { - const from = window.location.pathname == '/' ? '' : encodeURIComponent(window.location.href); - this.commit('setUserInfo', {}); - $A.goForward({path: '/login', query: from ? {from: from} : {}}, true); - } }