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
*/
public function basic()
public function one()
{
$user = User::auth();
//

View File

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

View File

@ -1,6 +1,6 @@
<template>
<div class="project-dialog">
<DialogWrapper class="project-dialog-wrapper">
<DialogWrapper :dialog-id="projectData.dialog_id" class="project-dialog-wrapper">
<div slot="head">
<div class="dialog-user">
<div class="member-head">
@ -22,7 +22,7 @@
</template>
<script>
import {mapGetters, mapState} from "vuex";
import {mapGetters} from "vuex";
import DialogWrapper from "./DialogWrapper";
export default {
@ -35,29 +35,7 @@ export default {
},
computed: {
...mapState(['projectChatShow']),
...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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,56 +1,3 @@
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 };
// ajax
state.ajaxLoadNum = 0;
state.ajaxWsReady = false;
state.ajaxWsListener = [];
// 数据缓存
state.cacheUserBasic = state.method.getStorageJson("cacheUserBasic");
state.cacheDialogMsg = state.method.getStorageJson("cacheDialogMsg");
@ -239,15 +234,12 @@ state.cacheColumns = state.method.getStorageArray("cacheColumns");
state.cacheTasks = state.method.getStorageArray("cacheTasks");
state.cacheTaskSubs = state.method.getStorageArray("cacheTaskSubs");
state.cacheTablePanel = state.method.getStorageArray("cacheTablePanel");
state.projectChatShow = state.method.getStorageBoolean("boolean:projectChatShow", false)
state.projectCompleteShow = state.method.getStorageBoolean("boolean:projectCompleteShow", false)
state.showCompletedTask = state.method.getStorageBoolean("boolean:showCompletedTask")
// 会员信息
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 = {};
// Ajax
state.ajaxLoadNum = 0;
state.ajaxWsReady = false;
state.ajaxWsListener = [];
// Websocket
state.ws = null;
@ -258,30 +250,30 @@ state.wsListener = {};
state.wsReadTimeout = null;
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.projectLoad = 0;
state.projectStatistics = {};
state.columns = [];
state.taskId = 0;
state.tasks = [];
state.taskSubs = [];
state.taskContents = [];
state.taskFiles = [];
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 = [];