完成优化聊天
This commit is contained in:
parent
2f9cd34ad2
commit
bbb73544ea
@ -107,16 +107,17 @@ class DialogController extends AbstractController
|
|||||||
//
|
//
|
||||||
$list = WebSocketDialogMsg::whereDialogId($dialog_id)->orderByDesc('id')->paginate(Base::getPaginate(100, 50));
|
$list = WebSocketDialogMsg::whereDialogId($dialog_id)->orderByDesc('id')->paginate(Base::getPaginate(100, 50));
|
||||||
$list->transform(function (WebSocketDialogMsg $item) use ($user) {
|
$list->transform(function (WebSocketDialogMsg $item) use ($user) {
|
||||||
$item->r = $item->userid === $user->userid ? null : WebSocketDialogMsgRead::whereMsgId($item->id)->whereUserid($user->userid)->first();
|
$item->is_read = $item->userid === $user->userid || WebSocketDialogMsgRead::whereMsgId($item->id)->whereUserid($user->userid)->value('read_at');
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
//
|
//
|
||||||
$data = $list->toArray();
|
$data = $list->toArray();
|
||||||
$data['dialog'] = WebSocketDialog::formatData($dialog, $user->userid);
|
if ($list->currentPage() === 1) {
|
||||||
//
|
$data['dialog'] = WebSocketDialog::formatData($dialog, $user->userid);
|
||||||
$user->dialog_id = $dialog->id;
|
//
|
||||||
$user->save();
|
$user->dialog_id = $dialog->id;
|
||||||
//
|
$user->save();
|
||||||
|
}
|
||||||
return Base::retSuccess('success', $data);
|
return Base::retSuccess('success', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {mapState} from "vuex";
|
|
||||||
import WCircle from "../../../components/WCircle";
|
import WCircle from "../../../components/WCircle";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -78,9 +77,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
activated() {
|
||||||
...mapState(['userId']),
|
this.msgRead()
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
readList() {
|
readList() {
|
||||||
return this.read_list.filter(({read_at}) => read_at)
|
return this.read_list.filter(({read_at}) => read_at)
|
||||||
},
|
},
|
||||||
@ -92,14 +93,29 @@ export default {
|
|||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
msgData: {
|
msgData: {
|
||||||
handler(data) {
|
handler() {
|
||||||
this.$store.dispatch("dialogMsgRead", data);
|
this.msgRead();
|
||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
msgRead() {
|
||||||
|
if (this.msgData._r === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.msgData._r = true;
|
||||||
|
//
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (!this.$el.offsetParent) {
|
||||||
|
this.msgData._r = false;
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$store.dispatch("dialogMsgRead", this.msgData);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
popperShow() {
|
popperShow() {
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
url: 'dialog/msg/readlist',
|
url: 'dialog/msg/readlist',
|
||||||
|
@ -356,7 +356,7 @@ export default {
|
|||||||
|
|
||||||
loadNextPage() {
|
loadNextPage() {
|
||||||
let topId = this.dialogMsgList[0].id;
|
let topId = this.dialogMsgList[0].id;
|
||||||
this.$store.dispatch('getDialogMsgNextPage').then(() => {
|
this.$store.dispatch('getDialogMsgNextPage', this.dialogId).then(() => {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.topId = topId;
|
this.topId = topId;
|
||||||
let dom = document.getElementById("view_" + topId);
|
let dom = document.getElementById("view_" + topId);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="project-dialog">
|
<div class="project-dialog">
|
||||||
<DialogWrapper :dialog-id="projectData.dialog_id" class="project-dialog-wrapper">
|
<DialogWrapper v-if="dialogs.length > 0" :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} from "vuex";
|
import {mapGetters, mapState} from "vuex";
|
||||||
import DialogWrapper from "./DialogWrapper";
|
import DialogWrapper from "./DialogWrapper";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -35,6 +35,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState(['dialogs']),
|
||||||
...mapGetters(['projectData'])
|
...mapGetters(['projectData'])
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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" :dialog-id="taskDetail.dialog_id">
|
<DialogWrapper ref="dialog" v-if="dialogs.length" :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">
|
||||||
@ -466,7 +466,17 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['userId', 'projects', 'columns', 'taskId', 'taskSubs', 'taskContents', 'taskFiles', 'taskPriority']),
|
...mapState([
|
||||||
|
'userId',
|
||||||
|
'projects',
|
||||||
|
'columns',
|
||||||
|
'taskId',
|
||||||
|
'taskSubs',
|
||||||
|
'taskContents',
|
||||||
|
'taskFiles',
|
||||||
|
'taskPriority',
|
||||||
|
'dialogs'
|
||||||
|
]),
|
||||||
|
|
||||||
projectName() {
|
projectName() {
|
||||||
if (!this.taskDetail.project_id) {
|
if (!this.taskDetail.project_id) {
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="messenger-msg">
|
<div class="messenger-msg">
|
||||||
<DialogWrapper v-if="dialogId > 0" :dialogId="dialogId" @on-active="scrollIntoActive"/>
|
<DialogWrapper v-if="dialogs.length > 0 && 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>
|
||||||
@ -96,7 +96,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
activated() {
|
activated() {
|
||||||
this.$store.dispatch("getDialogs");
|
|
||||||
this.openDialogStorage();
|
this.openDialogStorage();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
29
resources/assets/js/store/actions.js
vendored
29
resources/assets/js/store/actions.js
vendored
@ -1080,7 +1080,7 @@ export default {
|
|||||||
* @param dialog_id
|
* @param dialog_id
|
||||||
*/
|
*/
|
||||||
getDialogMsgs({state, dispatch}, dialog_id) {
|
getDialogMsgs({state, dispatch}, dialog_id) {
|
||||||
const dialog = state.dialogs.filter(({id}) => id == dialog_id);
|
const dialog = state.dialogs.find(({id}) => id == dialog_id);
|
||||||
if (!dialog) {
|
if (!dialog) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1099,11 +1099,14 @@ export default {
|
|||||||
},
|
},
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
dialog.loading = false;
|
dialog.loading = false;
|
||||||
|
dialog.currentPage = result.data.current_page;
|
||||||
|
dialog.hasMorePages = !!result.data.next_page_url;
|
||||||
const ids = result.data.data.map(({id}) => id)
|
const ids = result.data.data.map(({id}) => id)
|
||||||
if (ids.length == 0) {
|
if (ids.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.dialogMsgs = state.dialogMsgs.filter((item) => item.dialog_id != dialog_id || ids.includes(item.id));
|
state.dialogMsgs = state.dialogMsgs.filter((item) => item.dialog_id != dialog_id || ids.includes(item.id));
|
||||||
|
dispatch("saveDialog", result.data.dialog);
|
||||||
dispatch("saveDialogMsg", result.data.data);
|
dispatch("saveDialogMsg", result.data.data);
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@ -1119,7 +1122,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
getDialogMsgNextPage({state, dispatch}, dialog_id) {
|
getDialogMsgNextPage({state, dispatch}, dialog_id) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
const dialog = state.dialogs.filter(({id}) => id == dialog_id);
|
const dialog = state.dialogs.find(({id}) => id == dialog_id);
|
||||||
if (!dialog) {
|
if (!dialog) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1140,7 +1143,9 @@ export default {
|
|||||||
},
|
},
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
dialog.loading = false;
|
dialog.loading = false;
|
||||||
dispatch("saveDialogMsg", result.data);
|
dialog.currentPage = result.data.current_page;
|
||||||
|
dialog.hasMorePages = !!result.data.next_page_url;
|
||||||
|
dispatch("saveDialogMsg", result.data.data);
|
||||||
resolve(result)
|
resolve(result)
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@ -1154,23 +1159,19 @@ export default {
|
|||||||
* 发送已阅消息
|
* 发送已阅消息
|
||||||
* @param state
|
* @param state
|
||||||
* @param dispatch
|
* @param dispatch
|
||||||
* @param msgData
|
* @param data
|
||||||
*/
|
*/
|
||||||
dialogMsgRead({state, dispatch}, msgData) {
|
dialogMsgRead({state, dispatch}, data) {
|
||||||
if (msgData.userid == state.userId) return;
|
if (data.userid == state.userId) return;
|
||||||
if (!state.method.isJson(msgData.r)) msgData.r = {};
|
if (data.is_read === true) return;
|
||||||
|
data.is_read = true;
|
||||||
//
|
//
|
||||||
const {id, dialog_id, r} = msgData;
|
let dialog = state.dialogs.find(({id}) => id == data.dialog_id);
|
||||||
if (r.read_at) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
r.read_at = state.method.formatDate('Y-m-d H:i:s');
|
|
||||||
let dialog = state.dialogs.find(({id}) => id == dialog_id);
|
|
||||||
if (dialog && dialog.unread > 0) {
|
if (dialog && dialog.unread > 0) {
|
||||||
dialog.unread--
|
dialog.unread--
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
state.wsReadWaitList.push(id);
|
state.wsReadWaitList.push(data.id);
|
||||||
clearTimeout(state.wsReadTimeout);
|
clearTimeout(state.wsReadTimeout);
|
||||||
state.wsReadTimeout = setTimeout(() => {
|
state.wsReadTimeout = setTimeout(() => {
|
||||||
dispatch("websocketSend", {
|
dispatch("websocketSend", {
|
||||||
|
3
resources/assets/js/store/getters.js
vendored
3
resources/assets/js/store/getters.js
vendored
@ -30,7 +30,8 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
columns: []
|
columns: [],
|
||||||
|
project_user: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
7
resources/assets/js/store/state.js
vendored
7
resources/assets/js/store/state.js
vendored
@ -131,8 +131,6 @@ const method = {
|
|||||||
let keyName = '__state__';
|
let keyName = '__state__';
|
||||||
if (key.substring(0, 5) === 'cache') {
|
if (key.substring(0, 5) === 'cache') {
|
||||||
keyName = '__state:' + key + '__';
|
keyName = '__state:' + key + '__';
|
||||||
} else if (key.substring(0, 7) === 'boolean') {
|
|
||||||
keyName = '__state:Boolean__';
|
|
||||||
}
|
}
|
||||||
if (typeof value === 'undefined') {
|
if (typeof value === 'undefined') {
|
||||||
return this.loadFromlLocal(key, '', keyName);
|
return this.loadFromlLocal(key, '', keyName);
|
||||||
@ -228,13 +226,14 @@ const state = { method };
|
|||||||
|
|
||||||
// 数据缓存
|
// 数据缓存
|
||||||
state.cacheUserBasic = state.method.getStorageJson("cacheUserBasic");
|
state.cacheUserBasic = state.method.getStorageJson("cacheUserBasic");
|
||||||
state.cacheDialogMsg = state.method.getStorageJson("cacheDialogMsg");
|
state.cacheDialogs = state.method.getStorageArray("cacheDialogs");
|
||||||
|
state.cacheDialogMsgs = state.method.getStorageArray("cacheDialogMsgs");
|
||||||
state.cacheProjects = state.method.getStorageArray("cacheProjects");
|
state.cacheProjects = state.method.getStorageArray("cacheProjects");
|
||||||
state.cacheColumns = state.method.getStorageArray("cacheColumns");
|
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.showCompletedTask = state.method.getStorageBoolean("boolean:showCompletedTask")
|
state.showCompletedTask = state.method.getStorageBoolean("showCompletedTask")
|
||||||
|
|
||||||
// Ajax
|
// Ajax
|
||||||
state.ajaxLoadNum = 0;
|
state.ajaxLoadNum = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user