diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 52d0f00f4..9582325d2 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -568,36 +568,6 @@ class DialogController extends AbstractController return Base::retSuccess("success"); } - /** - * @api {get} api/dialog/top 14. 会话置顶 - * - * @apiDescription 需要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("会话不存在"); - } - $dialogUser->top_at = $dialogUser->top_at ? null : Carbon::now(); - $dialogUser->save(); - return Base::retSuccess("success", [ - 'id' => $dialogUser->dialog_id, - 'top_at' => $dialogUser->top_at?->toDateTimeString(), - ]); - } - /** * @api {get} api/dialog/msg/mark 15. 消息标记操作 * @@ -679,6 +649,69 @@ class DialogController extends AbstractController return $msg->forwardMsg($userids, $user->userid); } + /** + * @api {get} api/dialog/msg/emoji 13. emoji回复 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup dialog + * @apiName msg__forward + * + * @apiParam {Number} msg_id 消息ID + * @apiParam {String} emoji 回复或取消的emoji表情 + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function msg__emoji() + { + $user = User::auth(); + // + $msg_id = intval(Request::input("msg_id")); + $emoji = Request::input("emoji"); + // + if (!preg_match("/^[\u{d800}-\u{dbff}]|[\u{dc00}-\u{dfff}]$/", $emoji)) { + return Base::retError("参数错误"); + } + // + $msg = WebSocketDialogMsg::whereId($msg_id)->whereUserid($user->userid)->first(); + if (empty($msg)) { + return Base::retError("消息不存在或已被删除"); + } + return $msg->emojiMsg($emoji, $user->userid); + } + + /** + * @api {get} api/dialog/top 14. 会话置顶 + * + * @apiDescription 需要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("会话不存在"); + } + $dialogUser->top_at = $dialogUser->top_at ? null : Carbon::now(); + $dialogUser->save(); + return Base::retSuccess("success", [ + 'id' => $dialogUser->dialog_id, + 'top_at' => $dialogUser->top_at?->toDateTimeString(), + ]); + } + /** * @api {get} api/dialog/group/add 16. 新增群组 * diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index 2430aa652..45d18f0bc 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -19,6 +19,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property int|null $userid 发送会员ID * @property string|null $type 消息类型 * @property array|mixed $msg 详细消息 + * @property array|mixed $emoji emoji回复 * @property int|null $read 已阅数量 * @property int|null $send 发送数量 * @property \Illuminate\Support\Carbon|null $created_at @@ -34,6 +35,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereDeletedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereDialogId($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereDialogType($value) + * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereEmoji($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereMsg($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereRead($value) @@ -98,6 +100,19 @@ class WebSocketDialogMsg extends AbstractModel return $value; } + /** + * emoji回复格式化 + * @param $value + * @return array|mixed + */ + public function getEmojiAttribute($value) + { + if (is_array($value)) { + return $value; + } + return Base::json2array($value); + } + /** * 获取占比 * @param bool|int $increment 是否新增阅读数 @@ -161,6 +176,53 @@ class WebSocketDialogMsg extends AbstractModel return true; } + /** + * emoji回复 + * @param $emoji + * @param int $sender 发送的会员ID + * @return mixed + */ + public function emojiMsg($emoji, $sender) + { + $exist = false; + $array = $this->emoji; + foreach ($array as $index => &$item) { + if ($item['symbol'] === $emoji) { + if (in_array($sender, $item['userids'])) { + // 已存在 去除 + $item['userids'] = array_values(array_diff($item['userids'], [$sender])); + if (empty($item['userids'])) { + unset($array[$index]); + $array = array_values($array); + } + } else { + // 未存在 添加 + array_unshift($item['userids'], $sender); + } + $exist = true; + break; + } + } + if (!$exist) { + array_unshift($array, [ + 'symbol' => $emoji, + 'userids' => [$sender] + ]); + } + // + $this->emoji = Base::array2json($array); + $this->save(); + $resData = [ + 'id' => $this->id, + 'emoji' => $array, + ]; + // + $dialog = WebSocketDialog::find($this->dialog_id); + $dialog?->pushMsg('update', $resData); + // + return Base::retSuccess('sucess', $resData); + } + /** * 转发消息 * @param $userids diff --git a/database/migrations/2022_06_04_095019_add_web_socket_dialog_msgs_emoji.php b/database/migrations/2022_06_04_095019_add_web_socket_dialog_msgs_emoji.php new file mode 100644 index 000000000..9164d303b --- /dev/null +++ b/database/migrations/2022_06_04_095019_add_web_socket_dialog_msgs_emoji.php @@ -0,0 +1,34 @@ +longText('emoji')->after('msg')->nullable()->comment('emoji回复'); + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('web_socket_dialog_msgs', function (Blueprint $table) { + $table->dropColumn("emoji"); + }); + } +} diff --git a/resources/assets/js/pages/manage/components/DialogView.vue b/resources/assets/js/pages/manage/components/DialogView.vue index 5d37045e0..a1c7c6b14 100644 --- a/resources/assets/js/pages/manage/components/DialogView.vue +++ b/resources/assets/js/pages/manage/components/DialogView.vue @@ -5,15 +5,9 @@ -
+
-
+

@@ -66,6 +60,17 @@
                 
                 
{{$L("未知的消息类型")}}
+ +
    +
  • +
    {{item.symbol}}
    +
    {{item.userids.length}}
    +
  • +
@@ -523,6 +528,20 @@ export default { this.$store.dispatch('downUrl', $A.apiUrl(`dialog/msg/download?msg_id=${this.msgData.id}`)) } }); + }, + + setEmoji(emoji) { + this.$store.dispatch("call", { + url: 'dialog/msg/emoji', + data: { + msg_id: this.msgData.id, + emoji, + }, + }).then(({data}) => { + this.$store.dispatch("saveDialogMsg", data); + }).catch(({msg}) => { + $A.messageError(msg); + }); } } } diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index a5ad67c63..123cf1712 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -139,46 +139,56 @@
- -
- {{ $L('复制') }} - -
+ +
    + +
  • + + {{ $L('转发') }} +
  • + + +
