diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php
index 0c262d943..a9a6782f4 100755
--- a/app/Http/Controllers/Api/DialogController.php
+++ b/app/Http/Controllers/Api/DialogController.php
@@ -48,7 +48,7 @@ class DialogController extends AbstractController
{
$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')
->where('u.userid', $user->userid);
if (Request::exists('at_after')) {
@@ -88,7 +88,7 @@ class DialogController extends AbstractController
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')
->where('web_socket_dialogs.name', 'LIKE', "%{$key}%")
->where('u.userid', $user->userid)
@@ -121,7 +121,7 @@ class DialogController extends AbstractController
}
// 搜索消息会话
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_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id')
->where('u.userid', $user->userid)
@@ -158,7 +158,7 @@ class DialogController extends AbstractController
//
$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')
->where('web_socket_dialogs.id', $dialog_id)
->where('u.userid', $user->userid)
@@ -1060,6 +1060,69 @@ class DialogController extends AbstractController
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. 转发消息给
*
diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php
index d6b5c5903..9f946ae4f 100644
--- a/app/Models/WebSocketDialog.php
+++ b/app/Models/WebSocketDialog.php
@@ -5,6 +5,7 @@ namespace App\Models;
use App\Exceptions\ApiException;
use App\Module\Base;
use App\Tasks\PushTask;
+use Cache;
use Carbon\Carbon;
use Hhxsv5\LaravelS\Swoole\Task\Task;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -60,6 +61,13 @@ class WebSocketDialog extends AbstractModel
*/
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)) {
// 最后消息 (搜索预览消息)
$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->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);
$this->people = $builder->count();
@@ -86,7 +96,7 @@ class WebSocketDialog extends AbstractModel
// 对方信息
$this->dialog_user = 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;
switch ($this->type) {
case "user":
diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php
index 02991e6a6..a4d40269d 100644
--- a/app/Models/WebSocketDialogMsg.php
+++ b/app/Models/WebSocketDialogMsg.php
@@ -541,8 +541,7 @@ class WebSocketDialogMsg extends AbstractModel
$text = preg_replace("/]*?>/", "[图片]", $text);
if (!$preserveHtml) {
$text = strip_tags($text);
- $text = str_replace(" ", " ", $text);
- $text = str_replace("&", "&", $text);
+ $text = str_replace([" ", "&", "<", ">"], [" ", "&", "<", ">"], $text);
}
return $text;
}
diff --git a/app/Models/WebSocketDialogUser.php b/app/Models/WebSocketDialogUser.php
index 1f48cf039..24d634158 100644
--- a/app/Models/WebSocketDialogUser.php
+++ b/app/Models/WebSocketDialogUser.php
@@ -10,6 +10,7 @@ namespace App\Models;
* @property int|null $userid 会员ID
* @property string|null $top_at 置顶时间
* @property int|null $mark_unread 是否标记为未读:0否,1是
+ * @property int|null $silence 是否免打扰:0否,1是
* @property int|null $inviter 邀请人
* @property int|null $important 是否不可移出(项目、任务、部门人员)
* @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 whereInviter($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 whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUserid($value)
diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php
index 2ad6ea8e4..12bb9b37f 100644
--- a/app/Tasks/BotReceiveMsgTask.php
+++ b/app/Tasks/BotReceiveMsgTask.php
@@ -192,7 +192,7 @@ class BotReceiveMsgTask extends AbstractTask
case '/dialog':
$data = $this->botManagerOne($array[1], $msg->userid);
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')
->where('web_socket_dialogs.name', 'LIKE', "%{$array[2]}%")
->where('u.userid', $data->userid)
diff --git a/app/Tasks/WebSocketDialogMsgTask.php b/app/Tasks/WebSocketDialogMsgTask.php
index 833855fb4..f35f7c3a1 100644
--- a/app/Tasks/WebSocketDialogMsgTask.php
+++ b/app/Tasks/WebSocketDialogMsgTask.php
@@ -24,7 +24,7 @@ class WebSocketDialogMsgTask extends AbstractTask
protected $id;
protected $ignoreFd;
protected $msgNotExistRetry = false; // 推送失败后重试
- protected $silence = false; // 静默推送(1:前端不通知、2:App不推送)
+ protected $silence = false; // 静默推送(前端不通知、App不推送,如果会话设置了免打扰则强制静默)
protected $endPush = [];
protected $endArray = [];
@@ -85,6 +85,8 @@ class WebSocketDialogMsgTask extends AbstractTask
if (empty($dialog)) {
return;
}
+ $silences = $dialog->dialogUser->pluck('silence', 'userid')->toArray();
+ $userids = array_keys($silences);
// 提及会员
$mentions = [];
@@ -96,7 +98,6 @@ class WebSocketDialogMsgTask extends AbstractTask
}
// 将会话以外的成员加入会话内
- $userids = $dialog->dialogUser->pluck('userid')->toArray();
$diffids = array_values(array_diff($mentions, $userids));
if ($diffids) {
// 仅(群聊)且(是群主或没有群主)才可以@成员以外的人
@@ -111,7 +112,11 @@ class WebSocketDialogMsgTask extends AbstractTask
$array = [];
foreach ($userids AS $userid) {
if ($userid == $msg->userid) {
- $array[$userid] = false;
+ $array[$userid] = [
+ 'userid' => $userid,
+ 'silence' => $this->silence || $silences[$userid],
+ 'mention' => false,
+ ];
} else {
$mention = array_intersect([0, $userid], $mentions) ? 1 : 0;
WebSocketDialogMsgRead::createInstance([
@@ -120,7 +125,11 @@ class WebSocketDialogMsgTask extends AbstractTask
'userid' => $userid,
'mention' => $mention,
])->saveOrIgnore();
- $array[$userid] = $mention;
+ $array[$userid] = [
+ 'userid' => $userid,
+ 'silence' => $this->silence || $silences[$userid],
+ 'mention' => $mention,
+ ];
// 机器人收到消处理
$botUser = User::whereUserid($userid)->whereBot(1)->first();
if ($botUser) {
@@ -132,40 +141,41 @@ class WebSocketDialogMsgTask extends AbstractTask
$msg->send = WebSocketDialogMsgRead::whereMsgId($msg->id)->count();
$msg->save();
// 开始推送消息
- foreach ($array as $userid => $mention) {
+ $umengUserid = [];
+ foreach ($array as $item) {
$this->endPush[] = [
- 'userid' => $userid,
+ 'userid' => $item['userid'],
'ignoreFd' => $this->ignoreFd,
'msg' => [
'type' => 'dialog',
'mode' => 'add',
- 'silence' => $this->silence ? 1 : 0,
+ 'silence' => $item['silence'] ? 1 : 0,
'data' => array_merge($msg->toArray(), [
- 'mention' => $mention,
+ 'mention' => $item['mention'],
]),
]
];
+ if ($item['userid'] != $msg->userid && !$item['silence'] && !$this->silence) {
+ $umengUserid[] = $item['userid'];
+ }
}
// umeng推送app
- $setting = Base::setting('appPushSetting');
- $pushMsg = $setting['push'] === 'open' && $setting['push_msg'] !== 'close';
- if (!$this->silence && $pushMsg) {
- $umengUserid = $array;
- if (isset($umengUserid[$msg->userid])) {
- unset($umengUserid[$msg->userid]);
+ if ($umengUserid) {
+ $setting = Base::setting('appPushSetting');
+ $pushMsg = $setting['push'] === 'open' && $setting['push_msg'] !== 'close';
+ if ($pushMsg) {
+ $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,
+ ]);
}
- $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();
if ($list) {
$array = [];
- foreach ($list as $uid) {
- if (!in_array($uid, $userids)) {
- $array[] = $uid;
+ foreach ($list as $item) {
+ if (!in_array($item, $userids)) {
+ $array[] = $item;
}
}
if ($array) {
diff --git a/database/migrations/2023_01_17_124320_add_web_socket_dialog_users_add_silence.php b/database/migrations/2023_01_17_124320_add_web_socket_dialog_users_add_silence.php
new file mode 100644
index 000000000..b4ffda856
--- /dev/null
+++ b/database/migrations/2023_01_17_124320_add_web_socket_dialog_users_add_silence.php
@@ -0,0 +1,34 @@
+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");
+ });
+ }
+}
diff --git a/public/css/fonts/taskfont/iconfont.ttf b/public/css/fonts/taskfont/iconfont.ttf
index ab5e55f2d..f96027b2f 100644
Binary files a/public/css/fonts/taskfont/iconfont.ttf and b/public/css/fonts/taskfont/iconfont.ttf differ
diff --git a/public/css/fonts/taskfont/iconfont.woff b/public/css/fonts/taskfont/iconfont.woff
index 783a77bb5..d203ec9b0 100644
Binary files a/public/css/fonts/taskfont/iconfont.woff and b/public/css/fonts/taskfont/iconfont.woff differ
diff --git a/public/css/fonts/taskfont/iconfont.woff2 b/public/css/fonts/taskfont/iconfont.woff2
index e379e314c..2538cab30 100644
Binary files a/public/css/fonts/taskfont/iconfont.woff2 and b/public/css/fonts/taskfont/iconfont.woff2 differ
diff --git a/resources/assets/js/components/Mobile/Tabbar.vue b/resources/assets/js/components/Mobile/Tabbar.vue
index afcd92dd4..88b4085f4 100644
--- a/resources/assets/js/components/Mobile/Tabbar.vue
+++ b/resources/assets/js/components/Mobile/Tabbar.vue
@@ -97,7 +97,7 @@ export default {
let num = 0; // 未读
let mention = 0; // 提及
this.cacheDialogs.some(dialog => {
- num += $A.getDialogUnread(dialog);
+ num += $A.getDialogUnread(dialog, false);
mention += $A.getDialogMention(dialog);
})
if (num > 99) {
@@ -129,7 +129,7 @@ export default {
msgAllUnread() {
let num = 0;
this.cacheDialogs.some(dialog => {
- num += $A.getDialogUnread(dialog);
+ num += $A.getDialogUnread(dialog, false);
})
return num;
},
diff --git a/resources/assets/js/functions/web.js b/resources/assets/js/functions/web.js
index 51ba84fd0..9699cd3ea 100755
--- a/resources/assets/js/functions/web.js
+++ b/resources/assets/js/functions/web.js
@@ -350,10 +350,12 @@
/**
* 返回对话未读数量
* @param dialog
+ * @param containSilence
* @returns {*|number}
*/
- getDialogUnread(dialog) {
- return dialog ? (dialog.unread || dialog.mark_unread || 0) : 0
+ getDialogUnread(dialog, containSilence) {
+ const unread = containSilence || !dialog.silence ? dialog.unread : 0
+ return dialog ? (unread || dialog.mark_unread || 0) : 0
},
/**
@@ -375,9 +377,12 @@
text = text.replace(/
]*?alt="(\S+)"[^>]*?>/g, "[$1]")
text = text.replace(/
]*?>/g, `[${$A.L('动画表情')}]`)
text = text.replace(/
]*?>/g, `[${$A.L('图片')}]`)
+ 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
},
/**
diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue
index 3e851f731..d637faba1 100644
--- a/resources/assets/js/pages/manage.vue
+++ b/resources/assets/js/pages/manage.vue
@@ -448,7 +448,7 @@ export default {
let num = 0; // 未读
let mention = 0; // 提及
this.cacheDialogs.some(dialog => {
- num += $A.getDialogUnread(dialog);
+ num += $A.getDialogUnread(dialog, false);
mention += $A.getDialogMention(dialog);
})
if (num > 99) {
@@ -480,7 +480,7 @@ export default {
msgAllUnread() {
let num = 0;
this.cacheDialogs.some(dialog => {
- num += $A.getDialogUnread(dialog);
+ num += $A.getDialogUnread(dialog, false);
})
return num;
},
diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue
index 13cdb690a..8517eab1d 100644
--- a/resources/assets/js/pages/manage/components/DialogWrapper.vue
+++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue
@@ -703,7 +703,7 @@ export default {
msgUnreadOnly() {
let num = 0;
this.cacheDialogs.some(dialog => {
- num += $A.getDialogUnread(dialog);
+ num += $A.getDialogUnread(dialog, false);
})
if (num <= 0) {
return '';
diff --git a/resources/assets/js/pages/manage/components/ProjectPanel.vue b/resources/assets/js/pages/manage/components/ProjectPanel.vue
index 680a54216..658a01b17 100644
--- a/resources/assets/js/pages/manage/components/ProjectPanel.vue
+++ b/resources/assets/js/pages/manage/components/ProjectPanel.vue
@@ -586,7 +586,7 @@ export default {
msgUnread() {
const {cacheDialogs, projectData} = this;
const dialog = cacheDialogs.find(({id}) => id === projectData.dialog_id);
- return dialog ? $A.getDialogUnread(dialog) : 0;
+ return dialog ? $A.getDialogUnread(dialog, false) : 0;
},
panelTask() {
diff --git a/resources/assets/js/pages/manage/messenger.vue b/resources/assets/js/pages/manage/messenger.vue
index dab823011..838dc6363 100644
--- a/resources/assets/js/pages/manage/messenger.vue
+++ b/resources/assets/js/pages/manage/messenger.vue
@@ -83,9 +83,10 @@
{{formatMsgEmojiDesc(dialog.last_msg)}}
{{$A.getMsgSimpleDesc(dialog.last_msg)}}
+