feat: govern knowledge assets and source citations
This commit is contained in:
@@ -131,7 +131,7 @@
|
||||
:loading="reviewingFeedbackId === row.id"
|
||||
@click="markFeedbackReviewed(row)"
|
||||
>
|
||||
标记已复核
|
||||
处理争议
|
||||
</el-button>
|
||||
<span v-else class="review-done">已复核</span>
|
||||
</template>
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
<script setup name="KnowledgeSop" lang="ts">
|
||||
import { DocumentChecked, Reading, Tickets, Upload } from '@element-plus/icons-vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import type { UploadFile } from 'element-plus';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -309,7 +309,7 @@ const apiPill = computed(() => {
|
||||
const flowStatus = computed(() => {
|
||||
if (trainingGenerated.value) return { label: '已完成闭环', type: 'pill-success' };
|
||||
if (searched.value) return { label: `已命中 ${snippets.value.length} 段`, type: 'pill-primary' };
|
||||
return { label: '可引用 SOP 内容', type: 'pill-success' };
|
||||
return { label: '演示内容预览', type: 'pill-warning' };
|
||||
});
|
||||
const canReview = computed(() => apiMode.value === 'api' && Boolean(apiResult.value?.reviewId));
|
||||
const reviewMessage = computed(() => {
|
||||
@@ -323,7 +323,7 @@ const seedRecords = [
|
||||
title: '投诉处理 SOP v1.0',
|
||||
category: '投诉处理',
|
||||
version: 'v1.0',
|
||||
status: '已入库',
|
||||
status: '演示数据',
|
||||
owner: '品质组',
|
||||
summary: '业主投诉的接待、记录、派单、反馈和闭环确认。',
|
||||
source: 'demo'
|
||||
@@ -332,7 +332,7 @@ const seedRecords = [
|
||||
title: '催缴沟通 SOP v1.0',
|
||||
category: '催缴沟通',
|
||||
version: 'v1.0',
|
||||
status: '已入库',
|
||||
status: '演示数据',
|
||||
owner: '财务组',
|
||||
summary: '缴费提醒、费用争议回应、服务问题承接。',
|
||||
source: 'demo'
|
||||
@@ -423,13 +423,43 @@ async function loadPendingReviews() {
|
||||
}
|
||||
|
||||
async function markFeedbackReviewed(row: AnswerFeedbackItem) {
|
||||
reviewingFeedbackId.value = row.id;
|
||||
try {
|
||||
await reviewAnswerFeedback(row.id);
|
||||
let reviewAction: 'KEEP' | 'WITHDRAW';
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'保留资料表示该来源经核对仍可用;撤回来源会立即停止 MySQL 检索,并排队清除向量。',
|
||||
'处理答案争议',
|
||||
{
|
||||
confirmButtonText: '保留资料',
|
||||
cancelButtonText: '撤回来源',
|
||||
distinguishCancelAndClose: true,
|
||||
type: 'warning'
|
||||
}
|
||||
);
|
||||
reviewAction = 'KEEP';
|
||||
} catch (choice) {
|
||||
if (choice === 'close') return;
|
||||
reviewAction = 'WITHDRAW';
|
||||
}
|
||||
const { value: note } = await ElMessageBox.prompt(
|
||||
'选择“保留资料”表示该来源经核对仍可用;选择“撤回来源”会立即停止 MySQL 检索,并排队清除向量。',
|
||||
reviewAction === 'KEEP' ? '填写保留依据' : '填写撤回原因',
|
||||
{
|
||||
confirmButtonText: '提交复核',
|
||||
cancelButtonText: '取消',
|
||||
inputPlaceholder: '填写复核依据或撤回原因',
|
||||
inputValidator: (input) => Boolean(input?.trim()) || '请填写复核结论'
|
||||
}
|
||||
);
|
||||
reviewingFeedbackId.value = row.id;
|
||||
await reviewAnswerFeedback(row.id, {
|
||||
action: reviewAction,
|
||||
note: note.trim()
|
||||
});
|
||||
pendingReviews.value = pendingReviews.value.filter((item) => item.id !== row.id);
|
||||
ElMessage.success('答案已标记为已复核');
|
||||
} catch {
|
||||
ElMessage.error('答案复核失败');
|
||||
ElMessage.success(reviewAction === 'KEEP' ? '已记录保留依据' : '来源已撤回并进入索引清理队列');
|
||||
} catch (error) {
|
||||
if (error !== 'cancel' && error !== 'close') ElMessage.error('答案复核失败');
|
||||
} finally {
|
||||
reviewingFeedbackId.value = null;
|
||||
}
|
||||
@@ -461,14 +491,13 @@ async function handleDocSelected(uploadFile: UploadFile) {
|
||||
title: data.fileName,
|
||||
category: data.category.replace(' SOP', ''),
|
||||
version: '上传',
|
||||
status: '已入库',
|
||||
status: '待审核',
|
||||
owner: 'MinIO',
|
||||
summary: `OSS #${data.ossId},已解析 ${data.fragments} 个片段`,
|
||||
summary: `OSS #${data.ossId},已生成 ${data.fragments} 个候选片段,批准前不可检索`,
|
||||
source: 'uploaded'
|
||||
});
|
||||
queryText.value = data.snippets[0]?.text.slice(0, 40) || queryText.value;
|
||||
ElMessage.success(`已入库 ${data.fragments} 个片段`);
|
||||
await runSearch();
|
||||
ElMessage.success(`已提交审核,共 ${data.fragments} 个候选片段`);
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user