CzRger 3 months ago
parent
commit
ab9d15323c

+ 17 - 2
web/app/components/base/switch/index.tsx

@@ -5,6 +5,7 @@ import classNames from '@/utils/classnames'
 
 type SwitchProps = {
   onChange?: (value: boolean) => void
+  beforeChange?: () => void
   size?: 'xs' | 'sm' | 'md' | 'lg' | 'l'
   defaultValue?: boolean
   disabled?: boolean
@@ -15,6 +16,7 @@ const Switch = (
   {
     ref: propRef,
     onChange,
+    beforeChange,
     size = 'md',
     defaultValue = false,
     disabled = false,
@@ -50,6 +52,20 @@ const Switch = (
     sm: 'translate-x-2',
     xs: 'translate-x-1.5',
   }
+
+  const handleBeforeChange = (checked: boolean) => {
+    if (beforeChange) {
+      const result: any = beforeChange()
+      if (result) {
+        setEnabled(checked)
+        onChange?.(checked)
+      }
+    }
+    else {
+      setEnabled(checked)
+      onChange?.(checked)
+    }
+  }
   return (
     <OriginalSwitch
       ref={propRef}
@@ -57,8 +73,7 @@ const Switch = (
       onChange={(checked: boolean) => {
         if (disabled)
           return
-        setEnabled(checked)
-        onChange?.(checked)
+        handleBeforeChange(checked)
       }}
       className={classNames(
         wrapStyle[size],

+ 3 - 2
web/app/components/datasets/documents/index.tsx

@@ -101,7 +101,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
   const isDataSourceWeb = dataset?.data_source_type === DataSourceType.WEB
   const isDataSourceFile = dataset?.data_source_type === DataSourceType.FILE
   const embeddingAvailable = !!dataset?.embedding_available
-  const optionsStatus = [
+  const optionsExamineStatus = [
     { name: '待审核', value: 1 },
     { name: '审核不通过', value: 2 },
     { name: '无', value: 3 },
@@ -298,7 +298,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
                 onSelect={(i) => {
                   setStatus(i.value)
                 }}
-                items={optionsStatus}
+                items={optionsExamineStatus}
                 allowSearch={false}
                 placeholder="请选择审核状态"
               />
@@ -368,6 +368,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
                   onChange: setCurrPage,
                 }}
                 onManageMetadata={showEditMetadataModal}
+                optionsExamineStatus={optionsExamineStatus}
               />
               : <EmptyElement canAdd={embeddingAvailable} onClick={routeToDocCreate} type={isDataSourceNotion ? 'sync' : 'upload'} />
           }

+ 144 - 4
web/app/components/datasets/documents/list.tsx

@@ -46,6 +46,8 @@ import { useDocumentArchive, useDocumentDelete, useDocumentDisable, useDocumentE
 import { extensionToFileType } from '@/app/components/datasets/hit-testing/utils/extension-to-file-type'
 import useBatchEditDocumentMetadata from '../metadata/hooks/use-batch-edit-document-metadata'
 import EditMetadataBatchModal from '@/app/components/datasets/metadata/edit-metadata-batch/modal'
+import { useAppContext } from '@/context/app-context'
+import { applyExamine, handleExamine } from '@/service/common'
 
 export const useIndexStatus = () => {
   const { t } = useTranslation()
@@ -262,6 +264,37 @@ export const OperationAction: FC<{
   const handleRenamed = useCallback(() => {
     onUpdate()
   }, [onUpdate])
+  const [showNotDelModal, setShowNotDelModal] = useState(false)
+  const [showNotSwitchModal, setShowNotSwitchModal] = useState(false)
+  const beforeDel = () => {
+    if (!detail.enabled)
+      setShowModal(true)
+    else
+      setShowNotDelModal(true)
+  }
+  const [showApplyExamine, setShowApplyExamine] = useState<boolean>(false)
+  const beforeHandleSwitch = () => {
+    if (false) { // 待审核
+      setShowNotSwitchModal(true)
+      return false
+    }
+    if (true) { // 提交审批
+      setShowApplyExamine(true)
+      return false
+    }
+    return true
+  }
+  const onApplyExamine = useCallback(async () => {
+    try {
+      const { result }: any = await applyExamine({
+        url: '/workspaces/123123',
+        body: { id: detail.id, enabled: !detail.enabled },
+      })
+      onUpdate?.()
+      setShowApplyExamine(false)
+    }
+    catch (e) { }
+  }, [detail, onUpdate, setShowApplyExamine])
 
   return <div className='flex items-center' onClick={e => e.stopPropagation()}>
     {isListScene && !embeddingAvailable && (
@@ -279,7 +312,7 @@ export const OperationAction: FC<{
               <Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' />
             </div>
           </Tooltip>
-          : <Switch defaultValue={enabled} onChange={v => handleSwitch(v ? 'enable' : 'disable')} size='md' />
+          : <Switch defaultValue={enabled} beforeChange={beforeHandleSwitch} onChange={v => handleSwitch(v ? 'enable' : 'disable')} size='md' />
         }
         <Divider className='!ml-4 !mr-2 !h-3' type='vertical' />
       </>
@@ -332,7 +365,7 @@ export const OperationAction: FC<{
                   <span className={s.actionName}>{t('datasetDocuments.list.action.unarchive')}</span>
                 </div>
               )}
-              <div className={cn(s.actionItem, s.deleteActionItem, 'group')} onClick={() => setShowModal(true)}>
+              <div className={cn(s.actionItem, s.deleteActionItem, 'group')} onClick={() => beforeDel()}>
                 <RiDeleteBinLine className={'h-4 w-4 text-text-tertiary group-hover:text-text-destructive'} />
                 <span className={cn(s.actionName, 'group-hover:text-text-destructive')}>{t('datasetDocuments.list.action.delete')}</span>
               </div>
@@ -363,6 +396,37 @@ export const OperationAction: FC<{
         onCancel={() => setShowModal(false)}
       />
     }
+    {showNotDelModal
+      && <Confirm
+        isShow={showNotDelModal}
+        title="操作失败"
+        content="请将该知识停用后再删除!"
+        onConfirm={() => setShowNotDelModal(false)}
+        onCancel={() => setShowNotDelModal(false)}
+        showCancel={false}
+        confirmText="好的"
+      />
+    }
+    {showNotSwitchModal
+      && <Confirm
+        isShow={showNotSwitchModal}
+        title="操作失败"
+        content="该知识有待审核的操作,无法再进行上下线操作!"
+        onConfirm={() => setShowNotSwitchModal(false)}
+        onCancel={() => setShowNotSwitchModal(false)}
+        showCancel={false}
+        confirmText="好的"
+      />
+    }
+    {showApplyExamine
+      && <Confirm
+        isShow={showApplyExamine}
+        title={`${enabled ? '下线' : '上线'}审核确认`}
+        content="该操作需要提交管理员审核后生效,请确认是否提交?"
+        onConfirm={onApplyExamine}
+        onCancel={() => setShowApplyExamine(false)}
+      />
+    }
 
     {isShowRenameModal && currDocument && (
       <RenameModal
@@ -403,7 +467,8 @@ type IDocumentListProps = {
   datasetId: string
   pagination: PaginationProps
   onUpdate: () => void
-  onManageMetadata: () => void
+  onManageMetadata: () => void,
+  optionsExamineStatus: any[]
 }
 
 /**
@@ -418,6 +483,7 @@ const DocumentList: FC<IDocumentListProps> = ({
   pagination,
   onUpdate,
   onManageMetadata,
+  optionsExamineStatus,
 }) => {
   const { t } = useTranslation()
   const { formatTime } = useTimestamp()
@@ -513,7 +579,24 @@ const DocumentList: FC<IDocumentListProps> = ({
       else { Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) }
     }
   }
-
+  const appContext = useAppContext()
+  const [row, setRow] = useState<any>({})
+  const [showConfirmExamineResult, setShowConfirmExamineResult] = useState(false)
+  const [confirmExamineResultContent, setConfirmExamineResultContent] = useState('')
+  const [showConfirmExamineHandle, setShowConfirmExamineHandle] = useState(false)
+  const [confirmExamineHandleTitle, setConfirmExamineHandleTitle] = useState('')
+  const [confirmExamineHandleContent, setConfirmExamineHandleContent] = useState('')
+  const onHandleExamine = useCallback(async () => {
+    try {
+      const { result }: any = await handleExamine({
+        url: '/workspaces/123123',
+        body: { id: row.id, enabled: !row.enabled },
+      })
+      onUpdate?.()
+      setShowConfirmExamineHandle(false)
+    }
+    catch (e) { }
+  }, [row, onUpdate, setShowConfirmExamineHandle])
   return (
     <div className='relative flex h-full w-full flex-col'>
       <div className='relative grow overflow-x-auto'>
@@ -548,6 +631,7 @@ const DocumentList: FC<IDocumentListProps> = ({
                 </div>
               </td>
               <td className='w-40'>{t('datasetDocuments.list.table.header.status')}</td>
+              <td className='w-40'>审核状态</td>
               <td className='w-20'>{t('datasetDocuments.list.table.header.action')}</td>
             </tr>
           </thead>
@@ -622,6 +706,40 @@ const DocumentList: FC<IDocumentListProps> = ({
                   }
                 </td>
                 <td>
+                  {/* { */}
+                  {/*  true && ( */}
+                  {/*    <div className="cursor text-[#155aef]" onClick={e => { */}
+                  {/*      e.stopPropagation() */}
+                  {/*      setConfirmExamineResultContent(`用户“${doc.name}”不同意将该知识上线!`) */}
+                  {/*      setShowConfirmExamineResult(true) */}
+                  {/*    }}>审核不通过</div> */}
+                  {/*  ) */}
+                  {/* } */}
+                  {
+                    true && (
+                      ['owner', 'admin'].includes(appContext.currentWorkspace.role)
+                        ? <div className="cursor text-[#155aef]" onClick={(e) => {
+                          e.stopPropagation()
+                          setRow(doc)
+                          setConfirmExamineHandleTitle(`${doc.enabled ? '下线' : '上线'}审核`)
+                          setConfirmExamineHandleContent(`用户“${doc.name}”申请将该知识${doc.enabled ? '下线' : '上线'},请审核!`)
+                          setShowConfirmExamineHandle(true)
+                        }}>待审核</div>
+                        : <div>待审核</div>
+                    )
+                  }
+                  {/* { */}
+                  {/*  index === 2 && ( */}
+                  {/*    <div className="cursor text-[#155aef]" onClick={(e) => { */}
+                  {/*      e.stopPropagation() */}
+                  {/*      setConfirmExamineResultContent(`用户“${doc.name}”不同意将该知识上线!`) */}
+                  {/*      setShowConfirmExamineResult(true) */}
+                  {/*    }}>无</div> */}
+                  {/*  ) */}
+                  {/* } */}
+
+                </td>
+                <td>
                   <OperationAction
                     embeddingAvailable={embeddingAvailable}
                     datasetId={datasetId}
@@ -679,6 +797,28 @@ const DocumentList: FC<IDocumentListProps> = ({
           }}
         />
       )}
+      {showConfirmExamineResult && (
+        <Confirm
+          title="审核结果"
+          content={confirmExamineResultContent}
+          isShow={showConfirmExamineResult}
+          onConfirm={() => setShowConfirmExamineResult(false)}
+          onCancel={() => setShowConfirmExamineResult(false)}
+          showCancel={false}
+          confirmText="好的"
+        />
+      )}
+      {showConfirmExamineHandle && (
+        <Confirm
+          title={confirmExamineHandleTitle}
+          content={confirmExamineHandleContent}
+          isShow={showConfirmExamineHandle}
+          onConfirm={() => onHandleExamine()}
+          onCancel={() => setShowConfirmExamineHandle(false)}
+          confirmText="同意"
+          cancelText="不同意"
+        />
+      )}
     </div>
   )
 }

+ 2 - 2
web/app/components/datasets/documents/mould/index.tsx

@@ -152,7 +152,7 @@ const DetailModel = ({
                     }
                   </div>
                   <div className="ml-2">{file.fileName}</div>
-                  <div className="ml-auto" onClick={(e) => {
+                  <div className="cursor ml-auto" onClick={(e) => {
                     e.stopPropagation()
                     downloadFile(`/files/${file.id}/file-preview?timestamp=${new Date().getTime()}` || '', file.fileName)
                   }}>
@@ -160,7 +160,7 @@ const DetailModel = ({
                   </div>
                   {
                     transfer.mode === 'manage' && (
-                      <div className="ml-5" onClick={() => {
+                      <div className="cursor ml-5" onClick={() => {
                         setDelId(file.id)
                         setShowConfirmDelete(true)
                       }}>

+ 24 - 0
web/service/common.ts

@@ -263,6 +263,30 @@ export const delMouldFile = ({ url, body }) => {
   })
 }
 
+export const handleExamine = ({ url, body }) => {
+  // return post<InvitationResponse>(url, { body })
+  console.log('处理上下线审核', body)
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve({
+        result: 'success',
+      })
+    }, 1000)
+  })
+}
+
+export const applyExamine = ({ url, body }) => {
+  // return post<InvitationResponse>(url, { body })
+  console.log('提交上下线审核', body)
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve({
+        result: 'success',
+      })
+    }, 1000)
+  })
+}
+
 export const fetchFilePreview: Fetcher<{ content: string }, { fileID: string }> = ({ fileID }) => {
   return get<{ content: string }>(`/files/${fileID}/preview`)
 }