Explorar o código

添加上传loading

bill %!s(int64=2) %!d(string=hai) anos
pai
achega
84635cba4d

+ 5 - 0
.idea/.gitignore

@@ -0,0 +1,5 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/

+ 12 - 0
.idea/fuse.iml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.tmp" />
+      <excludeFolder url="file://$MODULE_DIR$/temp" />
+      <excludeFolder url="file://$MODULE_DIR$/tmp" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
+  </profile>
+</component>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/fuse.iml" filepath="$PROJECT_DIR$/.idea/fuse.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 3 - 3
src/api/instance.ts

@@ -1,6 +1,6 @@
 import { axiosFactory } from './setup'
 import { message } from 'antd'
-import { GET_MODEL_SCENE_STATUS, LOGIN, ResCode, ResCodeDesc } from 'constant'
+import {GET_MODEL_SCENE_STATUS, LOGIN, ResCode, ResCodeDesc, UPLOAD_MODEL} from 'constant'
 import { showLoading, hideLoading } from 'components/loading'
 import { baseURI } from 'env'
 
@@ -40,12 +40,12 @@ addResErrorHandler(
 
 addHook({
   before(config) {
-    if (config.url !== GET_MODEL_SCENE_STATUS) {
+    if (config.url !== GET_MODEL_SCENE_STATUS && config.url != UPLOAD_MODEL) {
       showLoading()
     }
   },
   after(config) {
-    if (config.url !== GET_MODEL_SCENE_STATUS) {
+    if (config.url !== GET_MODEL_SCENE_STATUS && config.url != UPLOAD_MODEL) {
       hideLoading()
     }
   }

+ 6 - 1
src/setupProxy.js

@@ -48,6 +48,11 @@ const proxys = {
 
 module.exports = function (app) {
   for (const [prefix, config] of Object.entries(proxys)) {
-    app.use(createProxyMiddleware(prefix, config))
+    app.use(createProxyMiddleware(prefix, {
+      ...config,
+      headers: {
+        Connection: 'keep-alive'
+      }
+    }))
   }
 }

+ 1 - 1
src/utils/serve.ts

@@ -10,7 +10,7 @@ export const jsonToForm = (data: { [key in string]: any }) => {
 export type UploadProgressCallback = (num: number) => void
 export const uploadProgressFactory = (callback: UploadProgressCallback) => (event: any) => {
   if(event.lengthComputable){
-    const complete = (event.loaded / event.total) * 100 || 0
+    const complete = (Math.round(event.loaded / event.total * 100) ) || 0
     callback(complete || 0)
   }
 }

+ 31 - 34
src/views/scene/content.tsx

@@ -1,26 +1,25 @@
-import { SceneType, ModelSceneStatus } from 'constant'
-import { Table, ActionsButton } from 'components'
-import { getSceneColumns, getSceneActions, sceneTitleColumn } from './columns'
-import { useThunkPaging } from 'hook'
-import { SceneHeader } from './header'
-import { confirm } from 'utils'
-import { message, Input, Button } from 'antd'
-import { CheckOutlined, EditOutlined } from '@ant-design/icons'
+import {ModelSceneStatus, SceneType} from 'constant'
+import {ActionsButton, Table} from 'components'
+import type {SceneColumn} from './columns'
+import {getSceneActions, getSceneColumns, sceneTitleColumn} from './columns'
+import {useThunkPaging} from 'hook'
+import {SceneHeader} from './header'
+import {confirm} from 'utils'
+import {Button, Input, message} from 'antd'
+import {CheckOutlined, EditOutlined} from '@ant-design/icons'
 import style from './style.module.scss'
-import { 
-  useSelector, 
-  filterScenesSelector,
-  fetchScenes,
+import {
+  cancelUploadScene,
+  checkSceneStatus,
   deleteModelScene,
+  fetchScenes,
+  filterScenesSelector,
   useDispatch,
-  checkSceneStatus,
-  cancelUploadScene
+  useSelector
 } from 'store'
-import { useEffect, useState } from 'react'
-import { updateModelSceneTitle } from 'api'
-
-import type { SceneColumn } from './columns'
-import type { Scene } from 'api'
+import {useEffect, useState} from 'react'
+import type {Scene} from 'api'
+import {updateModelSceneTitle} from 'api'
 
 export type EditModelSceneTitleProps = {
   scene: Scene
@@ -41,23 +40,21 @@ export const EditModelSceneTitle = (props: EditModelSceneTitleProps) => {
     }
   }
 
-  const renderTitle = inEditMode
+  return inEditMode
     ? <Input.Group style={{width: '200px'}}>
-        <Input 
-          maxLength={50}
-          autoFocus
-          style={{ width: 'calc(100% - 40px)' }} 
-          value={title} 
-          onChange={ev => setTitle(ev.target.value)} 
-        />
-        <Button icon={<CheckOutlined />} onClick={enterHandler} />
-      </Input.Group>
+      <Input
+        maxLength={50}
+        autoFocus
+        style={{width: 'calc(100% - 40px)'}}
+        value={title}
+        onChange={ev => setTitle(ev.target.value)}
+      />
+      <Button icon={<CheckOutlined/>} onClick={enterHandler}/>
+    </Input.Group>
     : <div className={style['show-scene-title']}>
-        <p>{props.scene.title}</p>
-        <EditOutlined onClick={() => setInEditMode(true)} />
-      </div>
-
-  return renderTitle
+      <p>{props.scene.title}</p>
+      <EditOutlined onClick={() => setInEditMode(true)}/>
+    </div>
 }
 
 

+ 28 - 4
src/views/scene/header.tsx

@@ -1,7 +1,8 @@
 import { SceneType } from "constant"
-import { memo } from 'react'
-import { Button, Upload, message, Input, Popover } from 'antd'
+import {memo, useState} from 'react'
+import {Button, Upload, message, Input, Popover, Progress, Modal} from 'antd'
 import { useDispatch, uploadModelScene } from 'store'
+import styles from './style.module.scss'
 
 import type { GetSceneByTypeParams, PagingRequest } from 'api'
 import type { UploadProps } from 'antd'
@@ -16,6 +17,11 @@ type ListHeaderProps = {
 
 export const SceneHeader = memo(({ readonly, type, onSearch, onDataChange }: ListHeaderProps) => {
   const dispatch = useDispatch()
+  const [progress, setProgress] = useState<number | null>(null);
+  const progressCallback = (num: number) => {
+    console.log(num)
+    setProgress(num === 100 ? null : num);
+  }
   const onUpload: UploadProps['beforeUpload'] = file => {
     const filename = file.name
     
@@ -24,11 +30,11 @@ export const SceneHeader = memo(({ readonly, type, onSearch, onDataChange }: Lis
     if (!isZip) {
       message.error('只能上传zip文件')
       return Upload.LIST_IGNORE
-    } else if (file.size > 1 * 1024 * 1024 * 1024) {
+    } else if (file.size > 1024 * 1024 * 1024) {
       message.error('大小在1GB以内')
       return Upload.LIST_IGNORE
     }
-    dispatch(uploadModelScene({ file }))
+    dispatch(uploadModelScene({ file, progressCallback }))
       .unwrap()
       .finally(onDataChange)
     return Upload.LIST_IGNORE
@@ -41,10 +47,28 @@ export const SceneHeader = memo(({ readonly, type, onSearch, onDataChange }: Lis
       </Popover>
     </Upload>
   ))
+  const renderProgress = progress
+    ? (
+      <Modal
+        title="文件上传中"
+        className={styles['upload-modal']}
+        centered
+        open={true}
+        width={1000}
+        footer={false}
+        closable={false}
+      >
+        <div style={{height: '100px'}}>
+          <Progress percent={progress} />
+        </div>
+      </Modal>
+      )
+    : null;
 
   return (
     <div className='content-header'>
       { renderUpload }
+      { renderProgress }
       <Input.Search
         allowClear
         className='content-header-search'

+ 3 - 0
src/views/scene/style.module.scss

@@ -21,4 +21,7 @@
 
 .scene-tab :global(.ant-tabs > .ant-tabs-nav) {
   margin-bottom: 0;
+}
+.upload-modal {
+
 }