mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-28 04:40:37 +00:00
feat: 新增消息类型筛选
This commit is contained in:
parent
a368e00b2f
commit
49f8e23aae
@ -214,7 +214,7 @@ class DialogController extends AbstractController
|
||||
* @apiName msg__lists
|
||||
*
|
||||
* @apiParam {Number} dialog_id 对话ID
|
||||
* @apiParam {String} [position_id] 定位消息ID(填写时page无效)
|
||||
* @apiParam {Number} [position_id] 定位消息ID(填写时page无效)
|
||||
*
|
||||
* @apiParam {Number} [page] 当前页,默认:1
|
||||
* @apiParam {Number} [pagesize] 每页显示数量,默认:50,最大:100
|
||||
@ -284,6 +284,13 @@ class DialogController extends AbstractController
|
||||
* @apiParam {Number} [prev_id] 此消息ID之前的数据
|
||||
* @apiParam {Number} [next_id] 此消息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
|
||||
*
|
||||
@ -301,6 +308,7 @@ class DialogController extends AbstractController
|
||||
$position_id = intval(Request::input('position_id'));
|
||||
$prev_id = intval(Request::input('prev_id'));
|
||||
$next_id = intval(Request::input('next_id'));
|
||||
$mtype = trim(Request::input('mtype'));
|
||||
$take = Base::getPaginate(100, 50, 'take');
|
||||
$data = [];
|
||||
//
|
||||
@ -317,6 +325,11 @@ class DialogController extends AbstractController
|
||||
->on('read.msg_id', '=', 'web_socket_dialog_msgs.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) {
|
||||
$builder->whereReplyId($msg_id);
|
||||
$reDialog = false;
|
||||
|
||||
@ -18,6 +18,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @property string|null $dialog_type 对话类型
|
||||
* @property int|null $userid 发送会员ID
|
||||
* @property string|null $type 消息类型
|
||||
* @property string|null $mtype 消息类型(用于搜索)
|
||||
* @property array|mixed $msg 详细消息
|
||||
* @property array|mixed $emoji emoji回复
|
||||
* @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 whereKey($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 whereReplyId($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)
|
||||
{
|
||||
$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([
|
||||
'dialog_id' => $dialog_id,
|
||||
'reply_id' => $reply_id,
|
||||
'userid' => $sender ?: User::userid(),
|
||||
'type' => $type,
|
||||
'mtype' => $mtype,
|
||||
'msg' => $msg,
|
||||
'read' => 0,
|
||||
]);
|
||||
|
||||
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
<!--顶部导航-->
|
||||
<div class="dialog-nav" :style="navStyle">
|
||||
<slot name="head">
|
||||
<div class="nav-wrapper" :class="{completed:$A.dialogCompleted(dialogData)}">
|
||||
<div class="nav-wrapper" :class="{completed: $A.dialogCompleted(dialogData)}">
|
||||
<div class="dialog-back" @click="onBack">
|
||||
<i class="taskfont"></i>
|
||||
<div v-if="msgUnreadOnly" class="back-num">{{msgUnreadOnly}}</div>
|
||||
@ -64,6 +64,16 @@
|
||||
<i class="taskfont dialog-create" @click="openCreateGroup"></i>
|
||||
</ETooltip>
|
||||
</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>
|
||||
</div>
|
||||
|
||||
@ -78,6 +88,7 @@
|
||||
:item-class-add="itemClassAdd"
|
||||
:extra-props="{dialogData, operateVisible, operateItem, hidePercentage: isMyDialog, hideReply: msgId > 0}"
|
||||
:estimate-size="78"
|
||||
:top-threshold="120"
|
||||
:keeps="70"
|
||||
@scroll="onScroll"
|
||||
@range="onRange"
|
||||
@ -330,6 +341,14 @@ export default {
|
||||
msgText: '',
|
||||
msgNew: 0,
|
||||
|
||||
msgType: '',
|
||||
msgTags: [
|
||||
{icon: '', type: '', label: '消息'},
|
||||
{icon: '', type: 'tag', label: '标注'},
|
||||
{icon: '', type: 'image', label: '图片'},
|
||||
{icon: '', type: 'file', label: '文件'},
|
||||
],
|
||||
|
||||
allMsgs: [],
|
||||
tempMsgs: [],
|
||||
|
||||
@ -408,12 +427,7 @@ export default {
|
||||
if (!this.isReady) {
|
||||
return [];
|
||||
}
|
||||
return this.dialogMsgs.filter(item => {
|
||||
if (this.msgId) {
|
||||
return item.reply_id == this.msgId;
|
||||
}
|
||||
return item.dialog_id == this.dialogId;
|
||||
}).sort((a, b) => {
|
||||
return this.dialogMsgs.filter(item => this.msgFilter(item)).sort((a, b) => {
|
||||
return a.id - b.id;
|
||||
});
|
||||
},
|
||||
@ -422,12 +436,7 @@ export default {
|
||||
if (!this.isReady) {
|
||||
return [];
|
||||
}
|
||||
return this.tempMsgs.filter(item => {
|
||||
if (this.msgId) {
|
||||
return item.reply_id == this.msgId;
|
||||
}
|
||||
return item.dialog_id == this.dialogId;
|
||||
});
|
||||
return this.tempMsgs.filter(item => this.msgFilter(item));
|
||||
},
|
||||
|
||||
allMsgList() {
|
||||
@ -442,7 +451,7 @@ export default {
|
||||
},
|
||||
|
||||
loadMsg() {
|
||||
return this.isLoad(`msg::${this.dialogId}-${this.msgId}`)
|
||||
return this.isLoad(`msg::${this.dialogId}-${this.msgId}-${this.msgType}`)
|
||||
},
|
||||
|
||||
prevId() {
|
||||
@ -534,6 +543,7 @@ export default {
|
||||
this.allMsgs = this.allMsgList;
|
||||
requestAnimationFrame(this.onToBottom);
|
||||
}
|
||||
this.msgType = '';
|
||||
this.$store.dispatch("getDialogMsgs", {
|
||||
dialog_id,
|
||||
msg_id: this.msgId
|
||||
@ -555,6 +565,15 @@ export default {
|
||||
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() {
|
||||
this.onSearchMsgId();
|
||||
},
|
||||
@ -582,6 +601,7 @@ export default {
|
||||
this.$store.dispatch("getDialogMsgs", {
|
||||
dialog_id: this.dialogId,
|
||||
msg_id: this.msgId,
|
||||
msg_type: this.msgType,
|
||||
}).catch(_ => {});
|
||||
},
|
||||
|
||||
@ -644,6 +664,7 @@ export default {
|
||||
}
|
||||
msgText = msgText.replace(/<\/span> <\/p>$/, "</span></p>")
|
||||
//
|
||||
this.msgType = '';
|
||||
this.onToBottom();
|
||||
this.onActive();
|
||||
//
|
||||
@ -687,6 +708,7 @@ export default {
|
||||
* @param msg {base64, duration}
|
||||
*/
|
||||
sendRecord(msg) {
|
||||
this.msgType = '';
|
||||
this.onToBottom();
|
||||
this.onActive();
|
||||
//
|
||||
@ -724,6 +746,7 @@ export default {
|
||||
sendFileMsg(row) {
|
||||
const files = $A.isArray(row) ? row : [row];
|
||||
if (files.length > 0) {
|
||||
this.msgType = '';
|
||||
this.pasteFile = [];
|
||||
this.pasteItem = [];
|
||||
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() {
|
||||
if (this.dialogSearchMsgId > 0 && this.openId === this.dialogId) {
|
||||
this.onPositionId(this.dialogSearchMsgId)
|
||||
@ -772,6 +813,7 @@ export default {
|
||||
delay: 600
|
||||
})
|
||||
}
|
||||
this.msgType = '';
|
||||
this.preventToBottom = true;
|
||||
this.$store.dispatch("getDialogMsgs", {
|
||||
dialog_id: this.dialogId,
|
||||
@ -1008,6 +1050,7 @@ export default {
|
||||
this.$store.dispatch('getDialogMsgs', {
|
||||
dialog_id: this.dialogId,
|
||||
msg_id: this.msgId,
|
||||
msg_type: this.msgType,
|
||||
prev_id: this.prevId
|
||||
}).then(({data}) => {
|
||||
const ids = data.list.map(item => item.id)
|
||||
@ -1109,6 +1152,7 @@ export default {
|
||||
this.$store.dispatch("getDialogMsgs", {
|
||||
dialog_id: this.dialogId,
|
||||
msg_id: this.msgId,
|
||||
msg_type: this.msgType,
|
||||
[key]: rangeValue,
|
||||
}).finally(_ => {
|
||||
this.preventMoreLoad = false
|
||||
|
||||
4
resources/assets/js/store/actions.js
vendored
4
resources/assets/js/store/actions.js
vendored
@ -2170,7 +2170,7 @@ export default {
|
||||
* @param state
|
||||
* @param dispatch
|
||||
* @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>}
|
||||
*/
|
||||
getDialogMsgs({state, dispatch, getters}, data) {
|
||||
@ -2181,7 +2181,7 @@ export default {
|
||||
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)) {
|
||||
reject({msg: 'Loading'});
|
||||
return
|
||||
|
||||
@ -207,12 +207,54 @@
|
||||
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 {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
padding: 16px 32px 0;
|
||||
padding: 48px 32px 0;
|
||||
|
||||
.dialog-shake {
|
||||
animation: ani-dialog-shake 600ms ease-in-out;
|
||||
@ -1232,6 +1274,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.nav-tags {
|
||||
top: 60px;
|
||||
}
|
||||
}
|
||||
.dialog-scroller {
|
||||
padding-right: 14px;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user