feat: 新增消息类型筛选

This commit is contained in:
kuaifan 2022-06-30 19:54:48 +08:00
parent a368e00b2f
commit 49f8e23aae
6 changed files with 187 additions and 18 deletions

View File

@ -214,7 +214,7 @@ class DialogController extends AbstractController
* @apiName msg__lists * @apiName msg__lists
* *
* @apiParam {Number} dialog_id 对话ID * @apiParam {Number} dialog_id 对话ID
* @apiParam {String} [position_id] 定位消息ID填写时page无效 * @apiParam {Number} [position_id] 定位消息ID填写时page无效
* *
* @apiParam {Number} [page] 当前页,默认:1 * @apiParam {Number} [page] 当前页,默认:1
* @apiParam {Number} [pagesize] 每页显示数量,默认:50,最大:100 * @apiParam {Number} [pagesize] 每页显示数量,默认:50,最大:100
@ -284,6 +284,13 @@ class DialogController extends AbstractController
* @apiParam {Number} [prev_id] 此消息ID之前的数据 * @apiParam {Number} [prev_id] 此消息ID之前的数据
* @apiParam {Number} [next_id] 此消息ID之后的数据 * @apiParam {Number} [next_id] 此消息ID之后的数据
* - position_id、prev_id、next_id 只有一个有效优先循序为position_id > prev_id > next_id * - position_id、prev_id、next_id 只有一个有效优先循序为position_id > prev_id > next_id
* @apiParam {String} [mtype] 消息类型
* - tag: 标记
* - text: 文本
* - image: 图片
* - file: 文件
* - record: 录音
* - meeting: 会议
* *
* @apiParam {Number} [take] 获取条数,默认:50,最大:100 * @apiParam {Number} [take] 获取条数,默认:50,最大:100
* *
@ -301,6 +308,7 @@ class DialogController extends AbstractController
$position_id = intval(Request::input('position_id')); $position_id = intval(Request::input('position_id'));
$prev_id = intval(Request::input('prev_id')); $prev_id = intval(Request::input('prev_id'));
$next_id = intval(Request::input('next_id')); $next_id = intval(Request::input('next_id'));
$mtype = trim(Request::input('mtype'));
$take = Base::getPaginate(100, 50, 'take'); $take = Base::getPaginate(100, 50, 'take');
$data = []; $data = [];
// //
@ -317,6 +325,11 @@ class DialogController extends AbstractController
->on('read.msg_id', '=', 'web_socket_dialog_msgs.id'); ->on('read.msg_id', '=', 'web_socket_dialog_msgs.id');
})->where('web_socket_dialog_msgs.dialog_id', $dialog_id); })->where('web_socket_dialog_msgs.dialog_id', $dialog_id);
// //
if ($mtype === 'tag') {
$builder->where('tag', '>', 0);
} elseif (in_array($mtype, ['text', 'image', 'file', 'record', 'meeting'])) {
$builder->whereMtype($mtype);
}
if ($msg_id > 0) { if ($msg_id > 0) {
$builder->whereReplyId($msg_id); $builder->whereReplyId($msg_id);
$reDialog = false; $reDialog = false;

View File

@ -18,6 +18,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property string|null $dialog_type 对话类型 * @property string|null $dialog_type 对话类型
* @property int|null $userid 发送会员ID * @property int|null $userid 发送会员ID
* @property string|null $type 消息类型 * @property string|null $type 消息类型
* @property string|null $mtype 消息类型(用于搜索)
* @property array|mixed $msg 详细消息 * @property array|mixed $msg 详细消息
* @property array|mixed $emoji emoji回复 * @property array|mixed $emoji emoji回复
* @property string|null $key 搜索关键词 * @property string|null $key 搜索关键词
@ -44,6 +45,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereKey($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereKey($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereMsg($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereMsg($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereMtype($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereRead($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereRead($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereReplyId($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereReplyId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereReplyNum($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereReplyNum($value)
@ -519,11 +521,20 @@ class WebSocketDialogMsg extends AbstractModel
*/ */
public static function sendMsg($dialog_id, $reply_id, $type, $msg, $sender = 0) public static function sendMsg($dialog_id, $reply_id, $type, $msg, $sender = 0)
{ {
$mtype = $type;
if ($type === 'text' && str_contains($msg['text'], '<img ')) {
$mtype = 'image';
}
if ($type === 'file' && in_array($msg['ext'], ['jpg', 'jpeg', 'png', 'gif'])) {
$mtype = 'image';
}
//
$dialogMsg = self::createInstance([ $dialogMsg = self::createInstance([
'dialog_id' => $dialog_id, 'dialog_id' => $dialog_id,
'reply_id' => $reply_id, 'reply_id' => $reply_id,
'userid' => $sender ?: User::userid(), 'userid' => $sender ?: User::userid(),
'type' => $type, 'type' => $type,
'mtype' => $mtype,
'msg' => $msg, 'msg' => $msg,
'read' => 0, 'read' => 0,
]); ]);

View File

@ -0,0 +1,56 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWebSocketDialogMsgsMtype extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$isAdd = false;
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) use (&$isAdd) {
if (!Schema::hasColumn('web_socket_dialog_msgs', 'mtype')) {
$isAdd = true;
$table->string('mtype', 20)->nullable()->default('')->after('type')->comment('消息类型(用于搜索)');
}
});
if ($isAdd) {
DB::table('web_socket_dialog_msgs')->update([
'mtype' => DB::raw('type')
]);
DB::table('web_socket_dialog_msgs')->where('type', 'text')->where('msg', 'LIKE', '%<img %')->update([
'mtype' => 'image'
]);
DB::table('web_socket_dialog_msgs')->where('type', 'file')->where('msg', 'LIKE', '%.jpg"%')->update([
'mtype' => 'image'
]);
DB::table('web_socket_dialog_msgs')->where('type', 'file')->where('msg', 'LIKE', '%.jpeg"%')->update([
'mtype' => 'image'
]);
DB::table('web_socket_dialog_msgs')->where('type', 'file')->where('msg', 'LIKE', '%.png"%')->update([
'mtype' => 'image'
]);
DB::table('web_socket_dialog_msgs')->where('type', 'file')->where('msg', 'LIKE', '%.gif"%')->update([
'mtype' => 'image'
]);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) {
$table->dropColumn("mtype");
});
}
}

View File

@ -64,6 +64,16 @@
<i class="taskfont dialog-create" @click="openCreateGroup">&#xe646;</i> <i class="taskfont dialog-create" @click="openCreateGroup">&#xe646;</i>
</ETooltip> </ETooltip>
</div> </div>
<ul class="nav-tags">
<li
v-for="item in msgTags"
:key="item.type"
:class="{active: msgType === item.type}"
@click="msgType=item.type">
<i class="taskfont" v-html="item.icon"></i>
<span>{{$L(item.label)}}</span>
</li>
</ul>
</slot> </slot>
</div> </div>
@ -78,6 +88,7 @@
:item-class-add="itemClassAdd" :item-class-add="itemClassAdd"
:extra-props="{dialogData, operateVisible, operateItem, hidePercentage: isMyDialog, hideReply: msgId > 0}" :extra-props="{dialogData, operateVisible, operateItem, hidePercentage: isMyDialog, hideReply: msgId > 0}"
:estimate-size="78" :estimate-size="78"
:top-threshold="120"
:keeps="70" :keeps="70"
@scroll="onScroll" @scroll="onScroll"
@range="onRange" @range="onRange"
@ -330,6 +341,14 @@ export default {
msgText: '', msgText: '',
msgNew: 0, msgNew: 0,
msgType: '',
msgTags: [
{icon: '&#xe6eb;', type: '', label: '消息'},
{icon: '&#xe61e;', type: 'tag', label: '标注'},
{icon: '&#xe7bc;', type: 'image', label: '图片'},
{icon: '&#xe7c0;', type: 'file', label: '文件'},
],
allMsgs: [], allMsgs: [],
tempMsgs: [], tempMsgs: [],
@ -408,12 +427,7 @@ export default {
if (!this.isReady) { if (!this.isReady) {
return []; return [];
} }
return this.dialogMsgs.filter(item => { return this.dialogMsgs.filter(item => this.msgFilter(item)).sort((a, b) => {
if (this.msgId) {
return item.reply_id == this.msgId;
}
return item.dialog_id == this.dialogId;
}).sort((a, b) => {
return a.id - b.id; return a.id - b.id;
}); });
}, },
@ -422,12 +436,7 @@ export default {
if (!this.isReady) { if (!this.isReady) {
return []; return [];
} }
return this.tempMsgs.filter(item => { return this.tempMsgs.filter(item => this.msgFilter(item));
if (this.msgId) {
return item.reply_id == this.msgId;
}
return item.dialog_id == this.dialogId;
});
}, },
allMsgList() { allMsgList() {
@ -442,7 +451,7 @@ export default {
}, },
loadMsg() { loadMsg() {
return this.isLoad(`msg::${this.dialogId}-${this.msgId}`) return this.isLoad(`msg::${this.dialogId}-${this.msgId}-${this.msgType}`)
}, },
prevId() { prevId() {
@ -534,6 +543,7 @@ export default {
this.allMsgs = this.allMsgList; this.allMsgs = this.allMsgList;
requestAnimationFrame(this.onToBottom); requestAnimationFrame(this.onToBottom);
} }
this.msgType = '';
this.$store.dispatch("getDialogMsgs", { this.$store.dispatch("getDialogMsgs", {
dialog_id, dialog_id,
msg_id: this.msgId msg_id: this.msgId
@ -555,6 +565,15 @@ export default {
immediate: true immediate: true
}, },
msgType(type) {
if (!type) return
this.$store.dispatch("getDialogMsgs", {
dialog_id: this.dialogId,
msg_id: this.msgId,
msg_type: this.msgType,
}).catch(_ => {});
},
dialogSearchMsgId() { dialogSearchMsgId() {
this.onSearchMsgId(); this.onSearchMsgId();
}, },
@ -582,6 +601,7 @@ export default {
this.$store.dispatch("getDialogMsgs", { this.$store.dispatch("getDialogMsgs", {
dialog_id: this.dialogId, dialog_id: this.dialogId,
msg_id: this.msgId, msg_id: this.msgId,
msg_type: this.msgType,
}).catch(_ => {}); }).catch(_ => {});
}, },
@ -644,6 +664,7 @@ export default {
} }
msgText = msgText.replace(/<\/span> <\/p>$/, "</span></p>") msgText = msgText.replace(/<\/span> <\/p>$/, "</span></p>")
// //
this.msgType = '';
this.onToBottom(); this.onToBottom();
this.onActive(); this.onActive();
// //
@ -687,6 +708,7 @@ export default {
* @param msg {base64, duration} * @param msg {base64, duration}
*/ */
sendRecord(msg) { sendRecord(msg) {
this.msgType = '';
this.onToBottom(); this.onToBottom();
this.onActive(); this.onActive();
// //
@ -724,6 +746,7 @@ export default {
sendFileMsg(row) { sendFileMsg(row) {
const files = $A.isArray(row) ? row : [row]; const files = $A.isArray(row) ? row : [row];
if (files.length > 0) { if (files.length > 0) {
this.msgType = '';
this.pasteFile = []; this.pasteFile = [];
this.pasteItem = []; this.pasteItem = [];
files.some(file => { files.some(file => {
@ -751,6 +774,24 @@ export default {
} }
}, },
msgFilter(item) {
if (this.msgType) {
if (this.msgType === 'tag') {
if (!item.tag) {
return false
}
} else if (this.msgType !== item.mtype) {
return false
}
}
if (this.msgId) {
if (item.reply_id != this.msgId) {
return false
}
}
return item.dialog_id == this.dialogId;
},
onSearchMsgId() { onSearchMsgId() {
if (this.dialogSearchMsgId > 0 && this.openId === this.dialogId) { if (this.dialogSearchMsgId > 0 && this.openId === this.dialogId) {
this.onPositionId(this.dialogSearchMsgId) this.onPositionId(this.dialogSearchMsgId)
@ -772,6 +813,7 @@ export default {
delay: 600 delay: 600
}) })
} }
this.msgType = '';
this.preventToBottom = true; this.preventToBottom = true;
this.$store.dispatch("getDialogMsgs", { this.$store.dispatch("getDialogMsgs", {
dialog_id: this.dialogId, dialog_id: this.dialogId,
@ -1008,6 +1050,7 @@ export default {
this.$store.dispatch('getDialogMsgs', { this.$store.dispatch('getDialogMsgs', {
dialog_id: this.dialogId, dialog_id: this.dialogId,
msg_id: this.msgId, msg_id: this.msgId,
msg_type: this.msgType,
prev_id: this.prevId prev_id: this.prevId
}).then(({data}) => { }).then(({data}) => {
const ids = data.list.map(item => item.id) const ids = data.list.map(item => item.id)
@ -1109,6 +1152,7 @@ export default {
this.$store.dispatch("getDialogMsgs", { this.$store.dispatch("getDialogMsgs", {
dialog_id: this.dialogId, dialog_id: this.dialogId,
msg_id: this.msgId, msg_id: this.msgId,
msg_type: this.msgType,
[key]: rangeValue, [key]: rangeValue,
}).finally(_ => { }).finally(_ => {
this.preventMoreLoad = false this.preventMoreLoad = false

View File

@ -2170,7 +2170,7 @@ export default {
* @param state * @param state
* @param dispatch * @param dispatch
* @param getters * @param getters
* @param data {dialog_id, msg_id, ?position_id, ?prev_id, ?next_id} * @param data {dialog_id, msg_id, ?msg_type, ?position_id, ?prev_id, ?next_id}
* @returns {Promise<unknown>} * @returns {Promise<unknown>}
*/ */
getDialogMsgs({state, dispatch, getters}, data) { getDialogMsgs({state, dispatch, getters}, data) {
@ -2181,7 +2181,7 @@ export default {
return; return;
} }
// //
const loadKey = `msg::${data.dialog_id}-${data.msg_id}` const loadKey = `msg::${data.dialog_id}-${data.msg_id}-${data.msg_type || ''}`
if (getters.isLoad(loadKey)) { if (getters.isLoad(loadKey)) {
reject({msg: 'Loading'}); reject({msg: 'Loading'});
return return

View File

@ -207,12 +207,54 @@
display: none; display: none;
} }
} }
.nav-tags {
position: absolute;
top: 78px;
left: 0;
width: 100%;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
> li {
list-style: none;
display: flex;
align-items: center;
margin: 0 8px;
padding: 3px 8px;
background-color: #c0c4cc;
color: #fff;
border-radius: 6px;
font-size: 12px;
cursor: pointer;
box-shadow: 0 1px 6px rgba(255, 255, 255, 0.2);
.taskfont {
font-size: 13px;
padding-right: 6px;
}
> span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&.active {
background-color: $primary-color;
}
}
}
} }
.dialog-scroller { .dialog-scroller {
flex: 1; flex: 1;
position: relative; position: relative;
padding: 16px 32px 0; padding: 48px 32px 0;
.dialog-shake { .dialog-shake {
animation: ani-dialog-shake 600ms ease-in-out; animation: ani-dialog-shake 600ms ease-in-out;
@ -1232,6 +1274,9 @@
} }
} }
} }
.nav-tags {
top: 60px;
}
} }
.dialog-scroller { .dialog-scroller {
padding-right: 14px; padding-right: 14px;