no message

This commit is contained in:
kuaifan 2021-06-22 22:04:08 +08:00
parent b8d06fcd36
commit 2f9cd34ad2
12 changed files with 269 additions and 386 deletions

View File

@ -42,11 +42,11 @@ class DialogController extends AbstractController
} }
/** /**
* 获取会话基础信息 * 获取单个会话信息
* *
* @apiParam {Number} dialog_id 对话ID * @apiParam {Number} dialog_id 对话ID
*/ */
public function basic() public function one()
{ {
$user = User::auth(); $user = User::auth();
// //

View File

@ -29,7 +29,7 @@
<li @click="toggleRoute('messenger')" :class="classNameRoute('messenger')"> <li @click="toggleRoute('messenger')" :class="classNameRoute('messenger')">
<i class="iconfont">&#xe6eb;</i> <i class="iconfont">&#xe6eb;</i>
<div class="menu-title">{{$L('消息')}}</div> <div class="menu-title">{{$L('消息')}}</div>
<Badge class="menu-badge" :count="dialogMsgUnread"></Badge> <Badge class="menu-badge" :count="msgAllUnread"></Badge>
</li> </li>
<li class="menu-project"> <li class="menu-project">
<ul> <ul>
@ -165,30 +165,25 @@ export default {
...mapState([ ...mapState([
'userId', 'userId',
'userInfo', 'userInfo',
'dialogMsgUnread', 'dialogs',
'projects', 'projects',
'projectChatShow',
'taskId', 'taskId',
]), ]),
...mapGetters(['taskData'])
...mapGetters(['taskData']),
msgAllUnread() {
let num = 0;
this.dialogs.map(({unread}) => {
num += unread;
})
return num;
}
}, },
watch: { watch: {
'$route' (route) { '$route' (route) {
this.curPath = route.path; this.curPath = route.path;
},
taskId (id) {
if (id > 0) {
if (this.projectChatShow) {
this._projectChatShow = true;
this.$store.dispatch("toggleBoolean", "projectChatShow");
}
} else {
if (this._projectChatShow) {
this._projectChatShow = false;
this.$store.dispatch("toggleBoolean", "projectChatShow");
}
}
} }
}, },

View File

@ -7,14 +7,14 @@
<slot name="head"> <slot name="head">
<div class="dialog-title"> <div class="dialog-title">
<div class="main-title"> <div class="main-title">
<h2>{{dialogDetail.name}}</h2> <h2>{{dialogData.name}}</h2>
<em v-if="peopleNum > 0">({{peopleNum}})</em> <em v-if="peopleNum > 0">({{peopleNum}})</em>
</div> </div>
<template v-if="dialogDetail.type === 'group'"> <template v-if="dialogData.type === 'group'">
<div v-if="dialogDetail.group_type === 'project'" class="sub-title pointer" @click="openProject"> <div v-if="dialogData.group_type === 'project'" class="sub-title pointer" @click="openProject">
{{$L('项目聊天室')}} {{$L('打开项目管理')}} {{$L('项目聊天室')}} {{$L('打开项目管理')}}
</div> </div>
<div v-else-if="dialogDetail.group_type === 'task'" class="sub-title pointer" @click="openTask"> <div v-else-if="dialogData.group_type === 'task'" class="sub-title pointer" @click="openTask">
{{$L('任务聊天室')}} {{$L('查看任务详情')}} {{$L('任务聊天室')}} {{$L('查看任务详情')}}
</div> </div>
</template> </template>
@ -28,11 +28,11 @@
static> static>
<div ref="manageList" class="dialog-list"> <div ref="manageList" class="dialog-list">
<ul> <ul>
<li v-if="dialogMsgHasMorePages" class="history" @click="loadNextPage">{{$L('加载历史消息')}}</li> <li v-if="dialogData.hasMorePages" class="history" @click="loadNextPage">{{$L('加载历史消息')}}</li>
<li v-else-if="dialogMsgLoad > 0 && dialogMsgList.length === 0" class="loading"><Loading/></li> <li v-else-if="dialogData.loading > 0 && dialogMsgList.length === 0" class="loading"><Loading/></li>
<li v-else-if="dialogMsgList.length === 0" class="nothing">{{$L('暂无消息')}}</li> <li v-else-if="dialogMsgList.length === 0" class="nothing">{{$L('暂无消息')}}</li>
<li <li
v-for="item in dialogMsgLists" v-for="item in dialogMsgList"
:id="'view_' + item.id" :id="'view_' + item.id"
:key="item.id" :key="item.id"
:class="{self:item.userid == userId, 'history-tip': topId == item.id}"> :class="{self:item.userid == userId, 'history-tip': topId == item.id}">
@ -40,7 +40,17 @@
<div class="dialog-avatar"> <div class="dialog-avatar">
<UserAvatar :userid="item.userid" :tooltip-disabled="item.userid == userId" :size="30"/> <UserAvatar :userid="item.userid" :tooltip-disabled="item.userid == userId" :size="30"/>
</div> </div>
<DialogView :msg-data="item" :dialog-type="dialogDetail.type"/> <DialogView :msg-data="item" :dialog-type="dialogData.type"/>
</li>
<li
v-for="item in tempMsgList"
:id="'tmp_' + item.id"
:key="'tmp_' + item.id"
:class="{self:item.userid == userId}">
<div class="dialog-avatar">
<UserAvatar :userid="item.userid" :tooltip-disabled="item.userid == userId" :size="30"/>
</div>
<DialogView :msg-data="item" :dialog-type="dialogData.type"/>
</li> </li>
</ul> </ul>
</div> </div>
@ -83,6 +93,13 @@ import DialogUpload from "./DialogUpload";
export default { export default {
name: "DialogWrapper", name: "DialogWrapper",
components: {DialogUpload, DialogView, ScrollerY, DragInput}, components: {DialogUpload, DialogView, ScrollerY, DragInput},
props: {
dialogId: {
type: Number,
default: 0
},
},
data() { data() {
return { return {
autoBottom: true, autoBottom: true,
@ -93,37 +110,45 @@ export default {
msgText: '', msgText: '',
msgNew: 0, msgNew: 0,
topId: 0, topId: 0,
tempMsgs: []
} }
}, },
destroyed() {
this.$store.state.dialogId = 0;
},
deactivated() {
this.$store.state.dialogId = 0;
},
computed: { computed: {
...mapState([ ...mapState([
'userId', 'userId',
'dialogId', 'dialogs',
'dialogDetail', 'dialogMsgs',
'dialogMsgLoad',
'dialogMsgPush', 'dialogMsgPush',
'dialogMsgList',
'dialogMsgHasMorePages',
]), ]),
dialogMsgLists() { dialogData() {
const list = $A.cloneJSON(this.dialogMsgList); return this.dialogs.find(({id}) => id == this.dialogId) || {};
return list.sort((a, b) => { },
dialogMsgList() {
if (!this.dialogId) {
return [];
}
return $A.cloneJSON(this.dialogMsgs.filter(({dialog_id}) => {
return dialog_id == this.dialogId;
})).sort((a, b) => {
return a.id - b.id; return a.id - b.id;
}); });
}, },
tempMsgList() {
if (!this.dialogId) {
return [];
}
return $A.cloneJSON(this.tempMsgs.filter(({dialog_id}) => {
return dialog_id == this.dialogId;
}));
},
peopleNum() { peopleNum() {
return this.dialogDetail.type === 'group' ? $A.runNum(this.dialogDetail.people) : 0; return this.dialogData.type === 'group' ? $A.runNum(this.dialogData.people) : 0;
} }
}, },
@ -136,10 +161,14 @@ export default {
} }
}, },
dialogId() { dialogId: {
this.autoBottom = true; handler(id) {
this.msgNew = 0; this.autoBottom = true;
this.topId = -1; this.msgNew = 0;
this.topId = -1;
this.$store.dispatch("getDialogMsgs", id);
},
immediate: true
} }
}, },
@ -153,8 +182,9 @@ export default {
return; return;
} }
let tempId = $A.randomString(16); let tempId = $A.randomString(16);
this.dialogMsgList.push({ this.tempMsgs.push({
id: tempId, id: tempId,
dialog_id: this.dialogData.id,
type: 'text', type: 'text',
userid: this.userId, userid: this.userId,
msg: { msg: {
@ -162,7 +192,6 @@ export default {
}, },
}); });
this.autoBottom = true; this.autoBottom = true;
this.$store.commit("dialogMoveToTop", this.dialogId);
this.onActive(); this.onActive();
// //
this.$store.dispatch("call", { this.$store.dispatch("call", {
@ -172,13 +201,15 @@ export default {
text: this.msgText, text: this.msgText,
}, },
}).then(({data}) => { }).then(({data}) => {
this.$store.dispatch("dialogMsgUpdate", {id: tempId, data}); this.tempMsgs = this.tempMsgs.filter(({id}) => id != tempId)
this.$store.dispatch("saveDialogMsg", data);
}).catch(({msg}) => { }).catch(({msg}) => {
$A.modalError(msg); $A.modalError(msg);
this.$store.dispatch("dialogMsgUpdate", {id: tempId}); this.tempMsgs = this.tempMsgs.filter(({id}) => id != tempId)
}); });
// //
this.msgText = ''; this.msgText = '';
this.$store.dispatch("dialogMoveTop", this.dialogId);
}, },
chatKeydown(e) { chatKeydown(e) {
@ -233,23 +264,25 @@ export default {
chatFile(type, file) { chatFile(type, file) {
switch (type) { switch (type) {
case 'progress': case 'progress':
this.dialogMsgList.push({ this.tempMsgs.push({
id: file.tempId, id: file.tempId,
dialog_id: this.dialogData.id,
type: 'loading', type: 'loading',
userid: this.userId, userid: this.userId,
msg: { }, msg: { },
}); });
this.autoBottom = true; this.autoBottom = true;
this.$store.commit("dialogMoveToTop", this.dialogId); this.$store.dispatch("dialogMoveTop", this.dialogId);
this.onActive(); this.onActive();
break; break;
case 'error': case 'error':
this.$store.dispatch("dialogMsgUpdate", {id: file.tempId}); this.tempMsgs = this.tempMsgs.filter(({id}) => id != tempId)
break; break;
case 'success': case 'success':
this.$store.dispatch("dialogMsgUpdate", {id: file.tempId, data: file.data}); this.tempMsgs = this.tempMsgs.filter(({id}) => id != tempId)
this.$store.dispatch("saveDialogMsg", file.data);
break; break;
} }
}, },
@ -308,22 +341,22 @@ export default {
}, },
openProject() { openProject() {
if (!this.dialogDetail.group_info) { if (!this.dialogData.group_info) {
return; return;
} }
this.goForward({path: '/manage/project/' + this.dialogDetail.group_info.id}); this.goForward({path: '/manage/project/' + this.dialogData.group_info.id});
}, },
openTask() { openTask() {
if (!this.dialogDetail.group_info) { if (!this.dialogData.group_info) {
return; return;
} }
this.$store.dispatch("openTask", this.dialogDetail.group_info.id); this.$store.dispatch("openTask", this.dialogData.group_info.id);
}, },
loadNextPage() { loadNextPage() {
let topId = this.dialogMsgLists[0].id; let topId = this.dialogMsgList[0].id;
this.$store.dispatch('getDialogMsgListNextPage').then(() => { this.$store.dispatch('getDialogMsgNextPage').then(() => {
this.$nextTick(() => { this.$nextTick(() => {
this.topId = topId; this.topId = topId;
let dom = document.getElementById("view_" + topId); let dom = document.getElementById("view_" + topId);

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="project-dialog"> <div class="project-dialog">
<DialogWrapper class="project-dialog-wrapper"> <DialogWrapper :dialog-id="projectData.dialog_id" class="project-dialog-wrapper">
<div slot="head"> <div slot="head">
<div class="dialog-user"> <div class="dialog-user">
<div class="member-head"> <div class="member-head">
@ -22,7 +22,7 @@
</template> </template>
<script> <script>
import {mapGetters, mapState} from "vuex"; import {mapGetters} from "vuex";
import DialogWrapper from "./DialogWrapper"; import DialogWrapper from "./DialogWrapper";
export default { export default {
@ -35,29 +35,7 @@ export default {
}, },
computed: { computed: {
...mapState(['projectChatShow']),
...mapGetters(['projectData']) ...mapGetters(['projectData'])
}, },
watch: {
'projectData.dialog_id' () {
this.getMsgList()
},
projectChatShow: {
handler() {
this.getMsgList()
},
immediate: true
}
},
methods: {
getMsgList() {
if (this.projectChatShow && this.projectData.dialog_id) {
this.$store.dispatch("getDialogMsgList", this.projectData.dialog_id);
}
}
}
} }
</script> </script>

View File

@ -23,7 +23,7 @@
</div> </div>
</Tooltip> </Tooltip>
</li> </li>
<li :class="['project-icon', projectChatShow ? 'active' : '']" @click="$store.dispatch('toggleBoolean', 'projectChatShow')"> <li :class="['project-icon', tablePanel('chat') ? 'active' : '']" @click="$store.dispatch('toggleTablePanel', 'chat')">
<Icon class="menu-icon" type="ios-chatbubbles" /> <Icon class="menu-icon" type="ios-chatbubbles" />
<Badge class="menu-badge" :count="msgUnread"></Badge> <Badge class="menu-badge" :count="msgUnread"></Badge>
</li> </li>
@ -46,7 +46,7 @@
<div v-if="projectData.desc" class="project-subtitle">{{projectData.desc}}</div> <div v-if="projectData.desc" class="project-subtitle">{{projectData.desc}}</div>
<div class="project-switch"> <div class="project-switch">
<div v-if="completedCount > 0" class="project-checkbox"> <div v-if="completedCount > 0" class="project-checkbox">
<Checkbox :value="projectCompleteShow" @on-change="$store.dispatch('toggleBoolean', 'projectCompleteShow')">{{$L('显示已完成')}}</Checkbox> <Checkbox :value="showCompletedTask" @on-change="$store.dispatch('toggleBoolean', 'showCompletedTask')">{{$L('显示已完成')}}</Checkbox>
</div> </div>
<div :class="['project-switch-button', !tablePanel('card') ? 'menu' : '']" @click="$store.dispatch('toggleTablePanel', 'card')"> <div :class="['project-switch-button', !tablePanel('card') ? 'menu' : '']" @click="$store.dispatch('toggleTablePanel', 'card')">
<div><i class="iconfont">&#xe60c;</i></div> <div><i class="iconfont">&#xe60c;</i></div>
@ -401,29 +401,28 @@ export default {
computed: { computed: {
...mapState([ ...mapState([
'userId', 'userId',
'dialogList', 'dialogs',
'projectId', 'projectId',
'projectLoad', 'projectLoad',
'tasks', 'tasks',
'columns', 'columns',
'projectChatShow', 'showCompletedTask',
'projectCompleteShow',
]), ]),
...mapGetters(['projectData', 'tablePanel']), ...mapGetters(['projectData', 'tablePanel']),
msgUnread() { msgUnread() {
const {dialogList, projectData} = this; const {dialogs, projectData} = this;
const dialog = dialogList.find(({id}) => id === projectData.dialog_id); const dialog = dialogs.find(({id}) => id === projectData.dialog_id);
return dialog ? dialog.unread : 0; return dialog ? dialog.unread : 0;
}, },
panelTask() { panelTask() {
const {searchText, projectCompleteShow} = this; const {searchText, showCompletedTask} = this;
return function (list) { return function (list) {
if (!projectCompleteShow) { if (!showCompletedTask) {
list = list.filter(({complete_at}) => { list = list.filter(({complete_at}) => {
return !complete_at; return !complete_at;
}); });
@ -438,12 +437,12 @@ export default {
}, },
myList() { myList() {
const {projectId, tasks, searchText, projectCompleteShow, userId} = this; const {projectId, tasks, searchText, showCompletedTask, userId} = this;
const array = tasks.filter((task) => { const array = tasks.filter((task) => {
if (task.project_id != projectId) { if (task.project_id != projectId) {
return false; return false;
} }
if (!projectCompleteShow) { if (!showCompletedTask) {
if (task.complete_at) { if (task.complete_at) {
return false; return false;
} }
@ -467,12 +466,12 @@ export default {
}, },
undoneList() { undoneList() {
const {projectId, tasks, searchText, projectCompleteShow} = this; const {projectId, tasks, searchText, showCompletedTask} = this;
const array = tasks.filter((task) => { const array = tasks.filter((task) => {
if (task.project_id != projectId) { if (task.project_id != projectId) {
return false; return false;
} }
if (!projectCompleteShow) { if (!showCompletedTask) {
if (task.complete_at) { if (task.complete_at) {
return false; return false;
} }
@ -936,8 +935,8 @@ export default {
taskIsHidden(task) { taskIsHidden(task) {
const {name, desc, complete_at} = task; const {name, desc, complete_at} = task;
const {searchText, projectCompleteShow} = this; const {searchText, showCompletedTask} = this;
if (!projectCompleteShow) { if (!showCompletedTask) {
if (complete_at) { if (complete_at) {
return true; return true;
} }

View File

@ -332,7 +332,7 @@
</div> </div>
<div class="task-dialog" :style="dialogStyle"> <div class="task-dialog" :style="dialogStyle">
<template v-if="taskDetail.dialog_id > 0"> <template v-if="taskDetail.dialog_id > 0">
<DialogWrapper ref="dialog"> <DialogWrapper ref="dialog" :dialog-id="taskDetail.dialog_id">
<div slot="head" class="head"> <div slot="head" class="head">
<Icon class="icon" type="ios-chatbubbles-outline" /> <Icon class="icon" type="ios-chatbubbles-outline" />
<div class="nav"> <div class="nav">
@ -638,11 +638,6 @@ export default {
immediate: true, immediate: true,
deep: true deep: true
}, },
'openTask.dialog_id' (dialog_id) {
if (dialog_id) {
this.$store.dispatch("getDialogMsgList", dialog_id)
}
},
'openTask._show' (show) { 'openTask._show' (show) {
if (show) { if (show) {
this.$nextTick(() => { this.$nextTick(() => {

View File

@ -9,15 +9,16 @@
</div> </div>
</div> </div>
<div v-if="tabActive==='dialog'" class="messenger-nav"> <div v-if="tabActive==='dialog'" class="messenger-nav">
<p :class="{active:dialogType==''}" @click="dialogType=''">{{$L('全部')}}</p> <p
<p :class="{active:dialogType=='project'}" @click="dialogType='project'">{{$L('项目')}}</p> v-for="(item, key) in dialogType"
<p :class="{active:dialogType=='task'}" @click="dialogType='task'">{{$L('任务')}}</p> :key="key"
<p :class="{active:dialogType=='user'}" @click="dialogType='user'">{{$L('个人')}}</p> :class="{active:dialogActive==item.type}"
@click="dialogActive=item.type">{{$L(item.name)}}</p>
</div> </div>
<div ref="list" class="messenger-list overlay-y"> <div ref="list" class="messenger-list overlay-y">
<ul v-if="tabActive==='dialog'" class="dialog"> <ul v-if="tabActive==='dialog'" class="dialog">
<li <li
v-for="(dialog, key) in dialogLists" v-for="(dialog, key) in dialogList"
:key="key" :key="key"
:class="{active: dialog.id == dialogId}" :class="{active: dialog.id == dialogId}"
@click="openDialog(dialog, true)"> @click="openDialog(dialog, true)">
@ -38,7 +39,6 @@
</div> </div>
<Badge class="dialog-num" :count="dialog.unread"/> <Badge class="dialog-num" :count="dialog.unread"/>
</li> </li>
<li v-if="dialogLoad > 0" class="loading"><Loading/></li>
</ul> </ul>
<ul v-else class="contacts"> <ul v-else class="contacts">
<li v-for="(users, label) in contactsLists"> <li v-for="(users, label) in contactsLists">
@ -60,7 +60,7 @@
</div> </div>
<div class="messenger-msg"> <div class="messenger-msg">
<DialogWrapper v-if="dialogId > 0" @on-active="scrollIntoActive"/> <DialogWrapper v-if="dialogId > 0" :dialogId="dialogId" @on-active="scrollIntoActive"/>
<div v-else class="dialog-no"> <div v-else class="dialog-no">
<div class="dialog-no-icon"><Icon type="ios-chatbubbles" /></div> <div class="dialog-no-icon"><Icon type="ios-chatbubbles" /></div>
<div class="dialog-no-text">{{$L('选择一个会话开始聊天')}}</div> <div class="dialog-no-text">{{$L('选择一个会话开始聊天')}}</div>
@ -80,50 +80,40 @@ export default {
return { return {
tabActive: 'dialog', tabActive: 'dialog',
dialogLoad: 0, dialogType: [
{type: '', name: '全部'},
{type: 'project', name: '项目'},
{type: 'task', name: '任务'},
{type: 'user', name: '个人'},
],
dialogActive: '',
dialogKey: '', dialogKey: '',
dialogType: '', dialogId: 0,
dialogMounted: false,
contactsLoad: 0, contactsLoad: 0,
contactsLists: null, contactsLists: null,
} }
}, },
mounted() {
this.dialogLoad++;
this.$store.dispatch("getDialogList").then(() => {
this.dialogLoad--;
this.dialogMounted = true;
this.openDialogStorage();
}).catch(() => {
this.dialogLoad--;
this.dialogMounted = true;
this.openDialogStorage();
});
},
activated() { activated() {
if (this.dialogMounted) { this.$store.dispatch("getDialogs");
this.$store.dispatch("getDialogList"); this.openDialogStorage();
this.openDialogStorage();
}
}, },
computed: { computed: {
...mapState(['userId', 'dialogId', 'dialogList']), ...mapState(['userId', 'dialogs']),
dialogLists() { dialogList() {
const {dialogType, dialogKey} = this; const {dialogActive, dialogKey} = this;
if (dialogType == '' && dialogKey == '') { if (dialogActive == '' && dialogKey == '') {
return this.dialogList; return this.dialogs;
} }
return this.dialogList.filter(({name, type, group_type, last_msg}) => { return this.dialogs.filter(({name, type, group_type, last_msg}) => {
if (dialogType) { if (dialogActive) {
switch (dialogType) { switch (dialogActive) {
case 'project': case 'project':
case 'task': case 'task':
if (group_type != dialogType) { if (group_type != dialogActive) {
return false; return false;
} }
break; break;
@ -158,15 +148,15 @@ export default {
methods: { methods: {
openDialog(dialog, smooth) { openDialog(dialog, smooth) {
this.$store.state.method.setStorage("messengerDialogId", dialog.id) this.$store.state.method.setStorage("messenger::dialogId", dialog.id)
this.$store.dispatch("getDialogMsgList", dialog.id); this.dialogId = dialog.id;
this.scrollIntoActive(smooth); this.scrollIntoActive(smooth);
}, },
openDialogStorage() { openDialogStorage() {
let tmpId = this.$store.state.method.getStorageInt("messengerDialogId") this.dialogId = this.$store.state.method.getStorageInt("messenger::dialogId")
if (tmpId > 0) { if (this.dialogId > 0) {
const dialog = this.dialogList.find(({id}) => id === tmpId); const dialog = this.dialogs.find(({id}) => id === this.dialogId);
dialog && this.openDialog(dialog, false); dialog && this.openDialog(dialog, false);
} }
}, },
@ -259,9 +249,9 @@ export default {
scrollMode: 'if-needed', scrollMode: 'if-needed',
}); });
} else { } else {
let dialog = this.dialogList.find(({id}) => id == this.dialogId) let dialog = this.dialogs.find(({id}) => id == this.dialogId)
if (dialog && this.dialogType) { if (dialog && this.dialogActive) {
this.dialogType = ''; this.dialogActive = '';
this.$nextTick(() => { this.$nextTick(() => {
let active = this.$refs.list.querySelector(".active") let active = this.$refs.list.querySelector(".active")
if (active) { if (active) {

View File

@ -2,11 +2,12 @@
<div class="page-project"> <div class="page-project">
<PageTitle>{{ $L('项目面板') }}</PageTitle> <PageTitle>{{ $L('项目面板') }}</PageTitle>
<ProjectList/> <ProjectList/>
<ProjectDialog v-if="$store.state.projectChatShow"/> <ProjectDialog v-if="tablePanel('chat')"/>
</div> </div>
</template> </template>
<script> <script>
import {mapGetters} from "vuex";
import ProjectList from "./components/ProjectList"; import ProjectList from "./components/ProjectList";
import ProjectDialog from "./components/ProjectDialog"; import ProjectDialog from "./components/ProjectDialog";
export default { export default {
@ -16,9 +17,15 @@ export default {
project_id: 0, project_id: 0,
} }
}, },
mounted() { mounted() {
this.project_id = this.$route.params.id; this.project_id = this.$route.params.id;
}, },
computed: {
...mapGetters(['tablePanel']),
},
watch: { watch: {
'$route' (route) { '$route' (route) {
this.project_id = route.params.id; this.project_id = route.params.id;

View File

@ -191,7 +191,7 @@ export default {
state.userIsAdmin = state.method.inArray('admin', userInfo.identity); state.userIsAdmin = state.method.inArray('admin', userInfo.identity);
state.method.setStorage("userInfo", state.userInfo); state.method.setStorage("userInfo", state.userInfo);
dispatch("getProjects"); dispatch("getProjects");
dispatch("getDialogMsgUnread"); dispatch("getDialogs");
dispatch("websocketConnection"); dispatch("websocketConnection");
resolve() resolve()
}); });
@ -543,7 +543,6 @@ export default {
}); });
}, },
/** *****************************************************************************************/ /** *****************************************************************************************/
/** ************************************** 任务 **********************************************/ /** ************************************** 任务 **********************************************/
/** *****************************************************************************************/ /** *****************************************************************************************/
@ -941,7 +940,6 @@ export default {
}); });
}, },
/** *****************************************************************************************/ /** *****************************************************************************************/
/** ************************************** 会话 **********************************************/ /** ************************************** 会话 **********************************************/
/** *****************************************************************************************/ /** *****************************************************************************************/
@ -953,15 +951,21 @@ export default {
* @param data * @param data
*/ */
saveDialog({state, dispatch}, data) { saveDialog({state, dispatch}, data) {
let splice = false; if (state.method.isArray(data)) {
state.dialogList.some(({id, unread}, index) => { data.forEach((dialog) => {
if (id == data.id) { dispatch("saveDialog", dialog)
unread !== data.unread && dispatch('getDialogMsgUnread'); });
state.dialogList.splice(index, 1, data); } else if (state.method.isJson(data)) {
return splice = true; let index = state.dialogs.findIndex(({id}) => id == data.id);
if (index > -1) {
state.dialogs.splice(index, 1, Object.assign(state.dialogs[index], data));
} else {
state.dialogs.push(data);
} }
}); setTimeout(() => {
!splice && state.dialogList.unshift(data) state.method.setStorage("cacheDialogs", state.cacheDialogs = state.dialogs);
})
}
}, },
/** /**
@ -969,23 +973,12 @@ export default {
* @param state * @param state
* @param dispatch * @param dispatch
*/ */
getDialogList({state, dispatch}) { getDialogs({state, dispatch}) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
dispatch("call", { dispatch("call", {
url: 'dialog/lists', url: 'dialog/lists',
}).then(result => { }).then(result => {
if (state.dialogList.length === 0) { dispatch("saveDialog", result.data.data);
state.dialogList = result.data.data;
} else {
result.data.data.forEach((dialog) => {
let index = state.dialogList.findIndex(({id}) => id == dialog.id);
if (index > -1) {
dialog = Object.assign(state.dialogList[index], dialog)
state.dialogList.splice(index, 1);
}
state.dialogList.push(dialog);
});
}
resolve(result); resolve(result);
}).catch(e => { }).catch(e => {
console.error(e); console.error(e);
@ -1000,9 +993,9 @@ export default {
* @param dispatch * @param dispatch
* @param dialog_id * @param dialog_id
*/ */
getDialogBasic({state, dispatch}, dialog_id) { getDialogOne({state, dispatch}, dialog_id) {
dispatch("call", { dispatch("call", {
url: 'dialog/basic', url: 'dialog/one',
data: { data: {
dialog_id, dialog_id,
}, },
@ -1029,7 +1022,6 @@ export default {
}, },
}).then(result => { }).then(result => {
state.method.setStorage("messengerDialogId", result.data.id) state.method.setStorage("messengerDialogId", result.data.id)
dispatch("getDialogMsgList", result.data.id);
dispatch("saveDialog", result.data); dispatch("saveDialog", result.data);
resolve(result); resolve(result);
}).catch(e => { }).catch(e => {
@ -1039,62 +1031,83 @@ export default {
}); });
}, },
/**
* 将会话移动到首位
* @param state
* @param dialog_id
*/
dialogMoveTop({state}, dialog_id) {
const index = state.dialogs.findIndex(({id}) => id == dialog_id);
if (index > -1) {
const tmp = state.method.cloneJSON(state.dialogs[index]);
state.dialogs.splice(index, 1);
state.dialogs.unshift(tmp);
}
},
/** *****************************************************************************************/
/** ************************************** 消息 **********************************************/
/** *****************************************************************************************/
/**
* 更新消息数据
* @param state
* @param dispatch
* @param data
*/
saveDialogMsg({state, dispatch}, data) {
if (state.method.isArray(data)) {
data.forEach((msg) => {
dispatch("saveDialogMsg", msg)
});
} else if (state.method.isJson(data)) {
let index = state.dialogMsgs.findIndex(({id}) => id == data.id);
if (index > -1) {
state.dialogMsgs.splice(index, 1, Object.assign(state.dialogMsgs[index], data));
} else {
state.dialogMsgs.push(data);
}
setTimeout(() => {
state.method.setStorage("cacheDialogMsgs", state.cacheDialogMsgs = state.dialogMsgs);
})
}
},
/** /**
* 获取会话消息 * 获取会话消息
* @param state * @param state
* @param dispatch * @param dispatch
* @param commit
* @param dialog_id * @param dialog_id
*/ */
getDialogMsgList({state, dispatch, commit}, dialog_id) { getDialogMsgs({state, dispatch}, dialog_id) {
if (state.method.runNum(dialog_id) === 0) { const dialog = state.dialogs.filter(({id}) => id == dialog_id);
if (!dialog) {
return; return;
} }
if (state.dialogId == dialog_id) { if (dialog.loading) {
return; return;
} }
dialog.loading = true;
dialog.currentPage = 1;
dialog.hasMorePages = false;
// //
state.dialogMsgList = [];
state.dialogMsgCurrentPage = 1;
state.dialogMsgHasMorePages = false;
if (state.method.isJson(state.cacheDialogMsg[dialog_id])) {
let length = state.cacheDialogMsg[dialog_id].data.length;
if (length > 50) {
state.cacheDialogMsg[dialog_id].data.splice(0, length - 50);
}
state.dialogDetail = state.cacheDialogMsg[dialog_id].dialog
state.dialogMsgList = state.cacheDialogMsg[dialog_id].data
}
state.dialogId = dialog_id;
//
if (state.cacheDialogMsg[dialog_id + "::load"]) {
return;
}
state.cacheDialogMsg[dialog_id + "::load"] = true;
//
state.dialogMsgLoad++;
dispatch("call", { dispatch("call", {
url: 'dialog/msg/lists', url: 'dialog/msg/lists',
data: { data: {
dialog_id: dialog_id, dialog_id: dialog_id,
page: state.dialogMsgCurrentPage page: dialog.currentPage
}, },
}).then(result => { }).then(result => {
state.dialogMsgLoad--; dialog.loading = false;
state.cacheDialogMsg[dialog_id + "::load"] = false; const ids = result.data.data.map(({id}) => id)
const data = result.data; if (ids.length == 0) {
// 更新缓存 return;
state.cacheDialogMsg[dialog_id] = { }
dialog: data.dialog, state.dialogMsgs = state.dialogMsgs.filter((item) => item.dialog_id != dialog_id || ids.includes(item.id));
data: [], dispatch("saveDialogMsg", result.data.data);
};
state.method.setStorage("cacheDialogMsg", state.cacheDialogMsg);
// 更新当前会话消息
commit("dialogMsgListSuccess", data);
}).catch(e => { }).catch(e => {
console.error(e); console.error(e);
state.dialogMsgLoad--; dialog.loading = false;
state.cacheDialogMsg[dialog_id + "::load"] = false;
}); });
}, },
@ -1102,97 +1115,41 @@ export default {
* 获取下一页会话消息 * 获取下一页会话消息
* @param state * @param state
* @param dispatch * @param dispatch
* @param commit * @param dialog_id
*/ */
getDialogMsgListNextPage({state, dispatch, commit}) { getDialogMsgNextPage({state, dispatch}, dialog_id) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
if (!state.dialogMsgHasMorePages) { const dialog = state.dialogs.filter(({id}) => id == dialog_id);
if (!dialog) {
return; return;
} }
state.dialogMsgHasMorePages = false; if (!dialog.hasMorePages) {
state.dialogMsgCurrentPage++; return;
}
if (dialog.loading) {
return;
}
dialog.loading = true;
dialog.currentPage++;
// //
const dialog_id = state.dialogId;
//
state.dialogMsgLoad++;
dispatch("call", { dispatch("call", {
url: 'dialog/msg/lists', url: 'dialog/msg/lists',
data: { data: {
dialog_id: dialog_id, dialog_id: dialog_id,
page: state.dialogMsgCurrentPage page: dialog.currentPage
}, },
}).then(result => { }).then(result => {
state.dialogMsgLoad--; dialog.loading = false;
commit("dialogMsgListSuccess", result.data); dispatch("saveDialogMsg", result.data);
resolve(result) resolve(result)
}).catch(e => { }).catch(e => {
console.error(e); console.error(e);
state.dialogMsgLoad--; dialog.loading = false;
reject(e) reject(e)
}); });
}); });
}, },
/**
* 获取未读信息
* @param state
* @param dispatch
*/
getDialogMsgUnread({state, dispatch}) {
if (state.userId === 0) {
state.dialogMsgUnread = 0;
return;
}
const unread = state.dialogMsgUnread;
dispatch("call", {
url: 'dialog/msg/unread',
}).then(result => {
if (unread == state.dialogMsgUnread) {
state.dialogMsgUnread = result.data.unread;
} else {
setTimeout(() => {
dispatch('getDialogMsgUnread');
}, 200);
}
});
},
/**
* 根据消息ID 删除 替换 会话数据
* @param state
* @param commit
* @param params {id, data}
*/
dialogMsgUpdate({state, commit}, params) {
let {id, data} = params;
if (!id) {
return;
}
if (state.method.isJson(data)) {
const task = state.tasks.find(({dialog_id}) => dialog_id === data.dialog_id);
if (task) {
task.msg_num++;
}
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));
commit("dialogMsgListStorageCurrent");
// 是最后一条消息时更新会话 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 state
@ -1208,10 +1165,9 @@ export default {
return; return;
} }
r.read_at = state.method.formatDate('Y-m-d H:i:s'); r.read_at = state.method.formatDate('Y-m-d H:i:s');
let dialog = state.dialogList.find(({id}) => id == dialog_id); let dialog = state.dialogs.find(({id}) => id == dialog_id);
if (dialog && dialog.unread > 0) { if (dialog && dialog.unread > 0) {
dialog.unread-- dialog.unread--
state.dialogMsgUnread--;
} }
// //
state.wsReadWaitList.push(id); state.wsReadWaitList.push(id);
@ -1312,25 +1268,17 @@ export default {
const {mode, data} = msg; const {mode, data} = msg;
const {dialog_id} = data; const {dialog_id} = data;
// 更新消息列表 // 更新消息列表
if (dialog_id == state.dialogId) { state.dialogMsgPush = data;
let index = state.dialogMsgList.findIndex(({id}) => id == data.id); dispatch("saveDialogMsg", data)
if (index === -1) {
state.dialogMsgPush = data;
state.dialogMsgList.push(data);
} else {
state.dialogMsgList.splice(index, 1, data);
}
commit("dialogMsgListStorageCurrent");
}
if (mode === "add2") { if (mode === "add2") {
return; return;
} }
// 更新最后消息 // 更新最后消息
let dialog = state.dialogList.find(({id}) => id == dialog_id); let dialog = state.dialogs.find(({id}) => id == dialog_id);
if (dialog) { if (dialog) {
dialog.last_msg = data; dialog.last_msg = data;
} else { } else {
dispatch("getDialogBasic", dialog_id); dispatch("getDialogOne", dialog_id);
} }
if (mode === "add1") { if (mode === "add1") {
// 更新对话列表 // 更新对话列表
@ -1338,13 +1286,11 @@ export default {
// 新增未读数 // 新增未读数
if (data.userid !== state.userId) dialog.unread++; if (data.userid !== state.userId) dialog.unread++;
// 移动到首位 // 移动到首位
commit("dialogMoveToTop", dialog_id); dispatch("dialogMoveTop", dialog_id);
} }
// 新增任务消息数量 // 新增任务消息数量
const task = state.tasks.find(({dialog_id}) => dialog_id === data.dialog_id); const task = state.tasks.find(({dialog_id}) => dialog_id === dialog_id);
if (task) task.msg_num++; if (task) task.msg_num++;
// 新增总未读数
if (data.userid !== state.userId) state.dialogMsgUnread++;
} }
})(msgDetail); })(msgDetail);
break; break;

View File

@ -59,6 +59,7 @@ export default {
cache = { cache = {
project_id: state.projectId, project_id: state.projectId,
card: true, card: true,
chat: false,
showMy: true, showMy: true,
showUndone: true, showUndone: true,
showCompleted: false, showCompleted: false,

View File

@ -1,56 +1,3 @@
export default { export default {
/**
* 会话消息列表
* @param state
* @param data
*/
dialogMsgListSuccess(state, data) {
const dialog = data.dialog;
const list = data.data;
// 更新当前会话消息
if (state.dialogId == dialog.id) {
state.dialogDetail = dialog;
list.forEach((item) => {
let index = state.dialogMsgList.findIndex(({id}) => id == item.id);
if (index === -1) {
state.dialogMsgList.unshift(item);
} else {
state.dialogMsgList.splice(index, 1, item);
}
});
this.commit("dialogMsgListStorageCurrent");
}
// 页数数据
state.dialogMsgCurrentPage = data.current_page;
state.dialogMsgHasMorePages = data.current_page < data.last_page;
// 更新会话数据
this.dispatch("saveDialog", dialog);
},
/**
* 保存当前会话消息
* @param state
*/
dialogMsgListStorageCurrent(state) {
if (!state.method.isJson(state.cacheDialogMsg[state.dialogId])) {
return;
}
//
state.cacheDialogMsg[state.dialogId].data = state.dialogMsgList;
state.method.setStorage("cacheDialogMsg", state.cacheDialogMsg);
},
/**
* 将会话移动到首位
* @param state
* @param dialog_id
*/
dialogMoveToTop(state, dialog_id) {
const index = state.dialogList.findIndex(({id}) => id == dialog_id);
if (index > -1) {
const tmp = state.method.cloneJSON(state.dialogList[index]);
state.dialogList.splice(index, 1);
state.dialogList.unshift(tmp);
}
}
} }

View File

@ -226,11 +226,6 @@ const method = {
// 方法类 // 方法类
const state = { method }; const state = { method };
// ajax
state.ajaxLoadNum = 0;
state.ajaxWsReady = false;
state.ajaxWsListener = [];
// 数据缓存 // 数据缓存
state.cacheUserBasic = state.method.getStorageJson("cacheUserBasic"); state.cacheUserBasic = state.method.getStorageJson("cacheUserBasic");
state.cacheDialogMsg = state.method.getStorageJson("cacheDialogMsg"); state.cacheDialogMsg = state.method.getStorageJson("cacheDialogMsg");
@ -239,15 +234,12 @@ state.cacheColumns = state.method.getStorageArray("cacheColumns");
state.cacheTasks = state.method.getStorageArray("cacheTasks"); state.cacheTasks = state.method.getStorageArray("cacheTasks");
state.cacheTaskSubs = state.method.getStorageArray("cacheTaskSubs"); state.cacheTaskSubs = state.method.getStorageArray("cacheTaskSubs");
state.cacheTablePanel = state.method.getStorageArray("cacheTablePanel"); state.cacheTablePanel = state.method.getStorageArray("cacheTablePanel");
state.projectChatShow = state.method.getStorageBoolean("boolean:projectChatShow", false) state.showCompletedTask = state.method.getStorageBoolean("boolean:showCompletedTask")
state.projectCompleteShow = state.method.getStorageBoolean("boolean:projectCompleteShow", false)
// 会员信息 // Ajax
state.userInfo = state.method.getStorageJson("userInfo"); state.ajaxLoadNum = 0;
state.userId = state.userInfo.userid = state.method.runNum(state.userInfo.userid); state.ajaxWsReady = false;
state.userToken = state.userInfo.token; state.ajaxWsListener = [];
state.userIsAdmin = state.method.inArray("admin", state.userInfo.identity);
state.userOnline = {};
// Websocket // Websocket
state.ws = null; state.ws = null;
@ -258,30 +250,30 @@ state.wsListener = {};
state.wsReadTimeout = null; state.wsReadTimeout = null;
state.wsReadWaitList = []; state.wsReadWaitList = [];
// 会员信息
state.userInfo = state.method.getStorageJson("userInfo");
state.userId = state.userInfo.userid = state.method.runNum(state.userInfo.userid);
state.userToken = state.userInfo.token;
state.userIsAdmin = state.method.inArray("admin", state.userInfo.identity);
state.userOnline = {};
// 会话聊天
state.dialogs = [];
state.dialogMsgs = [];
state.dialogMsgPush = {};
// 项目任务 // 项目任务
state.projectId = 0;
state.projects = []; state.projects = [];
state.projectLoad = 0; state.projectLoad = 0;
state.projectStatistics = {}; state.projectStatistics = {};
state.columns = []; state.columns = [];
state.taskId = 0;
state.tasks = []; state.tasks = [];
state.taskSubs = []; state.taskSubs = [];
state.taskContents = []; state.taskContents = [];
state.taskFiles = []; state.taskFiles = [];
state.taskLogs = []; state.taskLogs = [];
state.projectId = 0;
state.taskId = 0;
// 会话聊天
state.dialogId = 0;
state.dialogList = [];
state.dialogDetail = {};
state.dialogMsgUnread = 0;
state.dialogMsgLoad = 0;
state.dialogMsgPush = {};
state.dialogMsgList = [];
state.dialogMsgCurrentPage = 1;
state.dialogMsgHasMorePages = false;
// 任务优先级 // 任务优先级
state.taskPriority = []; state.taskPriority = [];