diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 5121f0350..29fd2d3ab 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -2334,6 +2334,9 @@ class DialogController extends AbstractController } WebSocketDialog::checkDialog($msgs->first()->dialog_id); foreach ($msgs as $msg) { + if (in_array($msg->type, WebSocketDialogMsg::$unforwardableTypes)) { + continue; + } $res = $msg->forwardMsg($dialogids, $userids, $user, $show_source, $leave_message); if (Base::isSuccess($res)) { $allMsgs = array_merge($allMsgs, $res['data']['msgs']); @@ -2356,12 +2359,12 @@ class DialogController extends AbstractController } /** - * @api {get} api/dialog/msg/merge-forward 合并转发消息 + * @api {get} api/dialog/msg/mergeforward 合并转发消息 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 * @apiGroup dialog - * @apiName msg__merge_forward + * @apiName msg__mergeforward * * @apiParam {Array} msg_ids 消息ID数组(最多100条) * @apiParam {Array} dialogids 转发给的对话ID @@ -2373,7 +2376,7 @@ class DialogController extends AbstractController * @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {Object} data 返回数据 */ - public function msg__merge_forward() + public function msg__mergeforward() { $user = User::auth(); // @@ -2396,6 +2399,57 @@ class DialogController extends AbstractController return WebSocketDialogMsg::mergeForwardMsg($msg_ids, $dialogids, $userids, $user, $show_source, $leave_message); } + /** + * @api {get} api/dialog/msg/mergedetail 合并转发消息详情 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup dialog + * @apiName msg__mergedetail + * + * @apiParam {Number} msg_id 合并转发消息ID + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function msg__mergedetail() + { + User::auth(); + // + $msg_id = intval(Request::input('msg_id')); + if ($msg_id <= 0) { + return Base::retError('参数错误'); + } + $dialogMsg = WebSocketDialogMsg::find($msg_id); + if (!$dialogMsg || $dialogMsg->type !== 'merge-forward') { + return Base::retError('消息不存在或已被删除'); + } + WebSocketDialog::checkDialog($dialogMsg->dialog_id); + // + $msgData = Base::json2array($dialogMsg->getRawOriginal('msg')); + $msgIds = $msgData['msg_ids'] ?? []; + if (empty($msgIds)) { + return Base::retError('消息不存在或已被删除'); + } + $msgs = WebSocketDialogMsg::withTrashed() + ->whereIn('id', $msgIds) + ->orderBy('created_at') + ->get() + ->map(function ($msg) { + return [ + 'id' => $msg->id, + 'userid' => $msg->userid, + 'type' => $msg->type, + 'msg' => $msg->msg, + 'created_at' => $msg->created_at->toDateTimeString(), + ]; + }); + return Base::retSuccess('success', [ + 'msgs' => $msgs, + ]); + } + /** * @api {get} api/dialog/msg/emoji emoji回复 * diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 4c200cf0c..658751fa5 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -500,7 +500,7 @@ class Setting extends AbstractModel } $limitTime = Carbon::parse($dialogMsg->created_at)->addMinutes($limitNum); if ($limitTime->lt(Carbon::now())) { - throw new ApiException('已超过' . Doo::translate(Base::forumMinuteDay($limitNum)) . ',' . $error); + throw new ApiException('已超过' . Base::forumMinuteDay($limitNum) . ',' . $error); } } } diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index d2b61facd..954c9de6c 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -533,9 +533,17 @@ class WebSocketDialogMsg extends AbstractModel return $dialogs; } + /** + * 不支持转发的消息类型 + */ + public static $unforwardableTypes = ['tag', 'top', 'todo', 'notice', 'word-chain', 'vote', 'template']; + public function forwardMsg($dialogids, $userids, $user, $showSource = 1, $leaveMessage = '') { return AbstractModel::transaction(function () use ($dialogids, $user, $userids, $showSource, $leaveMessage) { + if (in_array($this->type, self::$unforwardableTypes)) { + throw new ApiException('此类型消息不支持转发'); + } $msgData = Base::json2array($this->getRawOriginal('msg')); $forwardData = is_array($msgData['forward_data']) ? $msgData['forward_data'] : []; $forwardId = $forwardData['id'] ?: $this->id; @@ -601,31 +609,35 @@ class WebSocketDialogMsg extends AbstractModel throw new ApiException('只能合并转发同一对话的消息'); } WebSocketDialog::checkDialog($dialogId); - // 收集发送者生成标题 + // 过滤不支持转发的消息类型 + $msgs = $msgs->filter(function ($msg) { + return !in_array($msg->type, self::$unforwardableTypes); + }); + if ($msgs->isEmpty()) { + throw new ApiException('所选消息均不支持转发'); + } + // 收集发送者信息 $senderIds = $msgs->pluck('userid')->unique()->values()->toArray(); $senderNames = User::whereIn('userid', array_slice($senderIds, 0, 2)) ->pluck('nickname') ->toArray(); - $title = implode(Doo::translate('和'), $senderNames); - if (count($senderIds) > 2) { - $title .= Doo::translate('等人'); - } - $title .= Doo::translate('的聊天记录'); - // 组装消息列表 - $list = []; - foreach ($msgs as $msg) { - $list[] = [ + // 组装预览列表(前4条,精简字段) + $msgIds = $msgs->pluck('id')->toArray(); + $preview = []; + foreach ($msgs->take(4) as $msg) { + $preview[] = [ 'userid' => $msg->userid, 'type' => $msg->type, - 'msg' => Base::json2array($msg->getRawOriginal('msg')), - 'created_at' => $msg->created_at->toDateTimeString(), + 'msg' => self::buildPreviewMsg($msg->type, Base::json2array($msg->getRawOriginal('msg'))), ]; } // 构建合并转发消息体 $msgData = [ - 'title' => $title, - 'list' => $list, - 'count' => count($list), + 'sender_names' => $senderNames, + 'sender_total' => count($senderIds), + 'msg_ids' => $msgIds, + 'preview' => $preview, + 'count' => count($msgIds), 'forward_data' => [ 'show' => $showSource, 'leave' => $leaveMessage ? 1 : 0, @@ -652,6 +664,26 @@ class WebSocketDialogMsg extends AbstractModel }); } + /** + * 构建预览消息(精简字段) + * @param string $type + * @param array $msg + * @return array + */ + private static function buildPreviewMsg($type, $msg) + { + switch ($type) { + case 'text': + return ['text' => $msg['text'] ?? '']; + case 'file': + return ['name' => $msg['name'] ?? '', 'ext' => $msg['ext'] ?? '']; + case 'location': + return ['title' => $msg['title'] ?? '']; + default: + return []; + } + } + /** * 删除消息 * @param array|int $ids @@ -784,8 +816,7 @@ class WebSocketDialogMsg extends AbstractModel return self::previewTemplateMsg($data['msg']); case 'merge-forward': - $action = Doo::translate("聊天记录"); - return "[{$action}] " . Base::cutStr($data['msg']['title'] ?? '', 50); + return "[" . Doo::translate("聊天记录") . "]"; case 'preview': return $data['msg']['preview']; diff --git a/language/original-api.txt b/language/original-api.txt index bdb5745ca..1379d9b08 100644 --- a/language/original-api.txt +++ b/language/original-api.txt @@ -963,3 +963,13 @@ AI建议:采纳(*)建议 消息内容格式错误 AI 调用失败 AI 返回内容为空 + +修改AI自动分析 +关联不存在 +只能合并转发同一对话的消息 +所选消息均不支持转发 +无法创建任务对话 +最多转发(*)条消息 +此类型消息不支持转发 +没有权限操作此任务 +请选择要转发的消息 diff --git a/language/original-web.txt b/language/original-web.txt index db4fb2c3c..7ad3b3747 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -2329,3 +2329,21 @@ AI 消息助手 指派 关联 采纳 + +逐条转发 +合并转发 + +AI任务分析 +关闭后所有项目将不再自动分析任务。 +关闭后本项目将不再自动分析任务。 +新建任务后AI自动分析并给出建议。 +(最多(*)条) +最多选择(*)条消息 +系统已关闭AI任务分析功能。 +聊天记录 +确定要解除与任务 #(*) 的关联吗? +共(*)条消息 +已选(*)条 +(*)的聊天记录 +(*)和(*)的聊天记录 +(*)和(*)等人的聊天记录 \ No newline at end of file diff --git a/resources/assets/js/functions/web.js b/resources/assets/js/functions/web.js index 7929a6673..da6ca3db5 100755 --- a/resources/assets/js/functions/web.js +++ b/resources/assets/js/functions/web.js @@ -431,6 +431,20 @@ import {convertLocalResourcePath} from "../components/Replace/utils"; * @param imgClassName * @returns {string|*} */ + getMergeForwardTitle(msg) { + const names = msg.sender_names || []; + if (names.length === 0) { + return $A.L('聊天记录'); + } + if (names.length === 1) { + return $A.L('(*)的聊天记录', names[0]); + } + if (msg.sender_total > 2) { + return $A.L('(*)和(*)等人的聊天记录', names[0], names[1]); + } + return $A.L('(*)和(*)的聊天记录', names[0], names[1]); + }, + getMsgSimpleDesc(data, imgClassName = null) { if (!$A.isJson(data)) { return ''; @@ -462,7 +476,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils"; const notice = data.msg.source === 'api' ? data.msg.notice : $A.L(data.msg.notice); return $A.cutString(notice, 50) case 'merge-forward': - return `[${$A.L('聊天记录')}] ${$A.cutString(data.msg.title || '', 50)}` + return `[${$A.L('聊天记录')}] ${$A.cutString($A.getMergeForwardTitle(data.msg), 50)}` case 'template': return $A.templateMsgSimpleDesc(data.msg) case 'preview': diff --git a/resources/assets/js/pages/manage/components/DialogItem.vue b/resources/assets/js/pages/manage/components/DialogItem.vue index 4b334302e..0ecab8785 100644 --- a/resources/assets/js/pages/manage/components/DialogItem.vue +++ b/resources/assets/js/pages/manage/components/DialogItem.vue @@ -72,7 +72,8 @@ @on-error="onError" @on-emoji="onEmoji" @on-other="onOther" - @on-show-emoji-user="onShowEmojiUser"/> + @on-show-emoji-user="onShowEmojiUser" + @on-merge-forward-detail="onMergeForwardDetail"/> @@ -181,7 +182,7 @@ export default { }, isSelectableMsg() { - return !['tag', 'top', 'todo', 'notice'].includes(this.source.type); + return !['tag', 'top', 'todo', 'notice', 'word-chain', 'vote', 'template'].includes(this.source.type); }, classArray() { @@ -323,6 +324,10 @@ export default { this.dispatch("on-show-emoji-user", data) }, + onMergeForwardDetail(data) { + this.dispatch("on-merge-forward-detail", data) + }, + dispatch(event, ...arg) { if (this.isReply) { this.$emit(event, ...arg) diff --git a/resources/assets/js/pages/manage/components/DialogView/index.vue b/resources/assets/js/pages/manage/components/DialogView/index.vue index 4c57c1b70..06c7be24b 100644 --- a/resources/assets/js/pages/manage/components/DialogView/index.vue +++ b/resources/assets/js/pages/manage/components/DialogView/index.vue @@ -44,7 +44,7 @@ - + @@ -592,6 +592,10 @@ export default { this.$emit("on-show-emoji-user", item) }, + onMergeForwardDetail(msg) { + this.$emit("on-merge-forward-detail", {msgId: this.msgData.id, msgData: msg}) + }, + sortEmojiUser(useris) { const myList = useris.filter(item => item == this.userId); const otherList = useris.filter(item => item != this.userId); diff --git a/resources/assets/js/pages/manage/components/DialogView/merge-forward.vue b/resources/assets/js/pages/manage/components/DialogView/merge-forward.vue index d97fdeb4c..f6fd8103a 100644 --- a/resources/assets/js/pages/manage/components/DialogView/merge-forward.vue +++ b/resources/assets/js/pages/manage/components/DialogView/merge-forward.vue @@ -1,6 +1,6 @@ - {{ msg.title }} + {{ mergeTitle }} @@ -8,44 +8,7 @@ - - - - - - - - - - - - {{ item.created_at }} - - - - - - - [{{ $L('文件') }}] {{ item.msg.name }} - - - [{{ $L('聊天记录') }}] {{ item.msg.title }} - - - - - - - - - - + @@ -58,20 +21,17 @@ export default { default: () => ({}) } }, - data() { - return { - detailShow: false - } - }, computed: { displayList() { - if (!this.msg || !this.msg.list) return []; - return this.msg.list.slice(0, 4); + return this.msg?.preview || []; + }, + mergeTitle() { + return $A.getMergeForwardTitle(this.msg); } }, methods: { openDetail() { - this.detailShow = true; + this.$emit("on-view-detail", this.msg); } } } diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 0d9d6adc2..fe56920d3 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -220,6 +220,7 @@ @on-emoji="onEmoji" @on-other="onOther" @on-show-emoji-user="onShowEmojiUser" + @on-merge-forward-detail="onMergeForwardDetail" @on-multi-select-toggle="onMultiSelectToggle"> @@ -233,9 +234,9 @@ - + - {{ $L('已选') }} {{ selectedMsgIds.length }} {{ $L('条') }} + {{ $L('已选(*)条', selectedMsgIds.length) }} {{ $L('(最多100条)') }} @@ -245,7 +246,7 @@ -