Merge branch 'codex/personal-assistant-phase2' into codex/multi-tenant-knowledge-platform
# Conflicts: # backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/domain/AihrSopDto.java # backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrModelSeedService.java # backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java # backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrModelSeedServiceTest.java # backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrSopSeedServiceTest.java # docs/API_INTEGRATION.md # docs/个人AI助理阶段二专项TechSpec.md # docs/个人AI助理阶段二开发推进计划.md # frontend/src/views/knowledge/processing.vue # mobile-uni/src/pages/user/sop/index.vue # mobile-uni/src/services/api.ts # mobile-uni/src/services/personal-assistant.ts # mobile-uni/tests/personal-assistant.test.mjs # scripts/demo-check.sh # scripts/personal-assistant-smoke.sh
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
export interface PersonalPublishRequestRow {
|
||||
id: string;
|
||||
itemId: string;
|
||||
title: string;
|
||||
sourceType: string;
|
||||
targetScope: string;
|
||||
reason: string;
|
||||
sanitizedPreview?: string;
|
||||
status: 'PENDING' | 'APPROVED' | 'REJECTED';
|
||||
reviewComment?: string;
|
||||
publishedKnowledgeId?: string;
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
export const listPersonalPublishRequests = () =>
|
||||
request<PersonalPublishRequestRow[]>({
|
||||
url: '/api/aihr/personal-assistant/admin/publish-requests',
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
export const reviewPersonalPublishRequest = (id: string, payload: { approved: boolean; comment: string }) =>
|
||||
request<PersonalPublishRequestRow>({
|
||||
url: `/api/aihr/personal-assistant/admin/publish-requests/${encodeURIComponent(id)}/review`,
|
||||
method: 'post',
|
||||
data: payload
|
||||
});
|
||||
@@ -233,16 +233,37 @@
|
||||
<el-table-column prop="detail" label="详情" min-width="260" />
|
||||
</el-table>
|
||||
</section>
|
||||
|
||||
<section class="panel event-panel">
|
||||
<div class="panel-title compact">
|
||||
<h2>个人资料入库审核</h2>
|
||||
<el-button link :loading="publishLoading" @click="loadPublishRequests">刷新</el-button>
|
||||
</div>
|
||||
<el-table :data="publishRequests" size="small" empty-text="暂无待审核申请">
|
||||
<el-table-column prop="title" label="资料" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="sourceType" label="来源" width="90" />
|
||||
<el-table-column prop="targetScope" label="目标范围" min-width="140" />
|
||||
<el-table-column prop="reason" label="申请说明" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" width="90" />
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.status === 'PENDING'" link type="success" @click="reviewPublish(row, true)">批准</el-button>
|
||||
<el-button v-if="row.status === 'PENDING'" link type="danger" @click="reviewPublish(row, false)">驳回</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="KnowledgeProcessing" lang="ts">
|
||||
import { CircleCheck, Document, Files, Operation, Refresh, Search, Upload, WarningFilled } from '@element-plus/icons-vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { getProcessingOverview, type ProcessingOverview, type ProcessingTask } from '@/api/aihr/processing';
|
||||
import { uploadKnowledgeDocAsync, listUploadItems, retryUploadItem, type UploadItem } from '@/api/aihr/sop';
|
||||
import { listKnowledgeSpaces, type KnowledgeSpace } from '@/api/aihr/space';
|
||||
import { listPersonalPublishRequests, reviewPersonalPublishRequest, type PersonalPublishRequestRow } from '@/api/aihr/personal';
|
||||
|
||||
const acceptTypes = '.txt,.md,.markdown,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.jpg,.jpeg,.png,.gif,.webp,.bmp,.mp4,.mov,.avi,.mkv,.webm,.m4v,.zip';
|
||||
const supportedPattern = /\.(txt|md|markdown|pdf|doc|docx|xls|xlsx|ppt|pptx|jpg|jpeg|png|gif|webp|bmp|mp4|mov|avi|mkv|webm|m4v|zip)$/i;
|
||||
@@ -257,6 +278,8 @@ const browserBatchWarnSize = 200 * 1024 * 1024;
|
||||
const fileInput = ref<HTMLInputElement>();
|
||||
const loading = ref(false);
|
||||
const uploading = ref(false);
|
||||
const publishLoading = ref(false);
|
||||
const publishRequests = ref<PersonalPublishRequestRow[]>([]);
|
||||
const overview = ref<ProcessingOverview | null>(null);
|
||||
const overviewFailed = ref(false);
|
||||
const categoryKeyword = ref('');
|
||||
@@ -411,9 +434,33 @@ const pagedTasks = computed(() => {
|
||||
return filteredTasks.value.slice(start, start + taskPageSize.value);
|
||||
});
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadOverview(), loadManageableSpaces()]);
|
||||
await Promise.all([loadOverview(), loadManageableSpaces(), loadPublishRequests()]);
|
||||
});
|
||||
|
||||
async function loadPublishRequests() {
|
||||
publishLoading.value = true;
|
||||
try {
|
||||
publishRequests.value = (await listPersonalPublishRequests()).data || [];
|
||||
} catch {
|
||||
publishRequests.value = [];
|
||||
} finally {
|
||||
publishLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function reviewPublish(row: PersonalPublishRequestRow, approved: boolean) {
|
||||
try {
|
||||
const { value } = await ElMessageBox.prompt(approved ? '填写批准意见' : '填写驳回原因', approved ? '批准入库' : '驳回入库', {
|
||||
inputValidator: (input) => Boolean(input?.trim()) || '请填写审核意见'
|
||||
});
|
||||
await reviewPersonalPublishRequest(row.id, { approved, comment: value.trim() });
|
||||
ElMessage.success(approved ? '已批准' : '已驳回');
|
||||
await loadPublishRequests();
|
||||
} catch (error) {
|
||||
if (error !== 'cancel' && error !== 'close') ElMessage.error('审核失败,请重试');
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
clearBatchPoll();
|
||||
// 置空批次 ID,让在途的轮询请求返回后直接丢弃,不再重新挂起定时器
|
||||
|
||||
Reference in New Issue
Block a user