feat: 优化 AI 生成交互体验

- 移除不必要的 loading 状态,简化用户交互
- 在项目和任务生成中添加取消功能,提升用户体验
- 更新相关组件以支持取消操作,确保生成过程的灵活性
This commit is contained in:
kuaifan 2025-09-23 14:41:34 +08:00
parent 7f6abc331b
commit 5fd2505a33
3 changed files with 49 additions and 19 deletions

View File

@ -250,7 +250,6 @@
<div
class="project-ai-button"
type="text"
:loading="projectAiLoading"
@click="onProjectAI">
<i class="taskfont">&#xe8a1;</i>
</div>
@ -464,7 +463,6 @@ export default {
columns: '',
flow: 'open',
},
projectAiLoading: false,
addRule: {
name: [
{ required: true, message: this.$L('请填写项目名称!'), trigger: 'change' },
@ -999,7 +997,6 @@ export default {
onAddShow() {
this.$store.dispatch("getColumnTemplate").catch(() => {})
this.projectAiLoading = false;
this.addShow = true;
this.$nextTick(() => {
this.$refs.projectName.focus();
@ -1007,9 +1004,7 @@ export default {
},
onProjectAI() {
if (this.projectAiLoading) {
return;
}
let canceled = false;
$A.modalInput({
title: 'AI 生成',
placeholder: '请简要描述项目目标、范围或关键里程碑AI 将生成名称和任务列表',
@ -1019,12 +1014,18 @@ export default {
autosize: {minRows: 2, maxRows: 6},
maxlength: 500,
},
onCancel: () => {
canceled = true;
},
onOk: (value) => {
if (!value) {
return '请输入项目需求';
}
return new Promise((resolve, reject) => {
this.projectAiLoading = true;
if (canceled) {
reject();
return;
}
const parseColumns = (cols) => {
if (Array.isArray(cols)) {
return cols;
@ -1042,10 +1043,6 @@ export default {
columns: parseColumns(item.columns)
}));
const finish = () => {
this.projectAiLoading = false;
};
this.$store.dispatch("call", {
url: 'project/ai/generate',
data: {
@ -1056,6 +1053,10 @@ export default {
},
timeout: 45 * 1000,
}).then(({data}) => {
if (canceled) {
resolve();
return;
}
const columns = Array.isArray(data.columns) ? data.columns : parseColumns(data.columns);
this.$set(this.addData, 'name', data.name || '');
this.$set(this.addData, 'columns', columns.length > 0 ? columns.join(',') : '');
@ -1064,10 +1065,12 @@ export default {
this.$refs.projectName.focus();
}
});
finish();
resolve();
}).catch(({msg}) => {
finish();
if (canceled) {
resolve();
return;
}
reject(msg);
});
});

View File

@ -433,8 +433,6 @@ export default {
showMore: false,
showEmoji: false,
chatAiLoading: false,
emojiQuickShow: false,
emojiQuickKey: '',
emojiQuickItems: [],
@ -1823,13 +1821,14 @@ export default {
},
onMessageAI() {
if (this.disabled || this.chatAiLoading) {
if (this.disabled) {
return;
}
if (!this.dialogId) {
$A.messageWarning(this.$L('当前未选择会话'));
return;
}
let canceled = false;
$A.modalInput({
title: 'AI 生成',
placeholder: '请简要描述消息的主题、语气或要点AI 将生成完整消息',
@ -1839,12 +1838,18 @@ export default {
autosize: {minRows: 2, maxRows: 6},
maxlength: 500,
},
onCancel: () => {
canceled = true;
},
onOk: (value) => {
if (!value) {
return '请输入消息需求';
}
return new Promise((resolve, reject) => {
this.chatAiLoading = true;
if (canceled) {
reject();
return;
}
this.$store.dispatch('call', {
url: 'dialog/msg/ai_generate',
data: {
@ -1856,6 +1861,10 @@ export default {
timeout: 45 * 1000,
}).then(({data}) => {
const html = data && (data.html || data.text) ? (data.html || data.text) : '';
if (canceled) {
resolve();
return;
}
if (!html) {
reject(this.$L('AI 未生成内容'));
return;
@ -1864,9 +1873,11 @@ export default {
this.$nextTick(() => this.focus());
resolve();
}).catch(({msg}) => {
if (canceled) {
resolve();
return;
}
reject(msg);
}).finally(() => {
this.chatAiLoading = false;
});
});
}

View File

@ -625,6 +625,7 @@ export default {
},
onAI() {
let canceled = false;
$A.modalInput({
title: 'AI 生成',
placeholder: '请简要描述任务目标、背景或预期交付AI 将生成标题、详细说明和子任务',
@ -634,11 +635,18 @@ export default {
autosize: { minRows: 2, maxRows: 6 },
maxlength: 500,
},
onCancel: () => {
canceled = true;
},
onOk: (value) => {
if (!value) {
return `请输入任务描述`
}
return new Promise((resolve, reject) => {
if (canceled) {
reject();
return;
}
//
const currentTemplate = this.templateActiveID ?
this.taskTemplateList.find(item => item.id === this.templateActiveID) : null;
@ -660,6 +668,10 @@ export default {
},
timeout: 60 * 1000,
}).then(({data}) => {
if (canceled) {
resolve();
return;
}
this.addData.name = data.title;
this.$refs.editorTaskRef.setContent(data.content, {format: 'raw'});
if (Array.isArray(data.subtasks) && data.subtasks.length > 0) {
@ -695,6 +707,10 @@ export default {
}
resolve();
}).catch(({msg}) => {
if (canceled) {
resolve();
return;
}
reject(msg);
});
})