feat: 新增转发至AI开启新会话

This commit is contained in:
kuaifan 2025-04-07 01:20:58 +08:00
parent d144b06c1f
commit c5948c4171
3 changed files with 110 additions and 40 deletions

View File

@ -3183,6 +3183,7 @@ class DialogController extends AbstractController
* @apiName session_create * @apiName session_create
* *
* @apiParam {Number} dialog_id 对话ID * @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} [userid] 用户ID dialog_id 二选一userid 优先)
* *
* @apiSuccess {Number} ret 返回状态码1正确、0错误 * @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {String} msg 返回信息(错误描述)
@ -3190,11 +3191,16 @@ class DialogController extends AbstractController
*/ */
public function session__create() public function session__create()
{ {
User::auth(); $user = User::auth();
// //
$dialog_id = intval(Request::input('dialog_id')); $dialog_id = intval(Request::input('dialog_id'));
$userid = intval(Request::input('userid'));
// //
$dialog = WebSocketDialog::checkDialog($dialog_id); if ($userid) {
$dialog = WebSocketDialog::checkUserDialog($user, $userid);
} else {
$dialog = WebSocketDialog::checkDialog($dialog_id);
}
// //
if ($dialog->type != 'user') { if ($dialog->type != 'user') {
return Base::retError('当前对话不支持'); return Base::retError('当前对话不支持');
@ -3208,9 +3214,7 @@ class DialogController extends AbstractController
return Base::retError('当前对话不支持'); return Base::retError('当前对话不支持');
} }
// //
$session = WebSocketDialogSession::whereDialogId($dialog->id) $session = WebSocketDialogSession::whereDialogId($dialog->id)->whereTitle('')->first();
->whereTitle('')
->first();
if ($session) { if ($session) {
$dialog->session_id = $session->id; $dialog->session_id = $session->id;
$dialog->save(); $dialog->save();

View File

@ -61,13 +61,19 @@
:disabled="loading" :disabled="loading"
clearable/> clearable/>
</div> </div>
<ul class="radio-group">
<li v-if="aiUser.length > 0" :class="{selected: ainew}">
<Icon @click="onAinew" class="radio-icon" :type="ainew ? 'ios-checkmark-circle' : 'ios-radio-button-off'"/>
<span class="radio-label">{{ $L('AI开启新会话') }}</span>
</li>
<li v-if="!senderHidden" :class="{selected: !sender}">
<Icon @click="onSender" class="radio-icon" :type="sender ? 'ios-radio-button-off' : 'ios-checkmark-circle'"/>
<span class="radio-label">{{ $L('不显示原发送者信息') }}</span>
</li>
</ul>
</div> </div>
</div> </div>
<template #footer> <template #footer>
<div v-if="!senderHidden" class="forwarder-wrapper-footer" :class="{selected: !sender}" @click="onSender">
<Icon class="user-modal-icon" :type="sender ? 'ios-radio-button-off' : 'ios-checkmark-circle'" />
<span class="forward-text-tip">{{$L('不显示原发送者信息')}}</span>
</div>
<Button type="primary" :loading="loading" @click="onSubmit"> <Button type="primary" :loading="loading" @click="onSubmit">
{{$L('确定')}} {{$L('确定')}}
<template v-if="forwardTo.length > 0">({{forwardTo.length}})</template> <template v-if="forwardTo.length > 0">({{forwardTo.length}})</template>
@ -79,6 +85,7 @@
<script> <script>
import DialogItem from "../DialogItem.vue"; import DialogItem from "../DialogItem.vue";
import ChatInput from "../ChatInput/index.vue"; import ChatInput from "../ChatInput/index.vue";
import {mapState} from "vuex";
export default { export default {
components: {ChatInput, DialogItem}, components: {ChatInput, DialogItem},
@ -128,12 +135,21 @@ export default {
loading: false, loading: false,
message: '', // message: '', //
sender: true, // ainew: true, // AI
sender: true, //
} }
}, },
computed: { computed: {
...mapState(['cacheUserBasic']),
aiUser({forwardTo, cacheUserBasic}) {
const users = forwardTo.filter(item => item.type !== 'group');
return users.filter(user => {
const cachedUser = cacheUserBasic.find(item => item.userid === user.userid);
return cachedUser && cachedUser.bot && /^ai-(.*?)@bot\.system/.test(cachedUser.email);
});
}
}, },
watch: { watch: {
@ -145,6 +161,7 @@ export default {
if (!val) { if (!val) {
this.loading = false; this.loading = false;
this.message = ''; this.message = '';
this.ainew = true;
this.sender = true; this.sender = true;
} }
} }
@ -167,6 +184,13 @@ export default {
this.$emit('on-other', ...args); this.$emit('on-other', ...args);
}, },
onAinew() {
if (this.loading) {
return
}
this.ainew = !this.ainew
},
onSender() { onSender() {
if (this.loading) { if (this.loading) {
return return
@ -174,7 +198,7 @@ export default {
this.sender = !this.sender this.sender = !this.sender
}, },
onSubmit() { async onSubmit() {
if (this.loading) { if (this.loading) {
return return
} }
@ -188,9 +212,17 @@ export default {
if (!this.senderHidden) { if (!this.senderHidden) {
data.sender = this.sender data.sender = this.sender
} }
//
this.loading = true
try {
await this.onAiNew()
} catch (e) {
this.loading = false
return
}
//
const before = this.beforeSubmit(data); const before = this.beforeSubmit(data);
if (before && before.then) { if (before && before.then) {
this.loading = true
before.then(() => { before.then(() => {
this.hide() this.hide()
}).catch(_ => { }).catch(_ => {
@ -199,10 +231,41 @@ export default {
this.loading = false this.loading = false
}) })
} else { } else {
this.loading = false
this.hide() this.hide()
} }
}, },
onAiNew() {
return new Promise((resolve, reject) => {
if (this.aiUser.length === 0 || !this.ainew) {
return resolve();
}
const processQueue = async () => {
try {
for (const user of this.aiUser) {
await this.$store.dispatch("call", {
url: 'dialog/session/create',
data: {
userid: user.userid,
},
});
}
resolve();
} catch (error) {
$A.modalError({
language: false,
content: this.$L("AI开启新会话失败") + `: ${error.msg || error}`,
});
reject(error);
}
};
processQueue();
});
},
hide() { hide() {
this.show = false this.show = false
} }

View File

@ -88,39 +88,42 @@
background: #f7f7f7; background: #f7f7f7;
} }
} }
}
}
}
.ivu-modal-footer { .radio-group {
display: flex; z-index: 2;
justify-content: flex-end; display: flex;
gap: 20px; flex-direction: column;
.forwarder-wrapper-footer { > li {
flex: 1; display: flex;
width: 0; align-items: center;
display: flex; line-height: 22px;
line-height: 34px; margin-bottom: 8px;
cursor: pointer;
.user-modal-icon { .radio-icon {
flex-shrink: 0; flex-shrink: 0;
font-size: 22px; font-size: 22px;
margin-right: 5px; color: rgba($primary-desc-color, 0.7);
color: rgba($primary-desc-color, 0.7); cursor: pointer;
margin-top: 6px; }
}
.forward-text-tip { .radio-label {
overflow: hidden; padding-left: 6px;
text-overflow: ellipsis; overflow: hidden;
white-space: nowrap; text-overflow: ellipsis;
} white-space: nowrap;
}
&.selected { &.selected {
.user-modal-icon { .radio-icon {
color: $primary-color; color: $primary-color;
}
}
&:last-child {
margin-bottom: 16px;
}
}
} }
} }
} }