feat(ask-user): 弹窗新增「不回答」选项
- 弹窗 footer 新增「✕ 不回答」按钮,只跳过当前查看的问题, 其余问题保持待回答 - 后端 answer() 支持 dismissed 类型答案,跳过非空校验 - 模型侧工具结果返回「用户没有回答或不想回答这个问题, 请直接输出内容向用户提问」,引导模型改为在对话中提问
This commit is contained in:
parent
1cd3a742af
commit
045cc72c43
@ -105,10 +105,11 @@ class UserQuestionManager:
|
||||
username: str,
|
||||
selected_option_id: Optional[str] = None,
|
||||
text: Optional[str] = None,
|
||||
dismissed: bool = False,
|
||||
) -> Dict[str, Any]:
|
||||
clean_option_id = str(selected_option_id or "").strip()
|
||||
clean_text = str(text or "").strip()
|
||||
if not clean_option_id and not clean_text:
|
||||
if not dismissed and not clean_option_id and not clean_text:
|
||||
raise ValueError("回答不能为空")
|
||||
with self._lock:
|
||||
item = self._items.get(question_id)
|
||||
@ -119,6 +120,13 @@ class UserQuestionManager:
|
||||
if item.get("status") != "pending":
|
||||
return dict(item)
|
||||
|
||||
# 用户主动选择不回答:标记为 dismissed,工具结果会提示模型改为在对话中提问
|
||||
if dismissed:
|
||||
item["status"] = "answered"
|
||||
item["answered_at"] = time.time()
|
||||
item["answer"] = {"type": "dismissed", "text": ""}
|
||||
return dict(item)
|
||||
|
||||
selected_option = None
|
||||
if clean_option_id:
|
||||
for opt in item.get("options") or []:
|
||||
@ -152,6 +160,8 @@ def format_user_question_answer(item: Dict[str, Any]) -> str:
|
||||
answer = item.get("answer") if isinstance(item, dict) else None
|
||||
if not isinstance(answer, dict):
|
||||
return "用户未回答。"
|
||||
if answer.get("type") == "dismissed":
|
||||
return "用户没有回答或不想回答这个问题,请直接输出内容向用户提问"
|
||||
lines: List[str] = []
|
||||
label = str(answer.get("selected_option_label") or "").strip()
|
||||
text = str(answer.get("text") or "").strip()
|
||||
|
||||
@ -72,6 +72,7 @@ def answer_user_question(terminal: WebTerminal, workspace: UserWorkspace, userna
|
||||
username=username,
|
||||
selected_option_id=data.get("selected_option_id"),
|
||||
text=data.get("text"),
|
||||
dismissed=bool(data.get("dismissed")),
|
||||
)
|
||||
except ValueError as exc:
|
||||
return jsonify({"success": False, "error": str(exc)}), 400
|
||||
|
||||
@ -520,6 +520,7 @@
|
||||
@minimize="minimizeUserQuestionDialog"
|
||||
@update:active-index="userQuestionActiveIndex = $event"
|
||||
@submit="submitUserQuestionAnswers"
|
||||
@dismiss="dismissUserQuestions"
|
||||
/>
|
||||
<transition name="overlay-fade">
|
||||
<VersioningDialog
|
||||
|
||||
@ -144,7 +144,8 @@ export const dialogMethods = {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
selected_option_id: answer?.selected_option_id || undefined,
|
||||
text: answer?.text || ''
|
||||
text: answer?.text || '',
|
||||
dismissed: answer?.dismissed === true
|
||||
})
|
||||
});
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
@ -172,6 +173,15 @@ export const dialogMethods = {
|
||||
this.answeringUserQuestionIds = [];
|
||||
}
|
||||
},
|
||||
// 用户点击「不回答」:只将当前查看的这个问题标记为 dismissed,其余问题保持待回答。
|
||||
// 模型侧会收到「用户没有回答或不想回答」的工具结果并改为在对话中直接提问。
|
||||
async dismissUserQuestions(questionId) {
|
||||
const id = String(questionId || '').trim();
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
await this.submitUserQuestionAnswers([{ question_id: id, dismissed: true }]);
|
||||
},
|
||||
async answerUserQuestionFromComposer(text) {
|
||||
const clean = String(text || '').trim();
|
||||
if (!clean || !Array.isArray(this.pendingUserQuestions) || !this.pendingUserQuestions.length) {
|
||||
|
||||
@ -57,6 +57,15 @@
|
||||
</div>
|
||||
|
||||
<footer class="user-question-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="user-question-btn ghost"
|
||||
:disabled="submitting"
|
||||
title="不回答当前这个问题,AI 将改为在对话中直接提问"
|
||||
@click="dismiss"
|
||||
>
|
||||
✕ 不回答
|
||||
</button>
|
||||
<div class="user-question-spacer"></div>
|
||||
<div class="user-question-actions">
|
||||
<button type="button" class="user-question-btn primary" :disabled="!canSubmit || submitting" @click="submit">
|
||||
@ -83,6 +92,7 @@ const emit = defineEmits<{
|
||||
(event: 'minimize'): void;
|
||||
(event: 'update:active-index', value: number): void;
|
||||
(event: 'submit', answers: Array<any>): void;
|
||||
(event: 'dismiss', questionId: string): void;
|
||||
}>();
|
||||
|
||||
const drafts = reactive<Record<string, { selected_option_id: string; text: string }>>({});
|
||||
@ -142,6 +152,14 @@ function submit() {
|
||||
});
|
||||
emit('submit', answers);
|
||||
}
|
||||
|
||||
// 只跳过当前查看的问题,其余问题保持待回答
|
||||
function dismiss() {
|
||||
if (submitting.value) return;
|
||||
const questionId = String(currentQuestion.value?.question_id || '').trim();
|
||||
if (!questionId) return;
|
||||
emit('dismiss', questionId);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user