feat: 添加会话重命名功能

- 在 DialogController 中新增 session__rename 方法,支持用户重命名会话
- 更新前端组件 DialogSessionHistory.vue,添加重命名按钮及相关逻辑
- 修改样式以支持重命名功能的交互效果
- 优化用户体验,确保重命名操作的流畅性
This commit is contained in:
kuaifan 2025-09-24 18:39:25 +08:00
parent a268391e68
commit 4b45d5ca26
3 changed files with 166 additions and 5 deletions

View File

@ -5,6 +5,7 @@ namespace App\Http\Controllers\Api;
use DB;
use Request;
use Redirect;
use Cache;
use Carbon\Carbon;
use App\Tasks\PushTask;
use App\Module\AI;
@ -3600,4 +3601,51 @@ class DialogController extends AbstractController
//
return Base::retSuccess('success', $session);
}
/**
* @api {post} api/dialog/session/rename 69. AI-重命名会话
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName session_rename
*
* @apiParam {Number} session_id 会话ID
* @apiParam {String} title 会话名称
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function session__rename()
{
User::auth();
//
$session_id = intval(Request::input('session_id'));
$title = trim((string)Request::input('title'));
//
if ($session_id <= 0) {
return Base::retError('参数错误');
}
if ($title === '') {
return Base::retError('请输入会话名称');
}
//
$session = WebSocketDialogSession::whereId($session_id)->first();
if (empty($session)) {
return Base::retError('会话不存在或已被删除');
}
//
$dialog = WebSocketDialog::checkDialog($session->dialog_id);
if (!$dialog->isSessionDialog()) {
return Base::retError('当前对话不支持');
}
//
$session->title = Base::cutStr($title, 100);
$session->save();
$session->refresh();
Cache::forever('dialog_session_title_' . $session->id, true);
//
return Base::retSuccess('重命名成功', $session);
}
}

View File

@ -10,8 +10,17 @@
<div class="history-title">
<div v-if="openIng == item.id" class="history-load"><Loading/></div><em v-if="item.is_open">{{$L('当前')}}</em>{{item.title || $L('新会话')}}
</div>
<div class="history-time" :title="item.created_at">
{{$A.timeFormat(item.created_at)}}
<div class="history-meta">
<div v-if="renameIng === item.id" class="history-rename-load"><Loading/></div>
<Icon
v-else
class="history-rename"
type="ios-create-outline"
:title="$L('重命名')"
@click.stop="onRename(item)"/>
<div class="history-time" :title="item.created_at">
{{$A.timeFormat(item.created_at)}}
</div>
</div>
</li>
</ul>
@ -42,6 +51,7 @@ export default {
listLoad: 0,
listCurrentPage: 1,
listHasMorePages: false,
renameIng: 0,
}
},
@ -120,6 +130,52 @@ export default {
}).finally(_ => {
this.openIng = 0;
});
},
onRename(item) {
if (this.renameIng > 0) {
return
}
const placeholder = this.$L('请输入会话名称')
$A.modalInput({
title: this.$L('重命名会话'),
placeholder,
value: item.title,
onOk: (value) => {
const name = (value || '').trim()
if (!name) {
return placeholder
}
if (name === (item.title || '')) {
return false
}
return this.renameSession(item, name)
}
})
},
renameSession(item, name) {
this.renameIng = item.id
return new Promise((resolve, reject) => {
this.$store.dispatch("call", {
url: "dialog/session/rename",
method: 'post',
data: {
session_id: item.id,
title: name,
}
}).then(({data, msg}) => {
this.$set(item, 'title', data.title)
if (typeof data.updated_at !== 'undefined') {
this.$set(item, 'updated_at', data.updated_at)
}
resolve(msg)
}).catch(({msg}) => {
reject(msg)
}).finally(() => {
this.renameIng = 0
})
})
}
}
}

View File

@ -84,10 +84,50 @@
}
}
.history-time {
.history-meta {
float: right;
opacity: 0.5;
font-size: 13px;
display: flex;
align-items: center;
.history-rename {
font-size: 18px;
color: #999;
cursor: pointer;
margin-right: 8px;
opacity: 0;
pointer-events: none;
transition: color 0.2s, opacity 0.2s;
&:hover {
color: $primary-desc-color;
}
}
.history-rename-load {
width: 16px;
height: 16px;
margin-right: 8px;
.common-loading {
width: 16px;
height: 16px;
}
}
.history-time {
opacity: 0.5;
font-size: 13px;
}
}
&:hover,
&:focus-within {
.history-meta {
.history-rename {
opacity: 1;
pointer-events: auto;
}
}
}
}
}
@ -106,6 +146,23 @@
}
}
@media (pointer: coarse) {
.dialog-session-history {
.session-history-list {
ul {
> li {
.history-meta {
.history-rename {
opacity: 1;
pointer-events: auto;
}
}
}
}
}
}
}
body.window-portrait {
.dialog-session-history {
.session-history-list {