mirror of
https://github.com/kuaifan/dootask.git
synced 2026-03-17 11:13:26 +00:00
feat: 消息会话支持免打扰
This commit is contained in:
parent
d89377a8fe
commit
e84961f20f
@ -48,7 +48,7 @@ class DialogController extends AbstractController
|
|||||||
{
|
{
|
||||||
$user = User::auth();
|
$user = User::auth();
|
||||||
//
|
//
|
||||||
$builder = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
|
$builder = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence'])
|
||||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||||
->where('u.userid', $user->userid);
|
->where('u.userid', $user->userid);
|
||||||
if (Request::exists('at_after')) {
|
if (Request::exists('at_after')) {
|
||||||
@ -88,7 +88,7 @@ class DialogController extends AbstractController
|
|||||||
return Base::retError('请输入搜索关键词');
|
return Base::retError('请输入搜索关键词');
|
||||||
}
|
}
|
||||||
// 搜索会话
|
// 搜索会话
|
||||||
$dialogs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
|
$dialogs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence'])
|
||||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||||
->where('web_socket_dialogs.name', 'LIKE', "%{$key}%")
|
->where('web_socket_dialogs.name', 'LIKE', "%{$key}%")
|
||||||
->where('u.userid', $user->userid)
|
->where('u.userid', $user->userid)
|
||||||
@ -121,7 +121,7 @@ class DialogController extends AbstractController
|
|||||||
}
|
}
|
||||||
// 搜索消息会话
|
// 搜索消息会话
|
||||||
if (count($list) < 20) {
|
if (count($list) < 20) {
|
||||||
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'm.id as search_msg_id'])
|
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'm.id as search_msg_id'])
|
||||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||||
->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id')
|
->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id')
|
||||||
->where('u.userid', $user->userid)
|
->where('u.userid', $user->userid)
|
||||||
@ -158,7 +158,7 @@ class DialogController extends AbstractController
|
|||||||
//
|
//
|
||||||
$dialog_id = intval(Request::input('dialog_id'));
|
$dialog_id = intval(Request::input('dialog_id'));
|
||||||
//
|
//
|
||||||
$item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
|
$item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence'])
|
||||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||||
->where('web_socket_dialogs.id', $dialog_id)
|
->where('web_socket_dialogs.id', $dialog_id)
|
||||||
->where('u.userid', $user->userid)
|
->where('u.userid', $user->userid)
|
||||||
@ -1060,6 +1060,69 @@ class DialogController extends AbstractController
|
|||||||
return Base::retSuccess("success", $data);
|
return Base::retSuccess("success", $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {get} api/dialog/msg/silence 20. 消息免打扰
|
||||||
|
*
|
||||||
|
* @apiDescription 需要token身份
|
||||||
|
* @apiVersion 1.0.0
|
||||||
|
* @apiGroup dialog
|
||||||
|
* @apiName msg__silence
|
||||||
|
*
|
||||||
|
* @apiParam {Number} dialog_id 会话ID
|
||||||
|
* @apiParam {String} type 类型
|
||||||
|
* - set
|
||||||
|
* - cancel
|
||||||
|
*
|
||||||
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
|
* @apiSuccess {Object} data 返回数据
|
||||||
|
*/
|
||||||
|
public function msg__silence()
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
$dialogId = intval(Request::input('dialog_id'));
|
||||||
|
$type = Request::input('type');
|
||||||
|
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
|
||||||
|
if (!$dialogUser) {
|
||||||
|
return Base::retError("会话不存在");
|
||||||
|
}
|
||||||
|
//
|
||||||
|
$dialogData = WebSocketDialog::find($dialogId);
|
||||||
|
if (empty($dialogData)) {
|
||||||
|
return Base::retError("会话不存在");
|
||||||
|
}
|
||||||
|
if ($dialogData->type === 'group' && $dialogData->group_type !== 'user') {
|
||||||
|
return Base::retError("此会话不允许设置免打扰");
|
||||||
|
}
|
||||||
|
//
|
||||||
|
switch ($type) {
|
||||||
|
case 'set':
|
||||||
|
$data['silence'] = 0;
|
||||||
|
WebSocketDialogMsgRead::whereUserid($user->userid)
|
||||||
|
->whereReadAt(null)
|
||||||
|
->whereDialogId($dialogId)
|
||||||
|
->chunkById(100, function ($list) {
|
||||||
|
WebSocketDialogMsgRead::onlyMarkRead($list);
|
||||||
|
});
|
||||||
|
$dialogUser->silence = 1;
|
||||||
|
$dialogUser->save();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'cancel':
|
||||||
|
$dialogUser->silence = 0;
|
||||||
|
$dialogUser->save();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Base::retError("参数错误");
|
||||||
|
}
|
||||||
|
$data = [
|
||||||
|
'id' => $dialogId,
|
||||||
|
'silence' => $dialogUser->silence,
|
||||||
|
];
|
||||||
|
return Base::retSuccess("success", $data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} api/dialog/msg/forward 21. 转发消息给
|
* @api {get} api/dialog/msg/forward 21. 转发消息给
|
||||||
*
|
*
|
||||||
|
|||||||
@ -5,6 +5,7 @@ namespace App\Models;
|
|||||||
use App\Exceptions\ApiException;
|
use App\Exceptions\ApiException;
|
||||||
use App\Module\Base;
|
use App\Module\Base;
|
||||||
use App\Tasks\PushTask;
|
use App\Tasks\PushTask;
|
||||||
|
use Cache;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@ -60,6 +61,13 @@ class WebSocketDialog extends AbstractModel
|
|||||||
*/
|
*/
|
||||||
public function formatData($userid, $hasData = false)
|
public function formatData($userid, $hasData = false)
|
||||||
{
|
{
|
||||||
|
$dialogUserFun = function ($key, $default = null) use ($userid) {
|
||||||
|
$data = Cache::remember("Dialog::formatData", now()->addSeconds(10), function () use ($userid) {
|
||||||
|
return WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->first()?->toArray();
|
||||||
|
});
|
||||||
|
return $data[$key] ?? $default;
|
||||||
|
};
|
||||||
|
//
|
||||||
if (isset($this->search_msg_id)) {
|
if (isset($this->search_msg_id)) {
|
||||||
// 最后消息 (搜索预览消息)
|
// 最后消息 (搜索预览消息)
|
||||||
$this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id);
|
$this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id);
|
||||||
@ -76,7 +84,9 @@ class WebSocketDialog extends AbstractModel
|
|||||||
$this->mention = $unreadBuilder->clone()->whereMention(1)->count();
|
$this->mention = $unreadBuilder->clone()->whereMention(1)->count();
|
||||||
$this->last_umid = intval($unreadBuilder->clone()->orderByDesc('msg_id')->value('msg_id'));
|
$this->last_umid = intval($unreadBuilder->clone()->orderByDesc('msg_id')->value('msg_id'));
|
||||||
}
|
}
|
||||||
$this->mark_unread = $this->mark_unread ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('mark_unread');
|
$this->mark_unread = $this->mark_unread ?? $dialogUserFun('mark_unread');
|
||||||
|
// 是否免打扰
|
||||||
|
$this->silence = $this->silence ?? $dialogUserFun('silence');
|
||||||
// 对话人数
|
// 对话人数
|
||||||
$builder = WebSocketDialogUser::whereDialogId($this->id);
|
$builder = WebSocketDialogUser::whereDialogId($this->id);
|
||||||
$this->people = $builder->count();
|
$this->people = $builder->count();
|
||||||
@ -86,7 +96,7 @@ class WebSocketDialog extends AbstractModel
|
|||||||
// 对方信息
|
// 对方信息
|
||||||
$this->dialog_user = null;
|
$this->dialog_user = null;
|
||||||
$this->group_info = null;
|
$this->group_info = null;
|
||||||
$this->top_at = $this->top_at ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('top_at');
|
$this->top_at = $this->top_at ?? $dialogUserFun('top_at');
|
||||||
$this->bot = 0;
|
$this->bot = 0;
|
||||||
switch ($this->type) {
|
switch ($this->type) {
|
||||||
case "user":
|
case "user":
|
||||||
|
|||||||
@ -541,8 +541,7 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
$text = preg_replace("/<img\s+class=\"browse\"[^>]*?>/", "[图片]", $text);
|
$text = preg_replace("/<img\s+class=\"browse\"[^>]*?>/", "[图片]", $text);
|
||||||
if (!$preserveHtml) {
|
if (!$preserveHtml) {
|
||||||
$text = strip_tags($text);
|
$text = strip_tags($text);
|
||||||
$text = str_replace(" ", " ", $text);
|
$text = str_replace([" ", "&", "<", ">"], [" ", "&", "<", ">"], $text);
|
||||||
$text = str_replace("&", "&", $text);
|
|
||||||
}
|
}
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ namespace App\Models;
|
|||||||
* @property int|null $userid 会员ID
|
* @property int|null $userid 会员ID
|
||||||
* @property string|null $top_at 置顶时间
|
* @property string|null $top_at 置顶时间
|
||||||
* @property int|null $mark_unread 是否标记为未读:0否,1是
|
* @property int|null $mark_unread 是否标记为未读:0否,1是
|
||||||
|
* @property int|null $silence 是否免打扰:0否,1是
|
||||||
* @property int|null $inviter 邀请人
|
* @property int|null $inviter 邀请人
|
||||||
* @property int|null $important 是否不可移出(项目、任务、部门人员)
|
* @property int|null $important 是否不可移出(项目、任务、部门人员)
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
@ -23,6 +24,7 @@ namespace App\Models;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereImportant($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereImportant($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereInviter($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereInviter($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereMarkUnread($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereMarkUnread($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereSilence($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereTopAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereTopAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUpdatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUserid($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUserid($value)
|
||||||
|
|||||||
@ -192,7 +192,7 @@ class BotReceiveMsgTask extends AbstractTask
|
|||||||
case '/dialog':
|
case '/dialog':
|
||||||
$data = $this->botManagerOne($array[1], $msg->userid);
|
$data = $this->botManagerOne($array[1], $msg->userid);
|
||||||
if ($data) {
|
if ($data) {
|
||||||
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread'])
|
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence'])
|
||||||
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
|
||||||
->where('web_socket_dialogs.name', 'LIKE', "%{$array[2]}%")
|
->where('web_socket_dialogs.name', 'LIKE', "%{$array[2]}%")
|
||||||
->where('u.userid', $data->userid)
|
->where('u.userid', $data->userid)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
protected $id;
|
protected $id;
|
||||||
protected $ignoreFd;
|
protected $ignoreFd;
|
||||||
protected $msgNotExistRetry = false; // 推送失败后重试
|
protected $msgNotExistRetry = false; // 推送失败后重试
|
||||||
protected $silence = false; // 静默推送(1:前端不通知、2:App不推送)
|
protected $silence = false; // 静默推送(前端不通知、App不推送,如果会话设置了免打扰则强制静默)
|
||||||
protected $endPush = [];
|
protected $endPush = [];
|
||||||
protected $endArray = [];
|
protected $endArray = [];
|
||||||
|
|
||||||
@ -85,6 +85,8 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
if (empty($dialog)) {
|
if (empty($dialog)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$silences = $dialog->dialogUser->pluck('silence', 'userid')->toArray();
|
||||||
|
$userids = array_keys($silences);
|
||||||
|
|
||||||
// 提及会员
|
// 提及会员
|
||||||
$mentions = [];
|
$mentions = [];
|
||||||
@ -96,7 +98,6 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 将会话以外的成员加入会话内
|
// 将会话以外的成员加入会话内
|
||||||
$userids = $dialog->dialogUser->pluck('userid')->toArray();
|
|
||||||
$diffids = array_values(array_diff($mentions, $userids));
|
$diffids = array_values(array_diff($mentions, $userids));
|
||||||
if ($diffids) {
|
if ($diffids) {
|
||||||
// 仅(群聊)且(是群主或没有群主)才可以@成员以外的人
|
// 仅(群聊)且(是群主或没有群主)才可以@成员以外的人
|
||||||
@ -111,7 +112,11 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
$array = [];
|
$array = [];
|
||||||
foreach ($userids AS $userid) {
|
foreach ($userids AS $userid) {
|
||||||
if ($userid == $msg->userid) {
|
if ($userid == $msg->userid) {
|
||||||
$array[$userid] = false;
|
$array[$userid] = [
|
||||||
|
'userid' => $userid,
|
||||||
|
'silence' => $this->silence || $silences[$userid],
|
||||||
|
'mention' => false,
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
$mention = array_intersect([0, $userid], $mentions) ? 1 : 0;
|
$mention = array_intersect([0, $userid], $mentions) ? 1 : 0;
|
||||||
WebSocketDialogMsgRead::createInstance([
|
WebSocketDialogMsgRead::createInstance([
|
||||||
@ -120,7 +125,11 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
'userid' => $userid,
|
'userid' => $userid,
|
||||||
'mention' => $mention,
|
'mention' => $mention,
|
||||||
])->saveOrIgnore();
|
])->saveOrIgnore();
|
||||||
$array[$userid] = $mention;
|
$array[$userid] = [
|
||||||
|
'userid' => $userid,
|
||||||
|
'silence' => $this->silence || $silences[$userid],
|
||||||
|
'mention' => $mention,
|
||||||
|
];
|
||||||
// 机器人收到消处理
|
// 机器人收到消处理
|
||||||
$botUser = User::whereUserid($userid)->whereBot(1)->first();
|
$botUser = User::whereUserid($userid)->whereBot(1)->first();
|
||||||
if ($botUser) {
|
if ($botUser) {
|
||||||
@ -132,40 +141,41 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
$msg->send = WebSocketDialogMsgRead::whereMsgId($msg->id)->count();
|
$msg->send = WebSocketDialogMsgRead::whereMsgId($msg->id)->count();
|
||||||
$msg->save();
|
$msg->save();
|
||||||
// 开始推送消息
|
// 开始推送消息
|
||||||
foreach ($array as $userid => $mention) {
|
$umengUserid = [];
|
||||||
|
foreach ($array as $item) {
|
||||||
$this->endPush[] = [
|
$this->endPush[] = [
|
||||||
'userid' => $userid,
|
'userid' => $item['userid'],
|
||||||
'ignoreFd' => $this->ignoreFd,
|
'ignoreFd' => $this->ignoreFd,
|
||||||
'msg' => [
|
'msg' => [
|
||||||
'type' => 'dialog',
|
'type' => 'dialog',
|
||||||
'mode' => 'add',
|
'mode' => 'add',
|
||||||
'silence' => $this->silence ? 1 : 0,
|
'silence' => $item['silence'] ? 1 : 0,
|
||||||
'data' => array_merge($msg->toArray(), [
|
'data' => array_merge($msg->toArray(), [
|
||||||
'mention' => $mention,
|
'mention' => $item['mention'],
|
||||||
]),
|
]),
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
if ($item['userid'] != $msg->userid && !$item['silence'] && !$this->silence) {
|
||||||
|
$umengUserid[] = $item['userid'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// umeng推送app
|
// umeng推送app
|
||||||
$setting = Base::setting('appPushSetting');
|
if ($umengUserid) {
|
||||||
$pushMsg = $setting['push'] === 'open' && $setting['push_msg'] !== 'close';
|
$setting = Base::setting('appPushSetting');
|
||||||
if (!$this->silence && $pushMsg) {
|
$pushMsg = $setting['push'] === 'open' && $setting['push_msg'] !== 'close';
|
||||||
$umengUserid = $array;
|
if ($pushMsg) {
|
||||||
if (isset($umengUserid[$msg->userid])) {
|
$umengTitle = User::userid2nickname($msg->userid);
|
||||||
unset($umengUserid[$msg->userid]);
|
if ($dialog->type == 'group') {
|
||||||
|
$umengTitle = "{$dialog->getGroupName()} ($umengTitle)";
|
||||||
|
}
|
||||||
|
$this->endArray[] = new PushUmengMsg($umengUserid, [
|
||||||
|
'title' => $umengTitle,
|
||||||
|
'body' => $msg->previewMsg(),
|
||||||
|
'description' => "MID:{$msg->id}",
|
||||||
|
'seconds' => 3600,
|
||||||
|
'badge' => 1,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
$umengUserid = array_keys($umengUserid);
|
|
||||||
$umengTitle = User::userid2nickname($msg->userid);
|
|
||||||
if ($dialog->type == 'group') {
|
|
||||||
$umengTitle = "{$dialog->getGroupName()} ($umengTitle)";
|
|
||||||
}
|
|
||||||
$this->endArray[] = new PushUmengMsg($umengUserid, [
|
|
||||||
'title' => $umengTitle,
|
|
||||||
'body' => $msg->previewMsg(),
|
|
||||||
'description' => "MID:{$msg->id}",
|
|
||||||
'seconds' => 3600,
|
|
||||||
'badge' => 1,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 推送目标②:正在打开这个任务会话的会员
|
// 推送目标②:正在打开这个任务会话的会员
|
||||||
@ -173,9 +183,9 @@ class WebSocketDialogMsgTask extends AbstractTask
|
|||||||
$list = User::whereTaskDialogId($dialog->id)->pluck('userid')->toArray();
|
$list = User::whereTaskDialogId($dialog->id)->pluck('userid')->toArray();
|
||||||
if ($list) {
|
if ($list) {
|
||||||
$array = [];
|
$array = [];
|
||||||
foreach ($list as $uid) {
|
foreach ($list as $item) {
|
||||||
if (!in_array($uid, $userids)) {
|
if (!in_array($item, $userids)) {
|
||||||
$array[] = $uid;
|
$array[] = $item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($array) {
|
if ($array) {
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddWebSocketDialogUsersAddSilence 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', 'silence')) {
|
||||||
|
$table->boolean('silence')->default(0)->nullable()->after('mark_unread')->comment('是否免打扰:0否,1是');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn("silence");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -97,7 +97,7 @@ export default {
|
|||||||
let num = 0; // 未读
|
let num = 0; // 未读
|
||||||
let mention = 0; // 提及
|
let mention = 0; // 提及
|
||||||
this.cacheDialogs.some(dialog => {
|
this.cacheDialogs.some(dialog => {
|
||||||
num += $A.getDialogUnread(dialog);
|
num += $A.getDialogUnread(dialog, false);
|
||||||
mention += $A.getDialogMention(dialog);
|
mention += $A.getDialogMention(dialog);
|
||||||
})
|
})
|
||||||
if (num > 99) {
|
if (num > 99) {
|
||||||
@ -129,7 +129,7 @@ export default {
|
|||||||
msgAllUnread() {
|
msgAllUnread() {
|
||||||
let num = 0;
|
let num = 0;
|
||||||
this.cacheDialogs.some(dialog => {
|
this.cacheDialogs.some(dialog => {
|
||||||
num += $A.getDialogUnread(dialog);
|
num += $A.getDialogUnread(dialog, false);
|
||||||
})
|
})
|
||||||
return num;
|
return num;
|
||||||
},
|
},
|
||||||
|
|||||||
11
resources/assets/js/functions/web.js
vendored
11
resources/assets/js/functions/web.js
vendored
@ -350,10 +350,12 @@
|
|||||||
/**
|
/**
|
||||||
* 返回对话未读数量
|
* 返回对话未读数量
|
||||||
* @param dialog
|
* @param dialog
|
||||||
|
* @param containSilence
|
||||||
* @returns {*|number}
|
* @returns {*|number}
|
||||||
*/
|
*/
|
||||||
getDialogUnread(dialog) {
|
getDialogUnread(dialog, containSilence) {
|
||||||
return dialog ? (dialog.unread || dialog.mark_unread || 0) : 0
|
const unread = containSilence || !dialog.silence ? dialog.unread : 0
|
||||||
|
return dialog ? (unread || dialog.mark_unread || 0) : 0
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -375,9 +377,12 @@
|
|||||||
text = text.replace(/<img\s+class="emoticon"[^>]*?alt="(\S+)"[^>]*?>/g, "[$1]")
|
text = text.replace(/<img\s+class="emoticon"[^>]*?alt="(\S+)"[^>]*?>/g, "[$1]")
|
||||||
text = text.replace(/<img\s+class="emoticon"[^>]*?>/g, `[${$A.L('动画表情')}]`)
|
text = text.replace(/<img\s+class="emoticon"[^>]*?>/g, `[${$A.L('动画表情')}]`)
|
||||||
text = text.replace(/<img\s+class="browse"[^>]*?>/g, `[${$A.L('图片')}]`)
|
text = text.replace(/<img\s+class="browse"[^>]*?>/g, `[${$A.L('图片')}]`)
|
||||||
|
text = text.replace(/<[^>]+>/g,"")
|
||||||
text = text.replace(/ /g," ")
|
text = text.replace(/ /g," ")
|
||||||
text = text.replace(/&/g,"&")
|
text = text.replace(/&/g,"&")
|
||||||
return text.replace(/<[^>]+>/g,"")
|
text = text.replace(/</g,"<")
|
||||||
|
text = text.replace(/>/g,">")
|
||||||
|
return text
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -448,7 +448,7 @@ export default {
|
|||||||
let num = 0; // 未读
|
let num = 0; // 未读
|
||||||
let mention = 0; // 提及
|
let mention = 0; // 提及
|
||||||
this.cacheDialogs.some(dialog => {
|
this.cacheDialogs.some(dialog => {
|
||||||
num += $A.getDialogUnread(dialog);
|
num += $A.getDialogUnread(dialog, false);
|
||||||
mention += $A.getDialogMention(dialog);
|
mention += $A.getDialogMention(dialog);
|
||||||
})
|
})
|
||||||
if (num > 99) {
|
if (num > 99) {
|
||||||
@ -480,7 +480,7 @@ export default {
|
|||||||
msgAllUnread() {
|
msgAllUnread() {
|
||||||
let num = 0;
|
let num = 0;
|
||||||
this.cacheDialogs.some(dialog => {
|
this.cacheDialogs.some(dialog => {
|
||||||
num += $A.getDialogUnread(dialog);
|
num += $A.getDialogUnread(dialog, false);
|
||||||
})
|
})
|
||||||
return num;
|
return num;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -703,7 +703,7 @@ export default {
|
|||||||
msgUnreadOnly() {
|
msgUnreadOnly() {
|
||||||
let num = 0;
|
let num = 0;
|
||||||
this.cacheDialogs.some(dialog => {
|
this.cacheDialogs.some(dialog => {
|
||||||
num += $A.getDialogUnread(dialog);
|
num += $A.getDialogUnread(dialog, false);
|
||||||
})
|
})
|
||||||
if (num <= 0) {
|
if (num <= 0) {
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@ -586,7 +586,7 @@ export default {
|
|||||||
msgUnread() {
|
msgUnread() {
|
||||||
const {cacheDialogs, projectData} = this;
|
const {cacheDialogs, projectData} = this;
|
||||||
const dialog = cacheDialogs.find(({id}) => id === projectData.dialog_id);
|
const dialog = cacheDialogs.find(({id}) => id === projectData.dialog_id);
|
||||||
return dialog ? $A.getDialogUnread(dialog) : 0;
|
return dialog ? $A.getDialogUnread(dialog, false) : 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
panelTask() {
|
panelTask() {
|
||||||
|
|||||||
@ -83,9 +83,10 @@
|
|||||||
<em v-if="formatMsgEmojiDesc(dialog.last_msg)">{{formatMsgEmojiDesc(dialog.last_msg)}}</em>
|
<em v-if="formatMsgEmojiDesc(dialog.last_msg)">{{formatMsgEmojiDesc(dialog.last_msg)}}</em>
|
||||||
<span>{{$A.getMsgSimpleDesc(dialog.last_msg)}}</span>
|
<span>{{$A.getMsgSimpleDesc(dialog.last_msg)}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="dialog.silence" class="taskfont last-silence"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Badge class="dialog-num" :count="$A.getDialogUnread(dialog)"/>
|
<Badge class="dialog-num" :type="dialog.silence ? 'normal' : 'error'" :count="$A.getDialogUnread(dialog, true)"/>
|
||||||
<div class="dialog-line"></div>
|
<div class="dialog-line"></div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -120,13 +121,13 @@
|
|||||||
<div :style="{userSelect:operateVisible ? 'none' : 'auto', height: operateStyles.height}"></div>
|
<div :style="{userSelect:operateVisible ? 'none' : 'auto', height: operateStyles.height}"></div>
|
||||||
<DropdownMenu slot="list">
|
<DropdownMenu slot="list">
|
||||||
<DropdownItem @click.native="handleTopClick">
|
<DropdownItem @click.native="handleTopClick">
|
||||||
{{ $L(operateItem.top_at ? '取消置顶' : '置顶该聊天') }}
|
{{ $L(operateItem.top_at ? '取消置顶' : '置顶') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem @click.native="handleReadClick('read')" v-if="$A.getDialogUnread(operateItem) > 0">
|
<DropdownItem @click.native="handleReadClick">
|
||||||
{{ $L('标记已读') }}
|
{{ $L($A.getDialogUnread(operateItem, true) > 0 ? '标记已读' : '标记未读') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem @click.native="handleReadClick('unread')" v-else>
|
<DropdownItem @click.native="handleSilenceClick" :disabled="silenceDisabled(operateItem)">
|
||||||
{{ $L('标记未读') }}
|
{{ $L(operateItem.silence ? '允许消息通知' : '消息免打扰') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
@ -351,7 +352,7 @@ export default {
|
|||||||
return function (type) {
|
return function (type) {
|
||||||
let num = 0;
|
let num = 0;
|
||||||
this.cacheDialogs.some((dialog) => {
|
this.cacheDialogs.some((dialog) => {
|
||||||
let unread = $A.getDialogUnread(dialog);
|
let unread = $A.getDialogUnread(dialog, false);
|
||||||
if (unread) {
|
if (unread) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'project':
|
case 'project':
|
||||||
@ -480,7 +481,7 @@ export default {
|
|||||||
onActive(type) {
|
onActive(type) {
|
||||||
if (this.dialogActive == type) {
|
if (this.dialogActive == type) {
|
||||||
// 再次点击滚动到未读条目
|
// 再次点击滚动到未读条目
|
||||||
const dialog = this.dialogList.find(dialog => $A.getDialogUnread(dialog) > 0)
|
const dialog = this.dialogList.find(dialog => $A.getDialogUnread(dialog, false) > 0)
|
||||||
if (dialog) {
|
if (dialog) {
|
||||||
$A.scrollIntoViewIfNeeded(this.$refs[`dialog_${dialog.id}`][0])
|
$A.scrollIntoViewIfNeeded(this.$refs[`dialog_${dialog.id}`][0])
|
||||||
}
|
}
|
||||||
@ -531,7 +532,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
filterDialog(dialog) {
|
filterDialog(dialog) {
|
||||||
if ($A.getDialogUnread(dialog) > 0 || dialog.id == this.dialogId || dialog.top_at || dialog.todo_num > 0) {
|
if ($A.getDialogUnread(dialog, false) > 0 || dialog.id == this.dialogId || dialog.top_at || dialog.todo_num > 0) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (dialog.name === undefined || dialog.dialog_delete === 1) {
|
if (dialog.name === undefined || dialog.dialog_delete === 1) {
|
||||||
@ -718,12 +719,29 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleReadClick(type) {
|
handleReadClick() {
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
url: 'dialog/msg/mark',
|
url: 'dialog/msg/mark',
|
||||||
data: {
|
data: {
|
||||||
dialog_id: this.operateItem.id,
|
dialog_id: this.operateItem.id,
|
||||||
type: type
|
type: $A.getDialogUnread(this.operateItem, true) > 0 ? 'read' : 'unread'
|
||||||
|
},
|
||||||
|
}).then(({data}) => {
|
||||||
|
this.$store.dispatch("saveDialog", data);
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
$A.modalError(msg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSilenceClick() {
|
||||||
|
if (this.silenceDisabled(this.operateItem)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'dialog/msg/silence',
|
||||||
|
data: {
|
||||||
|
dialog_id: this.operateItem.id,
|
||||||
|
type: this.operateItem.silence ? 'cancel' : 'set'
|
||||||
},
|
},
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.$store.dispatch("saveDialog", data);
|
this.$store.dispatch("saveDialog", data);
|
||||||
@ -747,7 +765,12 @@ export default {
|
|||||||
$A.eeuiAppSendMessage({
|
$A.eeuiAppSendMessage({
|
||||||
action: 'gotoSetting',
|
action: 'gotoSetting',
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
silenceDisabled(data) {
|
||||||
|
const {type, group_type} = data
|
||||||
|
return type === 'group' && group_type !== 'user'
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -205,6 +205,7 @@
|
|||||||
.dialog-text {
|
.dialog-text {
|
||||||
color: $primary-desc-color;
|
color: $primary-desc-color;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
min-height: 24px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -248,6 +249,10 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.last-silence {
|
||||||
|
padding-left: 4px;
|
||||||
|
color: rgba($primary-desc-color, 0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dialog-num {
|
.dialog-num {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user