feat: 【消息】列表增加点击右键置顶该聊天功能
This commit is contained in:
parent
ab4fbf0437
commit
04c59041e0
@ -8,6 +8,7 @@ use App\Models\User;
|
||||
use App\Models\WebSocketDialog;
|
||||
use App\Models\WebSocketDialogMsg;
|
||||
use App\Models\WebSocketDialogMsgRead;
|
||||
use App\Models\WebSocketDialogUser;
|
||||
use App\Module\Base;
|
||||
use Carbon\Carbon;
|
||||
use Request;
|
||||
@ -39,9 +40,10 @@ class DialogController extends AbstractController
|
||||
{
|
||||
$user = User::auth();
|
||||
//
|
||||
$list = WebSocketDialog::select(['web_socket_dialogs.*'])
|
||||
$list = WebSocketDialog::select(['web_socket_dialogs.*','u.top'])
|
||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||
->where('u.userid', $user->userid)
|
||||
->orderByDesc('u.top')
|
||||
->orderByDesc('web_socket_dialogs.last_at')
|
||||
->paginate(Base::getPaginate(200, 100));
|
||||
$list->transform(function (WebSocketDialog $item) use ($user) {
|
||||
@ -475,4 +477,36 @@ class DialogController extends AbstractController
|
||||
$msg->deleteMsg();
|
||||
return Base::retSuccess("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/dialog/top 12. 会话置顶
|
||||
*
|
||||
* @apiDescription 消息撤回限制24小时内,需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup dialog
|
||||
* @apiName top
|
||||
*
|
||||
* @apiParam {Number} dialog_id 会话ID
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function top()
|
||||
{
|
||||
$user = User::auth();
|
||||
$dialogId = intval(Request::input('dialog_id'));
|
||||
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
|
||||
if (!$dialogUser) {
|
||||
return Base::retError("会话不存在");
|
||||
}
|
||||
WebSocketDialogUser::whereUserid($user->userid)
|
||||
->update([
|
||||
'top' => 0
|
||||
]);
|
||||
$dialogUser->top = 1;
|
||||
$dialogUser->save();
|
||||
return Base::retSuccess("success", $dialogId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ namespace App\Models;
|
||||
* @property int $id
|
||||
* @property int|null $dialog_id 对话ID
|
||||
* @property int|null $userid 会员ID
|
||||
* @property int|null $top 是否置顶:0否,1是
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery()
|
||||
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class WebSocketDialogUsersAddTop extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('web_socket_dialog_users', 'top')) {
|
||||
$table->tinyInteger('top')->nullable()->default(0)->after('userid')->comment('是否置顶:0否,1是');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
|
||||
$table->dropColumn("top");
|
||||
});
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "diagrams.net",
|
||||
"name": "",
|
||||
"short_name": "Diagrams",
|
||||
"description": "diagrams.net is a completely free diagram editor",
|
||||
"icons": [
|
||||
|
@ -24,13 +24,14 @@
|
||||
class="messenger-list overlay-y"
|
||||
@on-scroll="listScroll"
|
||||
static>
|
||||
<ul v-if="tabActive==='dialog'" class="dialog">
|
||||
<ul v-if="tabActive==='dialog'" class="dialog" ref="dialogWrapper">
|
||||
<li
|
||||
v-for="(dialog, key) in dialogList"
|
||||
:ref="`dialog_${dialog.id}`"
|
||||
:key="key"
|
||||
:class="{active: dialog.id == dialogId}"
|
||||
@click="openDialog(dialog, true)">
|
||||
@click="openDialog(dialog, true)"
|
||||
@contextmenu.prevent.stop="handleRightClick($event, dialog)">
|
||||
<template v-if="dialog.type=='group'">
|
||||
<i v-if="dialog.group_type=='project'" class="taskfont icon-avatar project"></i>
|
||||
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task" :class="{completed:$A.dialogCompleted(dialog)}"></i>
|
||||
@ -65,6 +66,22 @@
|
||||
<li v-if="contactsLoad > 0" class="loading"><Loading/></li>
|
||||
<li v-else-if="!contactsHasMorePages" class="loaded">{{$L('共' + contactsList.length + '位联系人')}}</li>
|
||||
</ul>
|
||||
<div class="top-operate" :style="topOperateStyles">
|
||||
<Dropdown
|
||||
trigger="custom"
|
||||
:visible="topOperateVisible"
|
||||
transfer-class-name="page-file-dropdown-menu"
|
||||
@on-clickoutside="handleClickTopOperateOutside"
|
||||
@on-visible-change="handleVisibleTopOperate"
|
||||
transfer>
|
||||
<DropdownMenu slot="list">
|
||||
<template v-if="topOperateItem.id">
|
||||
<DropdownItem @click.native="handleTopClick">{{ $L('置顶该聊天') }}
|
||||
</DropdownItem>
|
||||
</template>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</ScrollerY>
|
||||
<div class="messenger-menu">
|
||||
<Icon @click="tabActive='dialog'" :class="{active:tabActive==='dialog'}" type="ios-chatbubbles" />
|
||||
@ -114,6 +131,15 @@ export default {
|
||||
contactsData: null,
|
||||
contactsCurrentPage: 1,
|
||||
contactsHasMorePages: false,
|
||||
topOperateStyles: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
position: 'absolute'
|
||||
},
|
||||
topOperateVisible: false,
|
||||
topOperateItem: {},
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
@ -128,6 +154,9 @@ export default {
|
||||
const {dialogActive, dialogKey} = this;
|
||||
if (dialogActive == '' && dialogKey == '') {
|
||||
return this.cacheDialogs.filter(dialog => this.filterDialog(dialog)).sort((a, b) => {
|
||||
if (a.top || b.top) {
|
||||
return b.top - a.top;
|
||||
}
|
||||
return $A.Date(b.last_at) - $A.Date(a.last_at);
|
||||
});
|
||||
}
|
||||
@ -407,6 +436,45 @@ export default {
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
handleRightClick(event, item) {
|
||||
this.topOperateItem = $A.isJson(item) ? item : {};
|
||||
if (this.topOperateVisible) {
|
||||
this.handleClickTopOperateOutside();
|
||||
}
|
||||
this.dialogId = this.topOperateItem.id;
|
||||
this.scrollIntoActive(true);
|
||||
this.$nextTick(() => {
|
||||
const dialogWrap = this.$refs.dialogWrapper;
|
||||
const dialogBounding = dialogWrap.getBoundingClientRect();
|
||||
this.topOperateStyles = {
|
||||
left: `${event.clientX - dialogBounding.left}px`,
|
||||
top: `${event.clientY - dialogBounding.top + 100}px`
|
||||
};
|
||||
this.topOperateVisible = true;
|
||||
})
|
||||
},
|
||||
handleClickTopOperateOutside() {
|
||||
this.topOperateVisible = false;
|
||||
},
|
||||
handleVisibleTopOperate(visible) {
|
||||
if (visible && this.topOperateItem.id) {
|
||||
this.$set(this.topOperateItem, '_highlight', true);
|
||||
}
|
||||
},
|
||||
handleTopClick() {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'dialog/top',
|
||||
data: {
|
||||
dialog_id: this.topOperateItem.id,
|
||||
},
|
||||
}).then(() => {
|
||||
this.$store.dispatch("getDialogs");
|
||||
this.$Modal.remove();
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg, 301);
|
||||
this.$Modal.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
34
resources/assets/sass/pages/page-messenger.scss
vendored
34
resources/assets/sass/pages/page-messenger.scss
vendored
@ -258,6 +258,23 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.top-operate {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
transition: opacity 0.2s;
|
||||
display: flex;
|
||||
.ivu-icon {
|
||||
font-size: 16px;
|
||||
color: #aaaaaa;
|
||||
transition: color 0.2s;
|
||||
padding: 2px 5px;
|
||||
&:hover {
|
||||
color: $primary-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.messenger-menu {
|
||||
display: flex;
|
||||
@ -372,6 +389,23 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.top-operate {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
transition: opacity 0.2s;
|
||||
display: flex;
|
||||
.ivu-icon {
|
||||
font-size: 16px;
|
||||
color: #aaaaaa;
|
||||
transition: color 0.2s;
|
||||
padding: 2px 5px;
|
||||
&:hover {
|
||||
color: $primary-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user