- -
- {{ $L('转发') }} - -
+ +
    +
  • +
- -
- {{ $L('撤回') }} - -
-
-
@@ -260,6 +270,7 @@ import ChatInput from "./ChatInput"; import { DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller-hi' import 'vue-virtual-scroller-hi/dist/vue-virtual-scroller.css' +import {Store} from "le5le-store"; export default { name: "DialogWrapper", @@ -317,6 +328,7 @@ export default { operateHasText: false, operateStyles: {}, operateItem: {}, + operateEmojis: ['👌', '🤝', '🤔', '👍', '👎', '👏', '✋', '✅', '❌', '❤️', '❓'] } }, @@ -839,12 +851,11 @@ export default { }) }, - onOperate(name) { + onOperate(name, value = null) { switch (name) { case "copy": if (this.operateHasText) { - const text = this.operateItem.msg.text.replace(/<[^>]+>/g,""); - this.$copyText(text).then(_ => { + this.$copyText(this.operateItem.msg.text.replace(/<[^>]+>/g, "")).then(_ => { $A.messageSuccess('复制成功'); }).catch(_ => { $A.messageError('复制失败'); @@ -854,6 +865,15 @@ export default { } break; + case "newTask": + if (this.operateHasText) { + Store.set('addTask', { + owner: [this.userId], + name: this.operateItem.msg.text.replace(/<[^>]+>/g, "") + }); + } + break; + case "forward": this.onForward('open') break; @@ -869,6 +889,10 @@ export default { case "down": this.$refs[`msg_${this.operateItem.id}`].downFile() break; + + case "emoji": + this.$refs[`msg_${this.operateItem.id}`].setEmoji(value) + break; } }, } diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 03e41e226..17ade9961 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -2378,8 +2378,9 @@ export default { // 更新最后消息 dispatch("updateDialogLastMsg", data); break; + case 'update': case 'readed': - // 已读回执 + // 更新、已读回执 if (state.dialogMsgs.find(({id}) => id == data.id)) { dispatch("saveDialogMsg", data) } diff --git a/resources/assets/sass/dark.scss b/resources/assets/sass/dark.scss index a644bb68a..34656fe18 100644 --- a/resources/assets/sass/dark.scss +++ b/resources/assets/sass/dark.scss @@ -179,21 +179,29 @@ body.dark-mode-reverse { .dialog-item { .dialog-view { .dialog-head { + background-color: #e1e1e1; .dialog-content { - background-color: #e1e1e1; .content-text, .content-record, .content-meeting { color: #ffffff; } } + .dialog-emoji { + > li { + background-color: rgba(#f3f3f3, 0.5); + &.hasme { + background-color: #f3f3f3; + } + } + } } } &.self { .dialog-view { .dialog-head { + background-color: $primary-color; .dialog-content { - background-color: $primary-color; .content-text { > pre { a { @@ -205,6 +213,17 @@ body.dark-mode-reverse { } } } + .dialog-emoji { + > li { + background-color: rgba(#b2ff93, 0.5); + &.hasme { + background-color: #b2ff93; + } + .emoji-num { + color: #000000; + } + } + } } } } diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss index 36d3cf396..5e9768242 100644 --- a/resources/assets/sass/pages/components/dialog-wrapper.scss +++ b/resources/assets/sass/pages/components/dialog-wrapper.scss @@ -221,9 +221,7 @@ &.operate-action { .dialog-head { - .dialog-content { - box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2); - } + box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2); } } @@ -236,16 +234,16 @@ .dialog-head { display: flex; - align-items: flex-start; + flex-direction: column; + background-color: #F4F5F7; + padding: 8px; + min-width: 32px; + border-radius: 2px 8px 8px 8px; + transition: box-shadow 0.3s ease; .dialog-content { - background-color: #F4F5F7; - padding: 8px; - min-width: 32px; - border-radius: 2px 8px 8px 8px; display: flex; align-items: flex-start; - transition: box-shadow 0.3s ease; &.an-emoticon, &.an-emoji, @@ -558,6 +556,34 @@ text-decoration: underline; } } + + .dialog-emoji { + display: flex; + align-items: center; + margin-top: 4px; + > li { + list-style: none; + display: flex; + align-items: center; + padding: 2px 7px; + margin-right: 8px; + border-radius: 14px; + line-height: 22px; + cursor: pointer; + background-color: rgba(#e1e1e1, 0.5); + &.hasme { + background-color: #e1e1e1; + } + .emoji-symbol { + font-size: 16px; + } + .emoji-num { + font-size: 12px; + padding-left: 4px; + color: #818181; + } + } + } } .dialog-foot { @@ -674,12 +700,10 @@ margin: 0 8px 0 0; .dialog-head { - flex-direction: row-reverse; + background-color: $primary-color; + border-radius: 8px 2px 8px 8px; .dialog-content { - background-color: $primary-color; - border-radius: 8px 2px 8px 8px; - .content-text { color: #ffffff; @@ -738,6 +762,18 @@ } } } + + .dialog-emoji { + > li { + background-color: rgba(#5ba93c, 0.5); + &.hasme { + background-color: #5ba93c; + } + .emoji-num { + color: #ffffff; + } + } + } } .dialog-foot { @@ -842,7 +878,7 @@ .operate-position { position: absolute; top: 0; - right: 0; + left: 0; width: 1px; opacity: 0; visibility: hidden; @@ -941,13 +977,61 @@ } .dialog-wrapper-operate { - .operate-item { + .ivu-dropdown-item { + padding: 0; + &:hover { + background-color: transparent; + } + } + .operate-action { + width: 316px; + padding: 8px; + margin-bottom: -8px; + display: grid; + justify-content: space-between; + grid-template-columns: repeat(auto-fill, 50px); + > li { + list-style: none; + width: 50px; + height: 48px; + margin-bottom: 12px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + .taskfont { + font-size: 20px; + } + > span { + font-size: 12px; + } + } + } + .operate-emoji { + width: 316px; + padding: 8px 4px 2px; display: flex; align-items: center; - justify-content: space-between; - min-width: 80px; - .taskfont { - margin-left: 24px; + overflow: auto; + position: relative; + &:after { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 1px; + background-color: #f4f5f5; + } + > li { + list-style: none; + width: 44px; + box-sizing: content-box; + display: flex; + flex-shrink: 0; + font-size: 24px; + justify-content: center; + align-items: center; } } } diff --git a/resources/assets/sass/pages/components/project-list.scss b/resources/assets/sass/pages/components/project-list.scss index e0bb2d67c..03c5d388b 100644 --- a/resources/assets/sass/pages/components/project-list.scss +++ b/resources/assets/sass/pages/components/project-list.scss @@ -185,7 +185,7 @@ .operate-position { position: absolute; top: 0; - right: 0; + left: 0; width: 1px; opacity: 0; visibility: hidden; diff --git a/resources/assets/sass/pages/page-manage.scss b/resources/assets/sass/pages/page-manage.scss index 35b384432..3bf278a87 100644 --- a/resources/assets/sass/pages/page-manage.scss +++ b/resources/assets/sass/pages/page-manage.scss @@ -192,7 +192,7 @@ .operate-position { position: absolute; top: 0; - right: 0; + left: 0; width: 1px; opacity: 0; visibility: hidden; diff --git a/resources/assets/sass/pages/page-messenger.scss b/resources/assets/sass/pages/page-messenger.scss index 024c7e51f..7a7a2acfa 100644 --- a/resources/assets/sass/pages/page-messenger.scss +++ b/resources/assets/sass/pages/page-messenger.scss @@ -367,7 +367,7 @@ .operate-position { position: absolute; top: 0; - right: 0; + left: 0; width: 1px; opacity: 0; visibility: hidden;