|
@@ -1,246 +1,446 @@
|
|
|
import * as React from 'react';
|
|
import * as React from 'react';
|
|
|
-
|
|
|
|
|
-import { Table, TableColumnsType, TablePaginationConfig, Drawer, Button } from 'antd';
|
|
|
|
|
-import { StepForwardOutlined, PlusOutlined } from '@ant-design/icons';
|
|
|
|
|
-import dayjs from 'dayjs';
|
|
|
|
|
-import { GuideTips } from '@/components/common';
|
|
|
|
|
-import store from './store';
|
|
|
|
|
-import { Record } from './types';
|
|
|
|
|
|
|
+import { useState, useEffect } from 'react';
|
|
|
|
|
+import { Table, Button, Input, Space, Modal, Form, Drawer, message, Pagination, Tag } from 'antd';
|
|
|
|
|
+import { SearchOutlined, EyeOutlined, CheckCircleOutlined, CloseCircleOutlined } from 'iconoir-react';
|
|
|
|
|
+import { useAuditStore } from './store';
|
|
|
import './style.scss';
|
|
import './style.scss';
|
|
|
-import LocalStorage from '@/LocalStorage';
|
|
|
|
|
-import InfoModal from './components/InfoModal';
|
|
|
|
|
-import PreviewModal from './components/PreviewModal';
|
|
|
|
|
-import AuditHistory from './components/auditHistory';
|
|
|
|
|
|
|
|
|
|
-const KnowledgeLibList: React.FC = () => {
|
|
|
|
|
- const {
|
|
|
|
|
- state,
|
|
|
|
|
- onChangePagination,
|
|
|
|
|
- onClickCreate,
|
|
|
|
|
- onClickModify,
|
|
|
|
|
- onClickfetchTakaiApplicationDetail,
|
|
|
|
|
- infoModalOnClickConfirm,
|
|
|
|
|
- infoModalOnClickCancel,
|
|
|
|
|
- infoModalOnClickClose,
|
|
|
|
|
- init,
|
|
|
|
|
- reset
|
|
|
|
|
- } = store;
|
|
|
|
|
|
|
+interface AuditItem {
|
|
|
|
|
+ id: string;
|
|
|
|
|
+ appId: string;
|
|
|
|
|
+ appName: string;
|
|
|
|
|
+ appDescription: string;
|
|
|
|
|
+ creatorId: string;
|
|
|
|
|
+ creator: string;
|
|
|
|
|
+ department: string;
|
|
|
|
|
+ submitTime: string;
|
|
|
|
|
+ auditStatus: 'pending' | 'approved' | 'rejected';
|
|
|
|
|
+ auditor: string | null;
|
|
|
|
|
+ auditTime: string | null;
|
|
|
|
|
+ auditOpinion: string | null;
|
|
|
|
|
+ knowledgeBaseCount: number;
|
|
|
|
|
+ documentCount: number;
|
|
|
|
|
+ sliceCount: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const AuditPage: React.FC = () => {
|
|
|
const {
|
|
const {
|
|
|
listLoading,
|
|
listLoading,
|
|
|
list,
|
|
list,
|
|
|
- infoModalId,
|
|
|
|
|
- infoModalOpen,
|
|
|
|
|
- page
|
|
|
|
|
- } = state;
|
|
|
|
|
-
|
|
|
|
|
- const [drawerFlag, setDrawerFlag] = React.useState<boolean>(false);
|
|
|
|
|
- const [drawerData, setDrawerData] = React.useState<any>({});
|
|
|
|
|
- const [historyOpen, setHistoryOpen] = React.useState<boolean>(false);
|
|
|
|
|
-
|
|
|
|
|
- React.useEffect(() => {
|
|
|
|
|
- const userInfo = LocalStorage.getUserInfo();
|
|
|
|
|
- const userId = (userInfo?.id ?? '').toString();
|
|
|
|
|
- init(userId);
|
|
|
|
|
-
|
|
|
|
|
- // 监听面包屑创建知识库事件
|
|
|
|
|
- const handleKnowledgeLibCreate = (event: CustomEvent) => {
|
|
|
|
|
- if (event.detail.platform === 'auditHistory') {
|
|
|
|
|
- // onClickCreate();
|
|
|
|
|
- setHistoryOpen(true);
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- window.addEventListener('auditHistory', handleKnowledgeLibCreate as EventListener);
|
|
|
|
|
|
|
+ page,
|
|
|
|
|
+ stats,
|
|
|
|
|
+ fetchAuditList,
|
|
|
|
|
+ fetchAuditStats,
|
|
|
|
|
+ onAuditPass,
|
|
|
|
|
+ onAuditReject,
|
|
|
|
|
+ setQuery,
|
|
|
|
|
+ } = useAuditStore();
|
|
|
|
|
+
|
|
|
|
|
+ const [detailVisible, setDetailVisible] = useState(false);
|
|
|
|
|
+ const [auditModalVisible, setAuditModalVisible] = useState(false);
|
|
|
|
|
+ const [currentAudit, setCurrentAudit] = useState<AuditItem | null>(null);
|
|
|
|
|
+ const [auditActionType, setAuditActionType] = useState<'approve' | 'reject'>('approve');
|
|
|
|
|
+ const [auditForm] = Form.useForm();
|
|
|
|
|
+ const [keyword, setKeyword] = useState('');
|
|
|
|
|
+ const [statusFilter, setStatusFilter] = useState<string>('all');
|
|
|
|
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ fetchAuditList();
|
|
|
|
|
+ fetchAuditStats();
|
|
|
|
|
+ }, [page.pageNum, page.pageSize]);
|
|
|
|
|
+
|
|
|
|
|
+ // 处理审核操作
|
|
|
|
|
+ const handleAudit = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const values = await auditForm.validateFields();
|
|
|
|
|
+ if (auditActionType === 'approve') {
|
|
|
|
|
+ await onAuditPass(currentAudit?.id || '', values.opinion || '');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await onAuditReject(currentAudit?.id || '', values.opinion || '');
|
|
|
|
|
+ }
|
|
|
|
|
+ setAuditModalVisible(false);
|
|
|
|
|
+ } catch (error: any) {
|
|
|
|
|
+ if (error?.response?.status !== 200) {
|
|
|
|
|
+ console.error('审核操作失败:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
+ // 查看详情
|
|
|
|
|
+ const handleViewDetail = (record: AuditItem) => {
|
|
|
|
|
+ setCurrentAudit(record);
|
|
|
|
|
+ setDetailVisible(true);
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
+ // 打开审核弹窗
|
|
|
|
|
+ const handleOpenAuditModal = (record: AuditItem, action: 'approve' | 'reject') => {
|
|
|
|
|
+ setCurrentAudit(record);
|
|
|
|
|
+ setAuditActionType(action);
|
|
|
|
|
+ auditForm.resetFields();
|
|
|
|
|
+ setAuditModalVisible(true);
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- return () => {
|
|
|
|
|
- reset();
|
|
|
|
|
- window.removeEventListener('auditHistory', handleKnowledgeLibCreate as EventListener);
|
|
|
|
|
|
|
+ // 状态标签渲染
|
|
|
|
|
+ const renderStatusBadge = (status: string) => {
|
|
|
|
|
+ const statusMap: Record<string, { text: string; color: string }> = {
|
|
|
|
|
+ pending: { text: '待审核', color: '#F59E0B' },
|
|
|
|
|
+ approved: { text: '已通过', color: '#059669' },
|
|
|
|
|
+ rejected: { text: '已拒绝', color: '#DC2626' },
|
|
|
};
|
|
};
|
|
|
- }, []);
|
|
|
|
|
|
|
+ const config = statusMap[status] || { text: status, color: '#6B7280' };
|
|
|
|
|
+ return <Tag color={config.color}>{config.text}</Tag>;
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- const columns: TableColumnsType<Record> = [
|
|
|
|
|
|
|
+ // 表格列定义
|
|
|
|
|
+ const columns = [
|
|
|
{
|
|
{
|
|
|
- title: '序号',
|
|
|
|
|
- dataIndex: 'index',
|
|
|
|
|
|
|
+ title: '应用名称',
|
|
|
|
|
+ dataIndex: 'appName',
|
|
|
|
|
+ key: 'appName',
|
|
|
|
|
+ width: 200,
|
|
|
|
|
+ render: (text: string, record: AuditItem) => (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div style={{ fontWeight: 500, color: '#1F2937' }}>{text}</div>
|
|
|
|
|
+ <div style={{ fontSize: '12px', color: '#6B7280', marginTop: '4px' }}>
|
|
|
|
|
+ {record.appDescription}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ ),
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: '创建人',
|
|
|
|
|
+ dataIndex: 'creator',
|
|
|
|
|
+ key: 'creator',
|
|
|
|
|
+ width: 100,
|
|
|
|
|
+ render: (text: string, record: AuditItem) => (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div>{text}</div>
|
|
|
|
|
+ <div style={{ fontSize: '12px', color: '#9CA3AF' }}>{record.department}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ ),
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: '提交时间',
|
|
|
|
|
+ dataIndex: 'submitTime',
|
|
|
|
|
+ key: 'submitTime',
|
|
|
|
|
+ width: 160,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: '知识库',
|
|
|
|
|
+ key: 'knowledgeBase',
|
|
|
width: 80,
|
|
width: 80,
|
|
|
- render: (text, record, index) => {
|
|
|
|
|
- return index + 1;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ render: (_: any, record: AuditItem) => (
|
|
|
|
|
+ <span>{record.knowledgeBaseCount} 个</span>
|
|
|
|
|
+ ),
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '知识名称',
|
|
|
|
|
- dataIndex: 'name',
|
|
|
|
|
- render: (text, record) => {
|
|
|
|
|
- // const previewUrl = `/preview/${record.url}`; // 根据实际字段构造 URL
|
|
|
|
|
- return (
|
|
|
|
|
- <a
|
|
|
|
|
- href={record.url}
|
|
|
|
|
- target="_blank"
|
|
|
|
|
- rel="noopener noreferrer"
|
|
|
|
|
- onClick={(e) => {
|
|
|
|
|
- e.stopPropagation(); // 防止 Table 默认事件干扰
|
|
|
|
|
- }}
|
|
|
|
|
- >
|
|
|
|
|
- {text}
|
|
|
|
|
- </a>
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ title: '文档',
|
|
|
|
|
+ key: 'document',
|
|
|
|
|
+ width: 70,
|
|
|
|
|
+ render: (_: any, record: AuditItem) => (
|
|
|
|
|
+ <span>{record.documentCount} 篇</span>
|
|
|
|
|
+ ),
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '状态',
|
|
|
|
|
- dataIndex: 'status',
|
|
|
|
|
- render: (text) => {
|
|
|
|
|
- if (text === '1') {
|
|
|
|
|
- return '待审核';
|
|
|
|
|
- }else if(text === '2'){
|
|
|
|
|
- return '审核中';
|
|
|
|
|
- }else if(text === '3'){
|
|
|
|
|
- return '审核通过';
|
|
|
|
|
- }else if(text === '4'||text === '5'){
|
|
|
|
|
- return '审核拒绝';
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ title: '切片',
|
|
|
|
|
+ key: 'slice',
|
|
|
|
|
+ width: 70,
|
|
|
|
|
+ render: (_: any, record: AuditItem) => (
|
|
|
|
|
+ <span>{record.sliceCount} 条</span>
|
|
|
|
|
+ ),
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '审核人',
|
|
|
|
|
- dataIndex: 'userName',
|
|
|
|
|
- render: (text) => {
|
|
|
|
|
- return `${text}`;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ title: '审核状态',
|
|
|
|
|
+ dataIndex: 'auditStatus',
|
|
|
|
|
+ key: 'auditStatus',
|
|
|
|
|
+ width: 100,
|
|
|
|
|
+ render: renderStatusBadge,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '审核意见',
|
|
|
|
|
- dataIndex: 'comment',
|
|
|
|
|
- render: (text) => {
|
|
|
|
|
- if(text){
|
|
|
|
|
- return `${text}`;
|
|
|
|
|
- }else{
|
|
|
|
|
- return '--';
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ title: '审核人',
|
|
|
|
|
+ dataIndex: 'auditor',
|
|
|
|
|
+ key: 'auditor',
|
|
|
|
|
+ width: 90,
|
|
|
|
|
+ render: (text: string | null) => text || '-',
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '创建时间',
|
|
|
|
|
- dataIndex: 'createTime',
|
|
|
|
|
- width: 200,
|
|
|
|
|
- render: (text) => {
|
|
|
|
|
- if (text) {
|
|
|
|
|
- return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
|
- } else {
|
|
|
|
|
- return '--';
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ title: '审核时间',
|
|
|
|
|
+ dataIndex: 'auditTime',
|
|
|
|
|
+ key: 'auditTime',
|
|
|
|
|
+ width: 160,
|
|
|
|
|
+ render: (text: string | null) => text || '-',
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
title: '操作',
|
|
title: '操作',
|
|
|
- dataIndex: 'operation',
|
|
|
|
|
- width: 150,
|
|
|
|
|
- fixed: 'right',
|
|
|
|
|
- render: (text, record) => {
|
|
|
|
|
- return (
|
|
|
|
|
- <>
|
|
|
|
|
- <a
|
|
|
|
|
- style={{ marginRight: 16 }}
|
|
|
|
|
- onClick={() => {
|
|
|
|
|
- // onClickfetchTakaiApplicationDetail(record.appId);
|
|
|
|
|
- setDrawerFlag(true)
|
|
|
|
|
- setDrawerData(record)
|
|
|
|
|
- }}
|
|
|
|
|
- title='审核'
|
|
|
|
|
- >
|
|
|
|
|
- 查看
|
|
|
|
|
- </a >
|
|
|
|
|
- <a
|
|
|
|
|
- style={{ marginRight: 16 }}
|
|
|
|
|
- onClick={() => {
|
|
|
|
|
- onClickModify(record.appId);
|
|
|
|
|
- }}
|
|
|
|
|
- title='审核'
|
|
|
|
|
- >
|
|
|
|
|
- <StepForwardOutlined />审核
|
|
|
|
|
- </a >
|
|
|
|
|
- </>
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- const paginationConfig: TablePaginationConfig = {
|
|
|
|
|
- // 显示数据总量
|
|
|
|
|
- showTotal: (total: number) => {
|
|
|
|
|
- return `共 ${total} 条`;
|
|
|
|
|
- },
|
|
|
|
|
- // 展示分页条数切换
|
|
|
|
|
- showSizeChanger: true,
|
|
|
|
|
- // 指定每页显示条数
|
|
|
|
|
- pageSizeOptions: ['10', '20', '50', '100'],
|
|
|
|
|
- // 快速跳转至某页
|
|
|
|
|
- showQuickJumper: true,
|
|
|
|
|
- current: page.pageNum,
|
|
|
|
|
- pageSize: page.pageSize,
|
|
|
|
|
- total: page.total,
|
|
|
|
|
- onChange: async (page, pageSize) => {
|
|
|
|
|
- await onChangePagination(page, pageSize);
|
|
|
|
|
|
|
+ key: 'action',
|
|
|
|
|
+ width: 200,
|
|
|
|
|
+ render: (_: any, record: AuditItem) => (
|
|
|
|
|
+ <Space>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ icon={<EyeOutlined />}
|
|
|
|
|
+ onClick={() => handleViewDetail(record)}
|
|
|
|
|
+ >
|
|
|
|
|
+ 详情
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ {record.auditStatus === 'pending' && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ icon={<CheckCircleOutlined />}
|
|
|
|
|
+ style={{ background: '#059669', borderColor: '#059669' }}
|
|
|
|
|
+ onClick={() => handleOpenAuditModal(record, 'approve')}
|
|
|
|
|
+ >
|
|
|
|
|
+ 通过
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ danger
|
|
|
|
|
+ icon={<CloseCircleOutlined />}
|
|
|
|
|
+ onClick={() => handleOpenAuditModal(record, 'reject')}
|
|
|
|
|
+ >
|
|
|
|
|
+ 拒绝
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Space>
|
|
|
|
|
+ ),
|
|
|
},
|
|
},
|
|
|
- };
|
|
|
|
|
|
|
+ ];
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
- <div className="page-container">
|
|
|
|
|
- {/* 标题区域 */}
|
|
|
|
|
- <div className="list-header">
|
|
|
|
|
- <div className='list-header-title'>
|
|
|
|
|
- <h1>应用审核</h1>
|
|
|
|
|
- <p>审核和管理应用</p>
|
|
|
|
|
|
|
+ <div className="page-container audit-page">
|
|
|
|
|
+ {/* 统计卡片 */}
|
|
|
|
|
+ <div className="audit-stats">
|
|
|
|
|
+ <div className="content-section" style={{ textAlign: 'center' }}>
|
|
|
|
|
+ <div style={{ fontSize: '28px', fontWeight: 'bold', color: '#1F2937' }}>
|
|
|
|
|
+ {stats?.total || 0}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style={{ fontSize: '13px', color: '#6B7280', marginTop: '4px' }}>
|
|
|
|
|
+ 总审核数
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div className='list-header-actions'>
|
|
|
|
|
- <Button
|
|
|
|
|
- type='primary'
|
|
|
|
|
- icon={<PlusOutlined />}
|
|
|
|
|
- onClick={onClickCreate}
|
|
|
|
|
- >
|
|
|
|
|
- 创建
|
|
|
|
|
- </Button>
|
|
|
|
|
|
|
+ <div className="content-section" style={{ textAlign: 'center' }}>
|
|
|
|
|
+ <div style={{ fontSize: '28px', fontWeight: 'bold', color: '#F59E0B' }}>
|
|
|
|
|
+ {stats?.pending || 0}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style={{ fontSize: '13px', color: '#6B7280', marginTop: '4px' }}>
|
|
|
|
|
+ 待审核
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="content-section" style={{ textAlign: 'center' }}>
|
|
|
|
|
+ <div style={{ fontSize: '28px', fontWeight: 'bold', color: '#059669' }}>
|
|
|
|
|
+ {stats?.approved || 0}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style={{ fontSize: '13px', color: '#6B7280', marginTop: '4px' }}>
|
|
|
|
|
+ 已通过
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="content-section" style={{ textAlign: 'center' }}>
|
|
|
|
|
+ <div style={{ fontSize: '28px', fontWeight: 'bold', color: '#DC2626' }}>
|
|
|
|
|
+ {stats?.rejected || 0}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style={{ fontSize: '13px', color: '#6B7280', marginTop: '4px' }}>
|
|
|
|
|
+ 已拒绝
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- {/* 表格区域 - 使用单个 content-section */}
|
|
|
|
|
- <div className="content-section">
|
|
|
|
|
|
|
+ {/* 审核列表 */}
|
|
|
|
|
+ <div className="audit-table content-section">
|
|
|
|
|
+ <div className="table-header">
|
|
|
|
|
+ <div className="header-title">
|
|
|
|
|
+ <h3>审核列表</h3>
|
|
|
|
|
+ <p>管理和审核 RAG 应用上线申请</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="header-actions">
|
|
|
|
|
+ <Input
|
|
|
|
|
+ className="search-input"
|
|
|
|
|
+ placeholder="搜索应用名称或创建人"
|
|
|
|
|
+ prefix={<SearchOutlined />}
|
|
|
|
|
+ value={keyword}
|
|
|
|
|
+ onChange={(e) => setKeyword(e.target.value)}
|
|
|
|
|
+ onPressEnter={() => fetchAuditList()}
|
|
|
|
|
+ allowClear
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div className="filter-tags">
|
|
|
|
|
+ <span
|
|
|
|
|
+ className={`filter-tag ${statusFilter === 'all' ? 'active' : ''}`}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ setStatusFilter('all');
|
|
|
|
|
+ setQuery({ status: '' });
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 全部
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span
|
|
|
|
|
+ className={`filter-tag ${statusFilter === 'pending' ? 'active' : ''}`}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ setStatusFilter('pending');
|
|
|
|
|
+ setQuery({ status: 'pending' });
|
|
|
|
|
+ fetchAuditList();
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 待审核
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span
|
|
|
|
|
+ className={`filter-tag ${statusFilter === 'approved' ? 'active' : ''}`}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ setStatusFilter('approved');
|
|
|
|
|
+ setQuery({ status: 'approved' });
|
|
|
|
|
+ fetchAuditList();
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 已通过
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span
|
|
|
|
|
+ className={`filter-tag ${statusFilter === 'rejected' ? 'active' : ''}`}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ setStatusFilter('rejected');
|
|
|
|
|
+ setQuery({ status: 'rejected' });
|
|
|
|
|
+ fetchAuditList();
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 已拒绝
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<Table
|
|
<Table
|
|
|
- scroll={{ x: 'max-content' }}
|
|
|
|
|
- rowKey={(record) => record.createTime}
|
|
|
|
|
- loading={listLoading}
|
|
|
|
|
columns={columns}
|
|
columns={columns}
|
|
|
dataSource={list}
|
|
dataSource={list}
|
|
|
- pagination={paginationConfig}
|
|
|
|
|
|
|
+ rowKey="id"
|
|
|
|
|
+ loading={listLoading}
|
|
|
|
|
+ pagination={false}
|
|
|
|
|
+ scroll={{ x: 1400 }}
|
|
|
/>
|
|
/>
|
|
|
|
|
+
|
|
|
|
|
+ <div className="pagination-container" style={{ marginTop: '16px', display: 'flex', justifyContent: 'flex-end' }}>
|
|
|
|
|
+ <Pagination
|
|
|
|
|
+ current={page.pageNum}
|
|
|
|
|
+ pageSize={page.pageSize}
|
|
|
|
|
+ total={page.total}
|
|
|
|
|
+ onChange={(pageNum, pageSize) => {
|
|
|
|
|
+ useAuditStore.getState().setPage({ ...page, pageNum, pageSize });
|
|
|
|
|
+ fetchAuditList();
|
|
|
|
|
+ }}
|
|
|
|
|
+ showSizeChanger
|
|
|
|
|
+ showTotal={(t) => `共 ${t} 条`}
|
|
|
|
|
+ pageSizeOptions={['10', '20', '50', '100']}
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
- {
|
|
|
|
|
- infoModalOpen &&
|
|
|
|
|
- <InfoModal
|
|
|
|
|
- id={infoModalId}
|
|
|
|
|
- open={infoModalOpen}
|
|
|
|
|
- onClickConfirm={infoModalOnClickConfirm}
|
|
|
|
|
- onClickCancel={infoModalOnClickCancel}
|
|
|
|
|
- onClickClose={infoModalOnClickClose}
|
|
|
|
|
- />
|
|
|
|
|
- }
|
|
|
|
|
- {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ {/* 审核操作弹窗 */}
|
|
|
|
|
+ <Modal
|
|
|
|
|
+ title={auditActionType === 'approve' ? '审核通过' : '审核拒绝'}
|
|
|
|
|
+ open={auditModalVisible}
|
|
|
|
|
+ onOk={handleAudit}
|
|
|
|
|
+ onCancel={() => setAuditModalVisible(false)}
|
|
|
|
|
+ okText="确认"
|
|
|
|
|
+ cancelText="取消"
|
|
|
|
|
+ okButtonProps={{
|
|
|
|
|
+ danger: auditActionType === 'reject',
|
|
|
|
|
+ style: auditActionType === 'reject' ? {} : { background: '#059669', borderColor: '#059669' },
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <div style={{ marginBottom: '16px' }}>
|
|
|
|
|
+ <strong>应用名称:</strong>{currentAudit?.appName}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style={{ marginBottom: '16px' }}>
|
|
|
|
|
+ <strong>创建人:</strong>{currentAudit?.creator} ({currentAudit?.department})
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style={{ marginBottom: '16px' }}>
|
|
|
|
|
+ <strong>应用描述:</strong>
|
|
|
|
|
+ <p style={{ color: '#6B7280', fontSize: '13px' }}>{currentAudit?.appDescription}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <Form form={auditForm} layout="vertical">
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ label="审核意见"
|
|
|
|
|
+ name="opinion"
|
|
|
|
|
+ rules={[{ required: true, message: `请输入${auditActionType === 'approve' ? '通过' : '拒绝'}意见` }]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Input.TextArea
|
|
|
|
|
+ rows={4}
|
|
|
|
|
+ placeholder={auditActionType === 'reject'
|
|
|
|
|
+ ? '请输入拒绝原因(必填)'
|
|
|
|
|
+ : '请输入审核意见(必填)'}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ </Form>
|
|
|
|
|
+ </Modal>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 详情抽屉 */}
|
|
|
<Drawer
|
|
<Drawer
|
|
|
- title={drawerData.name}
|
|
|
|
|
- closable={{ 'aria-label': 'Close Button' }}
|
|
|
|
|
- onClose={() => { setDrawerFlag(false) }}
|
|
|
|
|
- width="80%"
|
|
|
|
|
- open={drawerFlag}
|
|
|
|
|
|
|
+ title="应用详情"
|
|
|
|
|
+ placement="right"
|
|
|
|
|
+ width={600}
|
|
|
|
|
+ open={detailVisible}
|
|
|
|
|
+ onClose={() => setDetailVisible(false)}
|
|
|
|
|
+ className="detail-drawer"
|
|
|
>
|
|
>
|
|
|
- {drawerFlag&&<PreviewModal isComponent={true} AuditAppId={drawerData.appId} />}
|
|
|
|
|
|
|
+ {currentAudit && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <div className="detail-section">
|
|
|
|
|
+ <h4 className="section-title">基本信息</h4>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">应用名称:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.appName}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">应用描述:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.appDescription}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">创建人:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.creator}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">所属部门:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.department}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">提交时间:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.submitTime}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">审核状态:</span>
|
|
|
|
|
+ <span className="value">{renderStatusBadge(currentAudit.auditStatus)}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div className="detail-section">
|
|
|
|
|
+ <h4 className="section-title">资源统计</h4>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">知识库:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.knowledgeBaseCount} 个</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">文档:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.documentCount} 篇</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="detail-row">
|
|
|
|
|
+ <span className="label">切片:</span>
|
|
|
|
|
+ <span className="value">{currentAudit.sliceCount} 条</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {currentAudit.auditOpinion && (
|
|
|
|
|
+ <div className="detail-section">
|
|
|
|
|
+ <h4 className="section-title">审核意见</h4>
|
|
|
|
|
+ <p style={{ color: '#6B7280', fontSize: '13px' }}>
|
|
|
|
|
+ {currentAudit.auditOpinion}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
</Drawer>
|
|
</Drawer>
|
|
|
- }
|
|
|
|
|
- <AuditHistory open={historyOpen} onClose={() => setHistoryOpen(false)} />
|
|
|
|
|
|
|
+ </div>
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-export default KnowledgeLibList;
|
|
|
|
|
|
|
+export default AuditPage;
|