feat(aihr): close functional checklist gaps

This commit is contained in:
key
2026-08-02 12:15:45 +08:00
parent 699cc08050
commit 6ad8a017a4
80 changed files with 4930 additions and 430 deletions
+74 -4
View File
@@ -113,10 +113,14 @@
</button>
</view>
<view
v-if="(msg.voiceStatus === 'unavailable' || msg.transcriptOpen) && (msg.result.answer || msg.result.snippets?.length || !msg.result.memoryCandidate)"
class="bubble master transcript-bubble"
>
<view
v-if="(msg.voiceStatus === 'unavailable' || msg.transcriptOpen) && (msg.result.answer || msg.result.snippets?.length || !msg.result.memoryCandidate)"
class="bubble master transcript-bubble"
>
<view class="answer-evidence-label">
<uni-icons type="info" size="13" color="#2f6bff" />
<text>AI 参考回答 · 下方引用为原文证据</text>
</view>
<text
v-if="msg.result.rewrittenQuery && msg.result.rewrittenQuery !== msg.result.queryText"
class="context-used"
@@ -186,6 +190,19 @@
<text v-if="msg.feedbackVerdict" class="feedback-note">
{{ msg.feedbackVerdict === 'up' ? '已记录' : '已进入复核' }}
</text>
<button
v-if="msg.feedbackVerdict === 'down' && !msg.helpQuestionId"
class="bubble-action primary"
:disabled="msg.helpSubmitting || !msg.result.requestId"
@click="submitHumanHelp(msg)"
>
{{ msg.helpSubmitting ? '提交中' : '转人工求助' }}
</button>
<button
v-if="msg.helpQuestionId"
class="bubble-action"
@click="openHelpQuestion(msg.helpQuestionId)"
>查看待审核问题</button>
</view>
<view v-if="msg.feedbackPanelOpen && !msg.feedbackVerdict" class="negative-feedback-panel">
<text class="negative-feedback-title">哪里还没解决?(可多选)</text>
@@ -473,6 +490,7 @@ import { chooseSpeechAudio, createSpeechPlaybackController, measureAudioDuration
import { isNativeAppRuntime, type SpeechCapture } from '@/services/speech-capture';
import { downloadSummaryCardImage } from '@/services/summary-card-image';
import { getMemoryCandidates } from '@/services/personal-assistant';
import { publishQuestionFromAnswerFeedback } from '@/services/questions';
import { currentAccountKey } from '@/services/request-scope';
import { isFileSelectionCancelled } from '@/utils/file-selection';
import {
@@ -504,6 +522,9 @@ interface MasterMsg {
feedbackPanelOpen: boolean;
feedbackReasonCodes: string[];
feedbackComment: string;
helpSubmitting: boolean;
helpQuestionId: number | null;
helpIdempotencyKey: string;
citationsOpen: boolean;
voiceStatus: 'preparing' | 'ready' | 'unavailable';
voiceDuration: number | null;
@@ -1023,6 +1044,9 @@ const sendQuestion = async (
feedbackPanelOpen: false,
feedbackReasonCodes: [],
feedbackComment: '',
helpSubmitting: false,
helpQuestionId: null,
helpIdempotencyKey: '',
citationsOpen: false,
voiceStatus: shouldPreloadVoice ? 'preparing' : 'unavailable',
voiceDuration: null,
@@ -1403,6 +1427,42 @@ const feedback = async (verdict: AnswerFeedbackVerdict, msg: MasterMsg) => {
}
};
const confirmHumanHelp = () => new Promise<boolean>((resolve) => {
uni.showModal({
title: '提交人工求助',
content: '将使用你刚才的问题创建问题榜条目。审核通过后其他员工可见,请确认问题中不含住户姓名、电话、房号等隐私信息。',
confirmText: '确认提交',
cancelText: '暂不提交',
success: (result) => resolve(Boolean(result.confirm)),
fail: () => resolve(false)
});
});
const submitHumanHelp = async (msg: MasterMsg) => {
if (msg.helpSubmitting || msg.helpQuestionId || !msg.result.requestId) return;
if (!await confirmHumanHelp()) return;
msg.helpSubmitting = true;
if (!msg.helpIdempotencyKey) {
msg.helpIdempotencyKey = `feedback-help-${createConversationId()}`;
}
try {
const question = await publishQuestionFromAnswerFeedback({
requestId: msg.result.requestId,
idempotencyKey: msg.helpIdempotencyKey
});
msg.helpQuestionId = question.id;
uni.showToast({ title: '已提交审核', icon: 'none' });
} catch (error) {
uni.showToast({ title: requestErrorText(error, '人工求助提交失败'), icon: 'none' });
} finally {
msg.helpSubmitting = false;
}
};
const openHelpQuestion = (questionId: number) => {
uni.navigateTo({ url: `/pages/user/questions/detail?id=${questionId}` });
};
const buildSummaryCard = async (msg: MasterMsg) => {
if (broadcastContext.value) {
uni.showToast({ title: '消息咨询不支持生成总结卡,请先结束咨询', icon: 'none' });
@@ -3286,6 +3346,16 @@ onUnload(() => {
background: #fafbfc;
}
.answer-evidence-label {
display: flex;
align-items: center;
gap: 5px;
color: #2f6bff;
font-size: 12px;
font-weight: 700;
line-height: 1.4;
}
.citation-action {
box-sizing: border-box;
width: 100%;