# MUpload 上传

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/mobile/upload/freepass)
- 平台：移动端
- 维护者：熊相超
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[MUpload]

## 代码演示

### 基础用法

直接引入组件进行使用

```jsx
import { Component } from 'react';
import { Dialog, Button, Upload, UploadData, MUpload } from '@weapp/ui';
import { formatParentPath } from '../../../../utils';
import { data } from '../mock';

class MockDemo extends Component<any, any> {
  uploadInstance: any = null;
  state = {
    data: [],
    uploadingData: [],
    isUploaded: false
  }

  componentDidUpdate(prevProps: Readonly<any>, prevState: Readonly<any>, snapshot?: any): void {
    console.error('componentDidUpdate', this.state.isUploaded)
    if (this.state.isUploaded && prevState.isUploaded !== this.state.isUploaded) {
      setTimeout(() => {
        Dialog.message({
          content: '执行逻辑'
        })
      }, 500);
    }
  }

  componentWillUnmount(): void {
    console.error('弹框内部组件卸载啦！')
  }

  onChange = (listT?: UploadData[] | undefined, listB?: UploadData[] | undefined) => {
    console.error('onChange', listT, listB)
    this.setState({ data: listT, uploadingData: listB });
  }

  onUploadComplete = (successFiles: UploadData[], failedFiles: UploadData[], total?: number | undefined) => {
    console.error('onUploadComplete', successFiles, failedFiles, total)
    this.setState({ isUploaded: true })
    this.props.onUploadComplete(successFiles, failedFiles, total);
  }

  getInstance = (uploadInstance: any) => {
    this.uploadInstance = uploadInstance;
  }

  onSure = () => {
    this.uploadInstance?.startUpload();
    this.props.onClose();
    // setInterval(() => {
    //   console.error('setInterval a', this.state.isUploaded)
    //   this.setState({ isUploaded: true }, () => {
    //     console.error('setInterval b', this.state.isUploaded)
    //   })
    // }, 1000)
  }

  render() {
    const { data, uploadingData } = this.state;
    return (
      <div>
        <Upload
         
          data={data}
          uploadingData={uploadingData}
          uploadParams={{
            module: 'document',
          }}
          getInstance={this.getInstance}
          autoUpload={false}
          onChange={this.onChange}
          onUploadComplete={this.onUploadComplete}
        />
        <Button onClick={this.onSure}>确认</Button>
      </div>
    );
  }
}

class UploadDemo extends Component<any, any> {
  state = {
    visible: false,
  }

  openDialog = () => {
    this.setState({ visible: true });
    const parentPath = formatParentPath(this.props as any);
    this.props.history.push(`${parentPath}/route`)
  }

  closeDialog = () => {
    this.setState({ visible: false });
    window.history.go(-1);
  }

  goRoute = () => {
    const parentPath = formatParentPath(this.props as any);
    // this.props.history.push(`${parentPath}/route`)
    this.props.history.push(`/ui/demo/mobile/upload/demo-1`);
  }

  onUploadComplete = (successFiles: UploadData[], failedFiles: UploadData[], total?: number | undefined) => {
    console.error('模块的 onUploadComplete 中的事件', successFiles, failedFiles, total)
    Dialog.message({
      content: `上传完成，成功${successFiles.length}，失败${failedFiles.length}，共${total}个！`
    })
  }

  onStart = (file: any) => {
    console.error('onStart', file);
  }

  render() {
    const { visible } = this.state;
    const parentPath = formatParentPath(this.props as any);
    return (
      <div>
        <MUpload
         
          uploadParams={{
            module: 'document'
          }}
          multiple
          onStart={this.onStart}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 异步上传

```jsx
import React, { PureComponent } from 'react';
import { MButton, MSwitch, MUpload, SwitchChangeEventHandler } from '@weapp/ui';
import { weappSDK } from '@weapp/utils';

/**
 * 是否 em 中且 sdk 正常使用
 * @returns boolean
 */
export const isEmSDK = () => {
  return new Promise(async (resolve, reject) => {
    try {
      let canChooseImage = await weappSDK.checkApi('chooseImage')
      let canChooseFile = await weappSDK.checkApi('chooseFile')
      let canUploadFile = await weappSDK.checkApi('uploadFile')
      if (weappSDK && canChooseImage === 'success' && canChooseFile === 'success' && canUploadFile === 'success') {
        resolve(true);
      }
      // return false;
      resolve(false);
    } catch (err) {
      // return false;
      resolve(false);
    }
  })
}

/** 判断当前环境是否允许调用异步上传 */
export const checkAsyncUpload = () => {
  return new Promise<boolean>(async (resolve, reject) => {
    try {
      const isElectron = navigator.userAgent.indexOf('Electron') > 0 && navigator.userAgent.indexOf('weapp-pc') > 0
      const isEm = await isEmSDK();
      if (isElectron) { // 客户端
        resolve(false);
      } else if (isEm) { // em
        const canAsyncUpload = await weappSDK.checkApi('openUpload')
        resolve(canAsyncUpload === 'success');
      } else {
        resolve(true);
      }
    } catch (error) {
      resolve(false);
    }
  })
}

class Demo extends PureComponent<any, any> {
  uploadInsRef = React.createRef<any>()

  state: any = { async: true, num: 1 }

  // componentDidMount(): void {
  //   checkAsyncUpload()
  //     .then(res => {
  //       console.error('demo 日志', res)
  //       weappSDK.exec('registerHandler', {
  //         name: 'onUploadStateChange',
  //         fn: (res: { state: string, files: string[] }) => {
  //           console.error('demo 中触发 onUploadStateChange', res, this.state);
  //         }
  //       });
  //     })
  // }

  onSwitchChange = (async: boolean) => {
    this.setState({ async })
  }

  getUploadInsRed = (el: any) => {
    console.log('getUploadInsRed')
    console.log('el', el)
    this.uploadInsRef = el
  }

  sureUpload = () => {
    (this.uploadInsRef as any)?.startUpload()
  }

  openUpload = () => {
    console.error('触发打开上传列表')
    weappSDK.exec('openUpload', {})
  }

  onAdd = () => {
    let newNum = this.state.num + 1;
    this.setState({ num: newNum });
  }

  render() {
    const { async } = this.state;
    return (
      <div>
        <h2> <MSwitch value={async} label={async ? '异步上传：开' : '异步上传：关'} onChange={this.onSwitchChange} /></h2>
        <h3>1</h3>
        <h3>自动上传</h3>
        <MUpload
                 uploadParams={{
                   module: 'document'
                 }}
                 asyncUpload={async}
                 onAdd={this.onAdd}
        />
        <h3>手动上传</h3>
        <MUpload
                 uploadParams={{
                   module: 'document'
                 }}
                 autoUpload={false}
                 secretProtect={true}
                 secretLevel='1'
                 wrappedComponentRef={this.getUploadInsRed}
                 asyncUpload={async}
        />
        <MButton
         
          type='primary'
          onClick={this.sureUpload}
        >
          确定上传
        </MButton>

        <h3>打开 em 上传列表</h3>
        <MButton onClick={this.openUpload}>打开 em 上传列表</MButton>
      </div>
    );
  }
}

export default Demo;
```

### 开启拖拽

```jsx
import { Component } from 'react';
import {MUpload, MUploadData, UploadData} from '@weapp/ui';
import { imgDeletedData } from '../mock';

const uploadParams = {
  module: 'document'
}

class UploadDemo extends Component {
  state = {
    listT: imgDeletedData,
    data:[]
  }

  onChange = (uploadedData?: any, uploadingData?: any) => {
    console.error('onChange', uploadedData, uploadingData)
  }
    onChange2 = (uploadedData?: any, uploadingData?: any) => {
      this.setState({ data: uploadedData })
    }

  onImageChange = (lsitT?: any, listB?: any) => {
    this.setState({ lsitT })
  }

  onSortEnd = (data: UploadData) => {
    console.error('onSortEnd', data)
  }

  onChangeByImg = () => (uploadedData?: any, uploadingData?: any) => {
    console.log(uploadedData, uploadingData)
    this.setState({ uploadedData: uploadedData, uploadingData: uploadingData })
  }

  handleChange = (listT: MUploadData[]) => {
    this.setState({ listT })
  }

  render() {
    const { listT, data } = this.state;
    return (
      <div>
        <h3>开启拖拽 - 图片列表</h3>
        <MUpload
          uploadParams={uploadParams}
          onChange={this.onChange}
          onSortEnd={this.onSortEnd}
          buttonType='image'
          listType='img'
          limitType='png,jpg,jpeg'
          sortable
        />
        <h3>开启拖拽 - 文件列表</h3>
        <MUpload
          uploadParams={uploadParams}
          onChange={this.onChange2}
          onSortEnd={this.onSortEnd}
          buttonType='default'
          listType='list'
          sortable
          data={data}
        />
        <h3>图片列表 - 已删除展示</h3>
        <MUpload
         
          data={listT}
          listType={'img'}
          buttonType={'image'}
          limitType={'png,jpg'}
          sortable={true}
          uploadParams={uploadParams}
          onChange={this.onChange}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 附件详情

```jsx
import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { MUpload, MButton, MDialog, MUploadData, Empty, Icon } from '@weapp/ui';
import { utils } from '@weapp/ui';
import { data } from '../mock';

const { formatParentPath } = utils;
const MUploadDetail = MUpload.MUploadDetail
class UploadDemo extends React.Component<RouteComponentProps> {
  state = { data: data }
  onChange = (data?: MUploadData[]) => {
    console.log(2222, data)
    this.setState({ data })
  }
  showMDialogByRoute = () => {
    let parentPath = formatParentPath(this.props as any)
    this.props.history.push(`${parentPath}/route`);
  }
  showMDialogByRoute2 = () => {
    let parentPath = formatParentPath(this.props as any)
    this.props.history.push(`${parentPath}/route2`);
  }
  showMDialogByRouteSec = () => {
    let parentPath = formatParentPath(this.props as any)
    this.props.history.push(`${parentPath}/route/second`);
  }
  onCloseRoute = () => {
    this.props.history.go(-1);
  }
  emptyContent = (
    <Empty
     
      title={'请上传不大于20MB的附件'}
      image={(
        <Icon
         
          name="Icon-empty-file"
          style={{ width: 100, height: 100 }}
        />
      )}
    />
  )
  render() {
    let parentPath = formatParentPath(this.props as any)
    return (<div>
      <h3>打开详情页面</h3>
      <MButton onClick={this.showMDialogByRoute} type="primary">打开详情页面</MButton>
      <MDialog
        destroyOnClose
        path={`${parentPath}/route`}
        isRouteLayout={true}
      >
        <MUploadDetail
          // data={this.state.data}
          // uploadUrl="/file/upload"
          uploadParams={{
            module: 'document'
          }}
          onChange={this.onChange}
          limitType='png,jpg,doc'
          maxSize={30}
        />
      </MDialog>
      <h3>自定义空附件提示</h3>
      <MButton onClick={this.showMDialogByRoute2} type="primary">打开详情页面（空）- 自定义</MButton>
      <MDialog
        destroyOnClose
        path={`${parentPath}/route2`}
        isRouteLayout={true}
      >
        <MUploadDetail
          uploadParams={{
            module: 'document'
          }}
          limitType='png,jpg,doc'
          maxSize={30}
          emptyContent={this.emptyContent}
        />
      </MDialog>
    </div>
    );
  }
}

export default withRouter(UploadDemo);
```

### SDK 测试

```jsx
import { Component } from 'react';
import { MUpload, MUploadData, ListData, MIFile } from '@weapp/ui';
import { data } from '../mock';
const { MFileList } = MUpload;
class UploadDemo extends Component {
  state = {
    data: data,
    imgData: data.map(val => {
      val.fileid = val.fileid;
      return val;
    }),
    uploading: data
  }
  onChange = (data?: MUploadData[]) => {
    this.setState({ data })
  }
  onDelete = (item: MUploadData, listT: MUploadData[], listB: ListData[]) => {
    console.log('this.state.data', this.state.data)
    console.log('item', item)
    console.log('listT', listT)
    console.log('listB', listB)
    this.setState({ data: listT })
  }
  handleChange = (data?: MUploadData[], uploading?: MUploadData[]) => {
    console.log('handleChange', data, uploading)
    this.setState({
      data,
      uploading
    })
  }
  handleChange1 = (imgData?: MUploadData[], imgDataLoading?: MUploadData[]) => {
    this.setState({
      imgData,
      imgDataLoading
    })
  }
  onSuccess = (file: MIFile, errorInfo: string, response?: any) => {
    console.log('onSuccess', file, errorInfo, response)
  }
  handleOptionClick = (value: any, fileData: MUploadData, fileIndex: number) => {
    console.log('handleOptionClick', value)
  }
  batchUploadCompleted = (successFiles: MIFile[], failedFiles: MIFile[], total?: number | undefined) => {
    console.log('batchUploadCompleted', successFiles, failedFiles, total)
  }
  render() {
    return (
      <div>
        <h4>默认</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          maxCount={3}
        />
        <h4>仅拍照</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          sourceType={['camera']}
          maxCount={1}
        />
        <h4>仅录像</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          sourceType={['video']}
        />
        <h4>仅文件</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          sourceType={['file']}
          multiple={false}
        />
        <h4>仅相册 - 默认</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          sourceType={['album']}
        />
        <h4>相册，选择图片</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          sourceType={['album']}
          ablumType={'photo'}
        />
        <h4>相册，选择视频</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          sourceType={['album']}
          ablumType={'video'}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 手动上传

```jsx
import React, { Component } from 'react';
import { MUpload, MButton, MUploadData, ListData, MIFile } from '@weapp/ui';
import { data } from '../mock';
const { MFileList } = MUpload;
class UploadDemo extends Component {
  uploadInsRef = React.createRef<any>()
  uploadInstance: any;
  state = {
    data: data,
    data1: data,
    imgData: data.map(val => {
      val.fileid = val.fileid;
      return val;
    }),
    uploading: data,
    uploadingData: [],
    uploadingData1: []
  }
  getUploadInsRed = (el: any) => {
    console.log('getUploadInsRed')
    console.log('el', el)
    this.uploadInsRef = el
  }
  onChange = (data?: MUploadData[], uploading?: MUploadData[], reUpload?: boolean) => {
    this.setState({ data, uploadingData: uploading })
    console.log(data, uploading, reUpload)
  }
  onChange1 = (data?: MUploadData[], uploading?: MUploadData[], reUpload?: boolean) => {
    this.setState({ data1: data, uploadingData1: uploading })
  }
  onDelete = (item: MUploadData, listT: MUploadData[], listB: ListData[]) => {
    console.log('this.state.data', this.state.data)
    console.log('item', item)
    console.log('listT', listT)
    console.log('listB', listB)
    this.setState({ data: listT })
  }
  handleChange = (data?: MUploadData[], uploading?: MUploadData[]) => {
    console.log('handleChange', data, uploading)
    this.setState({
      data,
      uploading
    })
  }
  handleOptionClick = (value: any, fileData: MUploadData, fileIndex: number) => {
    console.log('handleOptionClick', value)
  }
  onError = (file: any, errorInfo: string, response?: any) => {
    console.log(errorInfo)
  }

  sureUpload = () => {
    (this.uploadInsRef as any)?.startUpload()
  }
  chooseFile = () => {
    (this.uploadInsRef as any)?.uploaderRef?.onClick()
  }
  chooseFile1 = () => {
    this.uploadInstance?.onClick()
  }

  editSec = () => {
    const { uploadingData } = this.state;
    let _uploadingData = uploadingData.map((item: any) => {
      item.secretLevel = (Number(item?.secretLevel || 0) + 1).toString();
      if (item.secretLevel === '1') {
        item.secretLevelValidity = '20年'
      } else if (item.secretLevel === '2') {
        item.secretLevelValidity = '10个月'
      } else {
        delete item.secretLevelValidity;
      }
      return item;
    });
    console.log('_uploadingData', _uploadingData)
    this.setState({ uploadingData: _uploadingData })
  }
  editSec2 = () => {
    const { uploadingData } = this.state;
    let _uploadingData = uploadingData.map((item: any) => {
      item.secretLevel = (Number(item.secretLevel) - 1).toString();
      if (item.secretLevel === '1') {
        item.secretLevelValidity = '20年'
      } else if (item.secretLevel === '2') {
        item.secretLevelValidity = '10个月'
      } else {
        delete item.secretLevelValidity;
      }
      return item;
    });
    console.log('_uploadingData', _uploadingData)
    this.setState({ uploadingData: _uploadingData })
  }
  deleteUploading = () => {
    this.setState({ uploadingData: [] })
  }
  deleteUploading1 = () => {
    this.setState({ uploadingData1: [] })
  }
  onUploading = (status: string, listT: MUploadData[], listB: ListData[]) => {
    console.log('onUploading status', status, listT, listB)
  }

  getInstance = (uploadInstance: any) => {
    this.uploadInstance = uploadInstance;
  }
  startUpload1 = () => {
    console.log(this.uploadInstance)
    this.uploadInstance?.startUpload()
  }
  render() {
    return (
      <div>
        <h4>文件上传</h4>
        <MUpload
          wrappedComponentRef={this.getUploadInsRed}
         
          // onError={this.onError}
          onChange={this.onChange}
          uploadingData={this.state.uploadingData}
          uploadParams={{
            module: 'document'
          }}
          autoUpload={false}
          secretProtect
          secretLevel={'3'}
          onUploading={this.onUploading}
        // secretProtect
        // secretLevel={'3'}
        // onOptionClick={this.handleOptionClick}
        />
        <MButton onClick={this.editSec}>修改密级 +1</MButton>
        <MButton onClick={this.editSec2}>修改密级 -1</MButton>
        <div></div>
        <MButton onClick={this.deleteUploading}>移除待上传文件</MButton>
        <div></div>
        <MButton onClick={this.chooseFile}>选择文件</MButton>
        <MButton
         
          type='primary'
          onClick={this.sureUpload}
        >
          确定上传
        </MButton>
        <h4>instance 手动上传</h4>
        <MUpload
          uploadParams={{
            module: 'document'
          }}
          autoUpload={false}
          uploadingData={this.state.uploadingData1}
          onChange={this.onChange1}
          getInstance={this.getInstance}
        />
        <MButton onClick={this.deleteUploading1}>移除待上传文件</MButton>
        <MButton onClick={this.chooseFile1}>选择文件</MButton>
        <MButton
         
          type='primary'
          onClick={this.startUpload1}
        >
          确定上传
        </MButton>
      </div>
    );
  }
}

export default UploadDemo;
```

### 自定义上传按钮

```jsx
import { Component, ReactNode } from 'react';
import { MUpload, MUploadData, MIFile, MButton, Icon, IFile } from '@weapp/ui';
import { data } from '../mock';
class UploadDemo extends Component {
  state = {
    data: [],
    imgData: [],
    uploading: []
  }
  onChange = (data?: MUploadData[]) => {
    this.setState({ data })
  }
  onSuccess = (file: MIFile, errorInfo: string, response?: any) => {
    console.log('onSuccess', file, errorInfo, response)
  }
  handleOptionClick = (value: any, fileData: MUploadData, fileIndex: number) => {
    console.log('handleOptionClick', value)
  }
  onError = (file: any, errorInfo: string, response?: any) => {
    console.log(errorInfo)
  }
  renderUploadButton = (eventProps: any, inputDom: ReactNode) => {
    const { onClick, onPaste, ...restProps } = eventProps
    return <div {...restProps} >
      {inputDom}
      <MButton type="primary"
        onClick={onClick}
        {...restProps}
      >
        <Icon name="Icon-upload02" />
        {'自定义上传按钮'}
      </MButton>
    </div>
  }
  /** 渲染已上传按钮 */
  renderUploadedButton = (eventProps: any, inputDom: ReactNode) => {
    const { data } = this.state;
    const { onClick, onDetail, ...restProps } = eventProps;
    // onClick 打开文件选择
    // onDetail 打开详情页面
    // 需要自行根据需要配置
    return <MButton {...restProps} onClick={onDetail} type={'danger'}>
      已上传附件数量：{data.length}
      {inputDom}
    </MButton>
  }
  onAdd = (files: IFile[], listB: IFile[]) => {
    console.log('files', files)
  }
  render() {
    const { data } = this.state;
    return (
      <div>
        <h4>自定义上传按钮</h4>
        <MUpload
          onError={this.onError}
          onChange={this.onChange}
          uploadParams={{
            module: 'document'
          }}
          data={data}
          onOptionClick={this.handleOptionClick}
          renderUploadButton={this.renderUploadButton}
        />
        <h4>自定义已上传 lable 区域</h4>
        <MUpload
          onError={this.onError}
          onChange={this.onChange}
          uploadParams={{
            module: 'document'
          }}
          data={data}
          onOptionClick={this.handleOptionClick}
          renderUploadButton={this.renderUploadButton}
          renderUploadedButton={this.renderUploadedButton}
        />
        <h4>自定义已上传 label 名称</h4>
        <MUpload
          onError={this.onError}
          onChange={this.onChange}
          uploadParams={{
            module: 'document'
          }}
          data={data}
          onOptionClick={this.handleOptionClick}
          onAdd={this.onAdd}
          label='附件'
        />
        <h4>自定义上传按钮不显示已上传和待上传列表</h4>
        <MUpload
                 onChange={this.onChange}
                 uploadParams={{
                   module: 'document'
                 }}
                 data={data}
                 onOptionClick={this.handleOptionClick}
                 onAdd={this.onAdd}
                 label='附件'
                 renderUploadButton={this.renderUploadButton}
                 renderUploadedButton={this.renderUploadedButton}
                 showListUploading={false}
                 showListUploaded={false}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 文件操作配置

```jsx
import React, { Component } from 'react';
import { MUpload, UploadData, SelectOptionData, MInput, MButton, Tag } from '@weapp/ui';
import { data, uploadingdata2 } from '../mock';

const operateOptions = [
  [
    { id: 'custom1', content: '自定义1', icon: "Icon-delete" },
    { id: 'custom2', content: '自定义2', icon: "Icon-Account-security" },
    { id: 'custom3', content: '自定义3', icon: "Icon-Advanced-search" },
  ], [
    { id: 'custom1', content: '自定义1', icon: "Icon-delete" },
    { id: 'custom2', content: '自定义2', icon: "Icon-Advanced-search" },
  ], [
    { id: 'custom1', content: '自定义1', icon: "Icon-delete" },
    { id: 'custom2', content: '自定义2', icon: "Icon-Account-security" },
    { id: 'custom3', content: '自定义3', icon: "Icon-Advanced-search" },
  ]
];
const optionsMap = [
  {
    id: 'delete',
    content: '删除附件'
  },
  {
    id: 'edit',
    content: '编辑附件'
  },
  {
    id: 'preview',
    content: '预览附件'
  },
  {
    id: 'download',
    content: '下载附件'
  },
  {
    id: 'version',
    content: '查看历史版本'
  },
  {
    id: 'reupload',
    content: '替换附件'
  },
  {
    id: 'editSecLevel',
    content: '修改密级'
  },
  {
    id: 'appeal',
    content: '申述'
  },
  {
    id: 'sign',
    content: '发起签署'
  },
  {
    id: 'signFirst',
    content: '对方先签'
  },
  {
    id: 'signBack',
    content: '退回签署'
  },
  {
    id: 'share',
    content: '签署链接'
  },
  {
    id: 'signinv',
    content: '作废签署'
  },
  {
    id: 'apply',
    content: '申请签署'
  },
]
const uploadingOptionsMap = [{
  id: 'delete',
  content: '删除附件'
}, {
  id: 'editSecLevel',
  content: '修改密级'
}]

class UploadDemo extends Component<any> {

  uploadInsRef = React.createRef<any>()

  state = {
    data: data,
    uploadingData: uploadingdata2,
    uploadedOptionsWhitesStr: '',
    uploadedOptionsBlacksStr: '',
    uploadingOptionsWhitesStr: '',
    uploadingOptionsBlacksStr: ''
  }

  onChange = (data?: UploadData[], uploadingData?: any[]) => {
    this.setState({ data, uploadingData })
  }

  onOptionClick = (value: string | SelectOptionData) => {
    console.log(value)
  }

  onWhiteChange = (value: React.ReactText) => {
    this.setState({ uploadedOptionsWhitesStr: value });
  }
  onBlackChange = (value: React.ReactText) => {
    this.setState({ uploadedOptionsBlacksStr: value });
  }
  onUploadingWhiteChange = (value: React.ReactText) => {
    this.setState({ uploadingOptionsWhitesStr: value });
  }
  onUploadingBlackChange = (value: React.ReactText) => {
    this.setState({ uploadingOptionsBlacksStr: value });
  }
  startUpload = () => {
    this.uploadInsRef?.current?.startUpload()
  }

  render() {
    const { data, uploadingData, uploadedOptionsBlacksStr, uploadedOptionsWhitesStr, uploadingOptionsBlacksStr, uploadingOptionsWhitesStr } = this.state;
    const uploadedOptionsBlacks = uploadedOptionsBlacksStr.split(',');
    const uploadedOptionsWhites = uploadedOptionsWhitesStr.split(',');
    const uploadingOptionsBlacks = uploadingOptionsBlacksStr.split(',');
    const uploadingOptionsWhites = uploadingOptionsWhitesStr.split(',');
    return (
      <div>
        <h3>已上传操作按钮白名单</h3>
        <MInput value={uploadedOptionsWhitesStr} onChange={this.onWhiteChange} placeholder='填写已上传操作按钮白名单,逗号分隔' />
        <h3>已上传操作按钮黑名单</h3>
        <MInput value={uploadedOptionsBlacksStr} onChange={this.onBlackChange} placeholder='填写已上传操作按钮黑名单,逗号分隔' />
        <p>
          常用操作配置：
        </p>
        <div>
          {optionsMap.map(item => {
            return <Tag key={item.id} radius style={{
              margin: 4
            }}>
              {item.content}: {item.id}
            </Tag>
          })}
        </div>
        <h3>待上传操作按钮白名单</h3>
        <MInput value={uploadingOptionsWhitesStr} onChange={this.onUploadingWhiteChange} placeholder='填写待上传操作按钮白名单,逗号分隔' />
        <h3>待上传操作按钮黑名单</h3>
        <MInput value={uploadingOptionsBlacksStr} onChange={this.onUploadingBlackChange} placeholder='填写待上传操作按钮黑名单,逗号分隔' />
        <p>
          常用操作配置：
        </p>
        <div>
          {uploadingOptionsMap.map(item => {
            return <Tag key={item.id} radius style={{
              margin: 4
            }}>
              {item.content}: {item.id}
            </Tag>
          })}
        </div>
        <MUpload
         
          data={data}
          uploadingData={uploadingData}
          uploadUrl="/file/upload"
          onChange={this.onChange}
          uploadParams={{
            module: 'document'
          }}
          wrappedComponentRef={this.uploadInsRef}
          autoUpload={false}
          secretProtect
          secretLevel='1'
          operateOptions={operateOptions}
          uploadedOptionsBlacks={uploadedOptionsBlacksStr ? uploadedOptionsBlacks : undefined}
          uploadedOptionsWhites={uploadedOptionsWhitesStr ? uploadedOptionsWhites : undefined}
          uploadingOptionsBlacks={uploadingOptionsBlacksStr ? uploadingOptionsBlacks : undefined}
          uploadingOptionsWhites={uploadingOptionsWhitesStr ? uploadingOptionsWhites : undefined}
          onOptionClick={this.onOptionClick}
        />
        <MButton onClick={this.startUpload}>触发上传</MButton>
      </div>
    );
  }
}

export default UploadDemo;
```

### h5 仅拍照

```jsx
import { Component } from 'react';
import { Input, MUpload } from '@weapp/ui';

class UploadDemo extends Component {
  state = {
    accept: 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/pdf,image/jpeg,image/png,image/gif,image/bmp,application/zip'
  }

  handleInputChange = (v: any) => {
    this.setState({ accept: v })
  }
  render() {
    const { accept } = this.state;
    return (
      <div>
        <h3>h5 仅拍照  accept="image/*"  capture="camera"</h3>
        <MUpload
          accept="image/*"
          capture="camera"
        />
        <h3>h5 仅拍照  limitType='png'  capture="camera"</h3>
        <MUpload
          limitType='png'
          capture="camera"
        />
        <h3>待上传列表配置 - uploadingOptions</h3>
        <MUpload
          accept="image/*"
        />
        <h3>input 调用拍照</h3>
        <input type="file" accept="image/*" capture="camera" />
        <h3>pdf 测试</h3>
        <Input value={accept} onChange={this.handleInputChange} />
        <input type='file' accept={accept} />
      </div>
    );
  }
}

export default UploadDemo;
```

### 附件信息复写

```jsx
import { Component } from 'react';
import { MUpload, MUploadData } from '@weapp/ui';
import { dayjs } from '@weapp/utils';
import { data, uploadingOptions, uploadingdata2 } from '../mock';

const style = {

}

class UploadDemo extends Component {
  state = {
    data: data,
  }
  renderContentUploaded = (item: MUploadData, eventProps: any) => {
    let nameStyle = {
      width: '100%',
      display: 'flex',
      color: 'red'
    }
    let fileName = {
      width: "100%",
      overflow: 'hidden',
      textOverflow: 'ellipsis',
    }
    let itemStyle = {
      width: '100%',
      display: 'flex',
      color: "#999",
      marginTop: '4px'
    }
    let uploadUserName = {
      marginRight: '10px'
    }

    const sizeSpan = item.size > 1024 * 1024 ? `${Math.floor(item.size / 1024 / 1024)}M` : `${Math.floor(item.size / 1024)}KB`

    return <div>
      <div style={nameStyle}>
        <div style={fileName}>{item.name}</div>
        <div>{item.fileid === '2' ? '(主文档)' : ''}</div>
      </div>
      {item?.validity && <div style={itemStyle}>{item.validity}</div>}
      <div style={itemStyle}>
        <div style={uploadUserName}>{item.uploadUserName}</div>
        <div>{dayjs(item.uploadTime).format('YYYY-MM-DD HH:mm:ss')}</div>
      </div>
      {item?.size && <div style={itemStyle}>{sizeSpan}</div>}
      {item?.ban && <div style={itemStyle}>{item.ban}</div>}
      {item?.signTip && <div style={itemStyle}>{item.signTip}</div>}
    </div>
  }
  handleChange = (listT?: MUploadData) => {
    this.setState({ data: listT })
  }
  render() {
    const { data } = this.state;
    return (
      <div>
        <MUpload
          data={data}
          renderContentUploaded={this.renderContentUploaded}
          onChange={this.handleChange}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### title 复写

```jsx
import { Component } from 'react';
import { MUpload, MUploadData } from '@weapp/ui';
import { data } from '../mock';

let flexStyle = {
  display: 'flex',
  color: 'red'
}

let fileNameStyle = {
  width: '100%',
  overflow: 'hidden',
  textOverflow: 'ellipsis'
}

class UploadDemo extends Component {
  renderTitleUploaded = (item: MUploadData) => {
    if (item.fileid === '2') {
      return <div style={flexStyle}>
        <div style={fileNameStyle}>{item.name}</div>
        <div>(主文档)</div>
      </div>
    }
    return item.name;
  }
  render() {
    return (
      <div>
        <MUpload
          data={data}
          renderTitleUploaded={this.renderTitleUploaded}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 待上传列表自定义渲染

```jsx
import { Component } from 'react';
import { MUpload, MUploadData, UploadData, ListData, MIFile } from '@weapp/ui';
import { data, mp4, appealData, uploadingdata } from '../mock';

const { MFileList } = MUpload;
class UploadDemo extends Component {
  state = {
    data: data,
    imgData: data.map(val => {
      val.fileid = val.fileid;
      return val;
    }),
    uploading: data
  }
  onDelete = (item: MUploadData, listT: MUploadData[], listB: ListData[]) => {
    console.log('this.state.data', this.state.data)
    console.log('item', item)
    console.log('listT', listT)
    console.log('listB', listB)
    this.setState({ data: listT })
  }
  handleChange = (data?: MUploadData[], uploading?: MUploadData[]) => {
    console.log('handleChange', data, uploading)
    this.setState({
      data,
      uploading
    })
  }
  handleChange1 = (imgData?: MUploadData[], imgDataLoading?: MUploadData[]) => {
    this.setState({
      imgData,
      imgDataLoading
    })
  }
  renderUploadingContent = (item: MUploadData) => {
    return (
      <>
        {item.name}
        {console.log('item', item)}
        <button>自定义渲染</button>
        {item.size}
      </>
    )
  }
  render() {
    return (
      <div>
        <h4>文件列表（待上传）</h4>
        <MFileList
         
          uploadingData={this.state.uploading}
          onDelete={this.onDelete}
          maxSize={30}
          onChange={this.handleChange}
          renderUploadingContent={this.renderUploadingContent}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 修改传递文件的参数

```jsx
import React, { Component } from 'react';
import { MUpload, MDialog, MInput, MSelect, MButton } from '@weapp/ui';
import { request } from '@weapp/utils';
import { data, secData, secUploadingData } from '../mock';

class UploadDemo extends Component {

  render() {
    return (
      <div>
        <MUpload
         
          uploadParams={{
            module: 'document'
          }}
          isDeleteConfirm
          fileDataName='data'
        />
      </div >
    );
  }
}

export default UploadDemo;
```

### 附件名称重复校验

```jsx
import React, { Component } from 'react';
import { MUpload, MDialog, MInput, MSelect, MButton } from '@weapp/ui';
import { request } from '@weapp/utils';
import { data, secData, secUploadingData } from '../mock';

class UploadDemo extends Component {

  render() {
    return (
      <div>
        <h3>附件名称重复校验</h3>
        <MUpload
         
          uploadParams={{
            module: 'document'
          }}
          isDeleteConfirm
          fileDataName='data'
          checkName
          directoryId="200"
        />
      </div >
    );
  }
}

export default UploadDemo;
```

### 附件敏感词检测

```jsx
import React, { PureComponent } from 'react';
import { MUpload } from '@weapp/ui';

let result: any = {
  code: 200,
  status: true,
  message: 'successful',
  data: {
    fileid: '733496511975596033',
    name: '00-钉钉模块_泛微e-colgy与阿里钉钉集成配置手册2015V4.0.docx',
    size: 1622313,
    extName: 'docx',
    type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    img: false,
    uploadUser: '1554612592646902621',
    uploadUserName: '许平源',
    uploadTime: 1653980465964,
    doc: false,
    docId: '0',
    loadlink:
      '',
    options: [
      { id: 'preview', icon: 'Icon-custom34-o', content: '预览', moreType: false },
      { id: 'edit', icon: 'Icon-daily-o', content: '编辑', moreType: false },
      { id: 'download', icon: 'Icon-download02', content: '下载', moreType: false },
      { id: 'rename', icon: 'Icon-rename', content: '重命名', moreType: true },
      { id: 'version', icon: 'Icon-Unfinished-business-o', content: '历史版本', moreType: true },
      { id: 'reupload', icon: 'Icon-Left-refresh', content: '重新上传', moreType: true },
      { id: 'delete', icon: 'Icon-delete', content: '删除', moreType: false },
    ],
    uploadType: 'common',
    ban: false,
    mainAccess: false,
  },
};
result = {
  code: 300,
  status: false,
  message: 'error',
  data: {
    id: '733496511975596033', //文件id
    name: '+ +.docx', //文件名
    ban: true, //是否涉及敏感词，true ，涉及，false 不涉及
    sensitiveWords: '暴力，暴动', //具体的敏感词信息
  },
};
const datas = [
  {
    fileid: '733496511975596033',
    name: '00-钉钉模块_泛微e-colgy与阿里钉钉集成配置手册2015V4.0.docx',
    size: 1622313,
    extName: 'docx',
    type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    img: false,
    uploadUser: '1554612592646902621',
    uploadUserName: '许平源',
    uploadTime: 1653980465964,
    doc: false,
    docId: '0',
    ban: true, //是否涉及敏感词，true ，涉及，false 不涉及
    sensitiveWords: '暴力，暴动', //具体的敏感词信息
    sensitiveStatus: 2, //检测状态，0未检测，1，检测中，2，检测完成
    options: [
      {
        id: 'preview',
        icon: 'Icon-custom34-o',
        content: '预览',
        moreType: false,
      },
      {
        id: 'edit',
        icon: 'Icon-daily-o',
        content: '编辑',
        moreType: false,
      },
      {
        id: 'download',
        icon: 'Icon-download02',
        content: '下载',
        moreType: false,
      },
      {
        id: 'rename',
        icon: 'Icon-rename',
        content: '重命名',
        moreType: true,
      },
      {
        id: 'version',
        icon: 'Icon-Unfinished-business-o',
        content: '历史版本',
        moreType: true,
      },
      {
        id: 'reupload',
        icon: 'Icon-Left-refresh',
        content: '重新上传',
        moreType: true,
      },
      {
        id: 'delete',
        icon: 'Icon-delete',
        content: '删除',
        moreType: false,
      },
    ],
    uploadType: 'common',
    mainAccess: false,
  },
  {
    fileid: '733496511975596033',
    name: '00-钉钉模块_泛微e-colgy与阿里钉钉集成配置手册2015V4.0.docx',
    size: 1622313,
    extName: 'docx',
    type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    img: false,
    uploadUser: '1554612592646902621',
    uploadUserName: '许平源',
    uploadTime: 1653980465964,
    doc: false,
    docId: '0',
    ban: true, //是否涉及敏感词，true ，涉及，false 不涉及
    sensitiveWords: '暴力，暴动', //具体的敏感词信息
    sensitiveStatus: 2, //检测状态，0未检测，1，检测中，2，检测完成
    options: [
      {
        id: 'preview',
        icon: 'Icon-custom34-o',
        content: '预览',
        moreType: false,
      },
      {
        id: 'edit',
        icon: 'Icon-daily-o',
        content: '编辑',
        moreType: false,
      },
      {
        id: 'download',
        icon: 'Icon-download02',
        content: '下载',
        moreType: false,
      },
      {
        id: 'rename',
        icon: 'Icon-rename',
        content: '重命名',
        moreType: true,
      },
      {
        id: 'version',
        icon: 'Icon-Unfinished-business-o',
        content: '历史版本',
        moreType: true,
      },
      {
        id: 'reupload',
        icon: 'Icon-Left-refresh',
        content: '重新上传',
        moreType: true,
      },
      {
        id: 'delete',
        icon: 'Icon-delete',
        content: '删除',
        moreType: false,
      },
    ],
    uploadType: 'common',
    mainAccess: false,
  },
  {
    fileid: '733496511975596033',
    name: '00-钉钉模块_泛微e-colgy与阿里钉钉集成配置手册2015V4.0.docx',
    size: 1622313,
    extName: 'docx',
    type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    img: false,
    uploadUser: '1554612592646902621',
    uploadUserName: '许平源',
    uploadTime: 1653980465964,
    doc: false,
    docId: '0',
    ban: true, //是否涉及敏感词，true ，涉及，false 不涉及
    sensitiveWords: '暴力，暴动', //具体的敏感词信息
    sensitiveStatus: 2, //检测状态，0未检测，1，检测中，2，检测完成
    options: [
      {
        id: 'preview',
        icon: 'Icon-custom34-o',
        content: '预览',
        moreType: false,
      },
      {
        id: 'edit',
        icon: 'Icon-daily-o',
        content: '编辑',
        moreType: false,
      },
      {
        id: 'download',
        icon: 'Icon-download02',
        content: '下载',
        moreType: false,
      },
      {
        id: 'rename',
        icon: 'Icon-rename',
        content: '重命名',
        moreType: true,
      },
      {
        id: 'version',
        icon: 'Icon-Unfinished-business-o',
        content: '历史版本',
        moreType: true,
      },
      {
        id: 'reupload',
        icon: 'Icon-Left-refresh',
        content: '重新上传',
        moreType: true,
      },
      {
        id: 'delete',
        icon: 'Icon-delete',
        content: '删除',
        moreType: false,
      },
    ],
    uploadType: 'common',
    mainAccess: false,
  },
];
class UploadDemo extends PureComponent {
  uploadParams = {
    module: 'document',
  };
  mockFetch = (options: any) => {
    return new Promise((res, rej) => {
      console.log(options);
      res(result);
    });
  };
  render() {
    return (
      <div>
        <h3>模拟上传接口</h3>
        <MUpload
         
          data={datas}
          uploadParams={this.uploadParams}
          checkSensitiveWords={true}
          fetch={this.mockFetch}
        />
        <h3>无模拟上传接口</h3>
        <MUpload
         
          data={datas}
          uploadParams={this.uploadParams}
          checkSensitiveWords={true}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 批量操作

```jsx
import { Component } from 'react';
import { MUpload, MUploadData, ListData, MIFile, UploadData, MListData } from '@weapp/ui';
import { mp4, appealData, uploadingdata } from '../mock';
import { upingData } from '../mock';

const { MFileList } = MUpload;

const uploadParams = {
  module: 'document'
}

const uploadIngList = ('0,'.repeat(50).split(',')).map((v, i) => ({
  file: undefined,
  fileId: 'sdfsdfsdfsdsdfsd' + i,
  fileName: 'ces',
  filePath: 'sdfsdf',
  fileSize: 687,
  name: '测试',
  secretLevel: '2',
  secretLevelValidity: '十年',
  size: 687,
  uid: 'tsx234'
}));

class UploadDemo extends Component {
  state = {
    data: [],
    uploadingDemodata: upingData,
  }

  onChange = (uploadedData?: UploadData[], uploadingData?: MListData[]) => {
    console.log(uploadedData)
    this.setState({ data: uploadedData })
    this.setState({ uploadingDemodata: uploadingData });
  }

  render() {
    const { data } = this.state;
    return (
      <div>
        <h3>批量操作 - 批量签署</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          data={data}
          onChange={this.onChange}
          showBatchSign
        />
        <h3>批量操作 - 批量删除（不走接口）</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          data={data}
          onChange={this.onChange}
          batchDelete
          isDeleteConfirm
        />
        <h3>批量操作 - 批量删除（走接口）</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          data={data}
          onChange={this.onChange}
          batchDelete
          isDeleteConfirm
          isDeleteInterface
        // 目前组件内置业务的批量删除 url，文档模块需要自行设置文档模块自己的批量删除 url
        // batchDeleteURL={'/{api}/file/dl'}
        />
        <h3>批量操作 - 批量下载</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          data={data}
          onChange={this.onChange}
          batchDownload
        />
        <h3>批量操作</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          data={data}
          onChange={this.onChange}
          batchDownload
          batchDelete
          showBatchSign
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 单独使用敏感词提示面板

抛出敏感词面板，模块可以直接使用敏感词提示面板的展示功能

```jsx
import { Component } from 'react';
import { MUpload, MButton } from '@weapp/ui';
import { withRouter } from 'react-router-dom';

const { MSensitiveWordsDialog } = MUpload;

// @ts-ignore
@withRouter
class UploadDemo extends Component<any> {

  state = {
    data: [{
      name: '有问题附件',
      sensitiveWords: '测试,111'
    }, {
      name: '有问题的列表',
      sensitiveWords: '法轮'
    }],
    parentPath: window.location.pathname,
    randomRoute: 'words'
  }
  changeVisible = () => {
    const { parentPath, randomRoute } = this.state;
    // this.setState({ visible: !this.state.visible })
    this.props?.history?.push(`${parentPath}/sensitiveWords-${randomRoute}`);
  }
  onClose = (files: any) => {
    this.props?.history?.go(-1);
  }
  render() {
    const { data, randomRoute, parentPath } = this.state;
    return (
      <div
        style={{ overflow: 'hidden' }}
      >
        <MButton onClick={this.changeVisible}>点击弹出敏感词提示</MButton>
        <MSensitiveWordsDialog
          data={data}
          parentPath={parentPath}
          randomRoute={randomRoute}
          onClose={this.onClose}
          onSure={this.onClose}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### MFileAList新模式测试

```jsx
import { Component } from 'react';
import { MUpload, MUploadData, ListData, MIFile } from '@weapp/ui';
import { mp4, appealData, uploadingdata } from '../mock';
import { data, upingData } from '../mock';
import Button from '../../../../components/button';
const { MFileList } = MUpload;

const uploadParams = {
  module: 'document'
}

const uploadIngList = ('0,'.repeat(3).split(',')).map((v, i) => ({
  file: undefined,
  fileId: 'sdfsdfsdfsdsdfsd' + i,
  fileName: 'ces',
  filePath: 'sdfsdf',
  fileSize: 687,
  name: '人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2.xls',
  secretLevel: '2',
  secretLevelValidity: '十年',
  size: 687,
  uid: 'tsx234'
}));

// const data = ('0,'.repeat(50).split(',')).map((v, i) => ({
//   "fileid": "3084187008955059269" + i,
//   "name": "人员信息放到放假快点放假看副本2.xls",
//   "extName": "xls",
//   "size": 192621,
//   "uploadTime": 2022,
//   "img": true,
//   "loadlink": "/papi/file/preview?fileId=3084187008955059269&type=imgs&imgFormat=small",
//   "options": [
//     { content: "删除", icon: "", id: "delete" }
//   ],
//   "uid": "p12w59"
// }));

class UploadDemo extends Component {
  state = {
    uploadingList: uploadIngList,
    data: data,
    uploadingDemodata: upingData,
    readOnly: false,
    fileListType: 'useDetail'  as 'useDetail' | 'noUseDetail'
  }

  handleChange = (uploadedData?: MUploadData[], uploadingData?: MUploadData[]) => {
    console.log('uploadedData', uploadedData)
    console.log('uploadingData', uploadingData)
    this.setState({ uploadingList: uploadingData })
  }
  onChange = (uploadedData?: any, uploadingData?: any) => {
    console.log(uploadedData)
    this.setState({ data: uploadedData })
    this.setState({ uploadingDemodata: uploadingData });
  }
  showOnChange = (uploadedData?: MUploadData[], uploadingData?: MUploadData[]) => {
    console.log(uploadedData, uploadingData)
  }

  handleReadOnly = () => {
    const value = this.state.readOnly
    this.setState({readOnly: !value})
  }

  handleFileListType = () => {
    // let value = 'useDetail';
    if (this.state.fileListType === 'useDetail') {
      this.setState({fileListType: 'noUseDetail'})
    } else {
      this.setState({fileListType: 'useDetail'})
    }
  }

  render() {
    const { uploadingList } = this.state;
    console.log('uploadIngList', uploadingList)
    return (
      <div>
        <h3>Mupload列表状态</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          isDeleteConfirm
          batchDelete
          batchDownload
          showBatchSign
          data={data}
          showUpload={true}
          readOnly={false}
        //   fileListType={this.state.fileListType}
        fileListType={'useDetail'}
        //   uploadingData={uploadingList}
          onChange={this.handleChange}
        />
        <h3>Mupload列表 readOnly状态</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          isDeleteConfirm
          batchDelete
          batchDownload
          showBatchSign
          data={data}
          readOnly={true}
          fileListType={this.state.fileListType}
          uploadingData={uploadingList}
          onChange={this.handleChange}
        />
        <h3>Mupload列表 disabled状态</h3>
        <MUpload
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          isDeleteConfirm
          batchDelete
          batchDownload
          showBatchSign
          data={data}
        //   readOnly={true}
          disabled={true}
          fileListType={this.state.fileListType}
          uploadingData={uploadingList}
          onChange={this.handleChange}
        />
        <h3>MFileList useDetail状态</h3>
        <MFileList
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          isDeleteConfirm
          batchDelete
          batchDownload
          showBatchSign
          data={data}
          readOnly={false}
          fileListType={"useDetail"}
          uploadingData={uploadingList}
          onChange={this.handleChange}
        />
        <h3>MFileList noUseDetail状态</h3>
        <MFileList
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          isDeleteConfirm
          batchDelete
          batchDownload
          showBatchSign
          data={data}
          readOnly={false}
          fileListType={"noUseDetail"}
          uploadingData={uploadingList}
          onChange={this.handleChange}
        />
        <h3>MFileList disabled状态</h3>
        <MFileList
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          isDeleteConfirm
          batchDelete
          batchDownload
          showBatchSign
          data={data}
        //   readOnly={false}
          disabled={true}
          uploadingData={uploadingList}
          onChange={this.handleChange}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 上传文件预览事件拦截

onBeforeOptionClick控制右键菜单事件, 补充控制点击内容事件预览拦截

```jsx
import { Component } from 'react';
import { MUpload, MUploadData } from '@weapp/ui';
import { data, upingData } from '../mock';

const uploadParams = {
  module: 'document',
};

const uploadIngList = '0,'
  .repeat(3)
  .split(',')
  .map((v, i) => ({
    file: undefined,
    fileId: 'sdfsdfsdfsdsdfsd' + i,
    fileName: 'ces',
    filePath: 'sdfsdf',
    fileSize: 687,
    name: `人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2${i + 1}.xls`,
    secretLevel: '2',
    secretLevelValidity: '十年',
    size: 687,
    uid: 'tsx234',
  }));

class UploadDemo extends Component {
  state = {
    uploadingList: uploadIngList,
    data: data,
    uploadingDemodata: upingData,
  };

  handleChange = (uploadedData?: MUploadData[], uploadingData?: MUploadData[]) => {
    console.log('uploadedData', uploadedData);
    console.log('uploadingData', uploadingData);
    this.setState({ uploadingList: uploadingData });
  };
  onChange = (uploadedData?: any, uploadingData?: any) => {
    console.log(uploadedData);
    this.setState({ data: uploadedData });
    this.setState({ uploadingDemodata: uploadingData });
  };
  showOnChange = (uploadedData?: MUploadData[], uploadingData?: MUploadData[]) => {
    console.log(uploadedData, uploadingData);
  };
  onBeforeOptionClick = (value: any, item: any, index: any) => {
    if (value === 'preview' && (index === 0 || index === 1)) {
      alert(`自定义预览点击事件`);
      return false;
    }
  };
  render() {
    const { uploadingList } = this.state;
    console.log('uploadIngList', uploadingList);
    return (
      <div>
        <h3>测试点击预览触发onBeforeOptionClick</h3>
        <h4>第一个、第二个文件点击预览触发自定义事件(不可预览)</h4>
        <MUpload
         
          uploadParams={uploadParams}
          buttonType='default'
          listType='list'
          isDeleteConfirm
          data={data}
          onBeforeOptionClick={this.onBeforeOptionClick}
          uploadingData={uploadingList}
          onChange={this.handleChange}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 各空状态展示效果

各空状态展示效果

```jsx
import { Component } from 'react';
import { MUpload, MUploadData, ListData, MIFile } from '@weapp/ui';
import { mp4, appealData, uploadingdata } from '../mock';
import { data, upingData } from '../mock';
const { MFileList } = MUpload;

class UploadDemo extends Component {
  state = {
    uploadingList: uploadingdata,
    data: data,
    uploadingDemodata: upingData,
  }

  uploadParams = {
    module: 'document'
  }

  handleChange = (uploadedData?: MUploadData[], uploadingData?: MUploadData[]) => {
    console.log('uploadedData', uploadedData)
    console.log('uploadingData', uploadingData)
    this.setState({ uploadingList: uploadingData })
  }
  onChange = (uploadedData?: any, uploadingData?: any) => {
    console.log(uploadedData)
    this.setState({ data: uploadedData })
    this.setState({ uploadingDemodata: uploadingData });
  }
  showOnChange = (uploadedData?: MUploadData[], uploadingData?: MUploadData[]) => {
    console.log(uploadedData, uploadingData)
  }
  render() {
    const { uploadingList } = this.state;
    console.log('uploadIngList', uploadingList)
    return (
      <div>
        <h2>Upload</h2>
        <h3>非 readOnly/disabled</h3>
        <MUpload
          uploadParams={this.uploadParams}
        />
        <h3>readOnly/disabled - 无数据</h3>
        <MUpload
          readOnly
        />
        <h3>readOnly/disabled - 无数据(图片)</h3>
        <MUpload
          readOnly
          buttonType='image'
        />
        <h3>readOnly/disabled - 有数据</h3>
        <MUpload
          readOnly
          data={this.state.data}
        />
        <h2>cardDetailForm 中</h2>
        <h3>cardDetailForm 中：非 readOnly/disabled</h3>
        <MUpload
          uploadParams={this.uploadParams}
          isCardDetailForm
          isShowLabel
        />
        <h3>cardDetailForm 中：readOnly/disabled - 无数据</h3>
        <MUpload
          readOnly
          isCardDetailForm
          isShowLabel
        />
        <h3>cardDetailForm：readOnly/disabled - 有数据</h3>
        <MUpload
          data={this.state.data}
          readOnly
          isCardDetailForm
          isShowLabel
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 免登陆上传测试

```jsx
import { Component } from 'react';
import { MSwitch, MUpload } from '@weapp/ui';
import { data } from '../mock';

const uploadParams = {
  module: 'document',
}
class UploadDemo extends Component<any> {

  state = {
    data: data,
    loginFree: false
  }
  onClose = (files: any) => {
    console.log('files', files)
    this.setState({ visible: false })
  }
  onChange = (visible: boolean) => {
    this.setState({ loginFree: visible })
  }

  render() {
    const { loginFree } = this.state;
    // 免登陆接口要求必须传递 tenantKey，但此时客户没有登陆，所有取不到 tenantKey，可以随便传递一个值，后端不做校验
    const uploadParams = loginFree ? { module: 'document', tenantKey: 'all_teams' } : { module: 'document' }
    return (
      <div>
        <MSwitch value={loginFree} onChange={this.onChange}>{loginFree ? '免登陆' : '非免登陆'}</MSwitch>
        <h3>{loginFree ? '免登陆' : '非免登陆'}上传文件</h3>
        <MUpload
          uploadParams={uploadParams}
          loginFree={loginFree}
          batchDelete
          batchDownload
          showBatchSign
        />
        <h3>{loginFree ? '免登陆' : '非免登陆'}上传图片</h3>
        <MUpload
          uploadParams={uploadParams}
          loginFree={loginFree}
          buttonType={'image'}
          listType={'img'}
          batchDelete
          batchDownload
          showBatchSign
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 设置单次可选数量（仅 em 生效）

```jsx
import React, { Component } from 'react';
import { MInput, MUpload, MValueType } from '@weapp/ui';

const uploadParams = {
  module: 'document'
}

class UploadDemo extends Component {
  state = {
    inputValue: 3
  }
  handleInputChange = (value: MValueType) => {
    this.setState({ inputValue: value })
  }
  render() {
    const { inputValue } = this.state;
    return (
      <div>
        <h3>设置单次可选数量</h3>
        <MInput
          value={inputValue}
          onChange={this.handleInputChange}
          placeholder={'设置单次可选数量'}
        />
        <MUpload
          uploadParams={uploadParams}
          selectNum={inputValue}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 模拟上传失败提示效果

上传失败效果模拟

```jsx
import { Component } from 'react';
import { MUpload } from '@weapp/ui';
import { data,uploadingdata } from '../mock';
import { uploadData, upingData } from '../mock';

class UploadDemo extends Component {
  state = {
    uploadingList: uploadingdata,
    data: data,
    uploadingDemodata: upingData,
  };

  uploadParams = {
    module: 'documentss',
  };

  render() {
    return (
      <div>
        <h3>基本使用</h3>
        <MUpload
         
          uploadParams={this.uploadParams}
          // uploadUrl='/file/upload/error'
        />
        <h3>图片上传</h3>
        <MUpload
         
          uploadParams={this.uploadParams}
          // uploadUrl='/file/upload/error'
          listType='img'
          buttonType={'image'}
        />
        <h3>文件上传</h3>
        <MUpload
         
          uploadParams={this.uploadParams}
          // uploadUrl='/file/upload/error'
          buttonType='default'
          listType='list'
          data={uploadData}
        />
        <h3>cardDetailForm</h3>
        <MUpload
         
          uploadParams={this.uploadParams}
          isCardDetailForm
          isShowLabel
          // uploadUrl='/file/upload/error'
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 提示语

上传限制提示语内容

```jsx
import { Component } from 'react';
import { MUpload, MUploadData, ListData, MIFile } from '@weapp/ui';
import { data, mp4, appealData, uploadingdata } from '../mock';
const { MFileList } = MUpload;

const uploadParams = {
  module: 'document',
};

const uploadingList = '0,'
  .repeat(3)
  .split(',')
  .map((v, i) => ({
    file: undefined,
    fileId: 'sdfsdfsdfsdsdfsd' + i,
    fileName: 'ces',
    filePath: 'sdfsdf',
    fileSize: 687,
    name: '人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2人员信息放到放假快点放假看副本2.xls',
    secretLevel: '2',
    secretLevelValidity: '十年',
    size: 687,
    uid: 'tsx234',
  }));

// const data = ('0,'.repeat(50).split(',')).map((v, i) => ({
//   "fileid": "3084187008955059269" + i,
//   "name": "人员信息放到放假快点放假看副本2.xls",
//   "extName": "xls",
//   "size": 192621,
//   "uploadTime": 2022,
//   "img": true,
//   "loadlink": "/papi/file/preview?fileId=3084187008955059269&type=redirect&imgFormat=small",
//   "options": [
//     { content: "删除", icon: "", id: "delete" }
//   ],
//   "uid": "p12w59"
// }));

class UploadDemo extends Component {
  state = {
    data: data,
    uploadFiles: [],
    imgData: data.map((val) => {
      val.fileid = val.fileid;
      return val;
    }),
    uploading: data,
  };
  onChange = (data?: MUploadData[], uploading?: MUploadData[], reUpload?: boolean) => {
    this.setState({ data });
    console.log(data, uploading, reUpload);
  };
  onDelete = (item: MUploadData, listT: MUploadData[], listB: ListData[]) => {
    console.log('this.state.data', this.state.data);
    console.log('item', item);
    console.log('listT', listT);
    console.log('listB', listB);
    this.setState({ data: listT });
  };
  handleChange = (data?: MUploadData[], uploading?: MUploadData[]) => {
    console.log('handleChange', data, uploading);
    this.setState({
      data,
      uploading,
    });
  };
  handleChange1 = (imgData?: MUploadData[], imgDataLoading?: MUploadData[]) => {
    this.setState({
      imgData,
      imgDataLoading,
    });
  };
  onSuccess = (file: MIFile, errorInfo: string, response?: any) => {
    console.log('onSuccess', file, errorInfo, response);
  };
  handleOptionClick = (value: any, fileData: MUploadData, fileIndex: number) => {
    console.log('handleOptionClick', value);
  };
  onError = (file: any, errorInfo: string, response?: any) => {
    console.log(errorInfo);
  };
  onUploading = (status: string, listT: MUploadData[], listB: ListData[]) => {
    console.log('onUploading status', status, listT, listB);
  };
  get = () => {
    console.log(document.getElementById('2222'));
  };
  onChange1 = (
    listT?: MUploadData[] | undefined,
    listB?: MUploadData[] | undefined,
    reUpload?: boolean | undefined
  ) => {
    console.error('onChange', listT, listB, reUpload);
    this.setState({ uploadFiles: listT });
  };

  onUploadFinally = () => {
    console.log('上传结束！');
  };
  render() {
    return (
      <div>
        <h4>文件上传,限制大小</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          maxSize={20}
          displayTip={true}
        />

        <h4>文件上传,限制数量</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          maxCount={20}
          displayTip={true}
        />

        <h4>文件上传,限制格式</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          limitType='jpg,jpeg,png'
          displayTip={true}
        />

        <h4>文件上传,限制大小数量</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          maxCount={10}
          maxSize={20}
          displayTip={true}
        />

        <h4>文件上传,限制大小格式</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          limitType='jpg,jpeg,png'
          maxSize={20}
          displayTip={true}
        />

        <h4>文件上传,限制数量格式</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          limitType='jpg,jpeg,png'
          maxCount={20}
          displayTip={true}
        />

        <h4>文件上传,限制大小数量格式</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          limitType='jpg,jpeg,png'
          maxCount={20}
          maxSize={10}
          displayTip={true}
        />

        <h4>文件上传,限制大小数量格式(特殊情况限制类型多)</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          limitType='jpg,jpeg,png,mkv,mp4,avi,swf,wmv,rmvb,mpg,jpg,jpeg,pen,png,gif,bmp,psd,tif,txt,doc,docs,xls,xlsx,ppt,pptx,wps,rar,zip,7z,gz,mp3,mp4,mp5,wma,wav,aac,m4a,au,au,ram'
          maxCount={20}
          maxSize={10}
          displayTip={true}
        />

        <h4>文件上传,关闭提示语内容(displayTip=false)</h4>
        <MUpload
         
          uploadParams={{
            module: 'document',
          }}
          prohibitType={'jpg'}
          maxCount={20}
          maxSize={10}
          displayTip={false}
        />
      </div>
    );
  }
}

export default UploadDemo;
```

### 上传类型限制

通过设置 limitType, prohibitType 约束上传文件类型

```jsx
import React, { PureComponent } from 'react';
import { MUpload, MInput } from '@weapp/ui';

class LimitTypeDemo extends PureComponent<any, any> {
  state = {
    limitType: '',
    prohibitType: ''
  }
  setLimitType = (value: React.ReactText) => {
    this.setState({ limitType: value })
  }
  setProhibitType = (value: React.ReactText) => {
    this.setState({ prohibitType: value })
  }
  uploadParams = {
    module: 'document'
  }
  render() {
    const { limitType, prohibitType } = this.state;
    return (
      <div>
        <h3>limitType</h3>
        <MInput value={limitType} onChange={this.setLimitType} />
        <h3>prohibitType</h3>
        <MInput value={prohibitType} onChange={this.setProhibitType} />
        <MUpload 
          limitType={limitType}
          prohibitType={prohibitType}
          uploadParams={this.uploadParams}
        />
      </div>
    );
  }
}

export default LimitTypeDemo;
```

### 附件密级校验

```jsx
import React, { Component } from 'react';
import { MUpload, MSecretSelect, MButton, SecretSelectValueType } from '@weapp/ui';

const { getSecretLevelInfo } = MSecretSelect;
const { getAttachmentLocalSecurityInfo } = MUpload;

class UploadDemo extends Component {

  state = {
    listT: [],
    listB: [],
    isAllow: false,
    verifyFormat: '',
    isOpenClassification: false,
    secretLevel: '',
    secretLevelValidity: '',
  }

  uploadInsRef = React.createRef<any>()

  componentDidMount() {
    getSecretLevelInfo()
      .then(res => {
        this.setState({ isOpenClassification: res.isOpenClassification })
      })

    getAttachmentLocalSecurityInfo()
      .then(res => {
        this.setState({ isAllow: res.isAllow, verifyFormat: res.verifyFormat })
      })
  }
  
  startUpload = () => {
    console.log(123, this.uploadInsRef.current)
    this.uploadInsRef?.current?.startUpload()
  }

  secretChange = (value: SecretSelectValueType) => {
    this.setState({ secretLevel: value.secretLevel, secretLevelValidity: value.secretLevelValidity })
  }

  render() {
    const { isOpenClassification, isAllow, verifyFormat, secretLevel, secretLevelValidity } = this.state;

    return (
        <div>
            <h4>{isAllow ? `已开启本地标密上传，格式：${verifyFormat}` : '未开启本地标密上传'}</h4>
            {isOpenClassification ?
                <MSecretSelect
                               onChange={this.secretChange}
                /> : <div>未开启密级，请先开启密级后再使用该 demo</div>}

            <h3>自动上传</h3>
            <MUpload
               
                uploadParams={{
                    module: 'document'
                }}
                isDeleteConfirm
                // 附件密级
                secretProtect
                secretLevel={secretLevel}  // 设置附件密级信息
                secretLevelValidity={secretLevelValidity}
            />
            <h3>主动上传</h3>
            <MUpload
               
                wrappedComponentRef={this.uploadInsRef}
                uploadParams={{
                    module: 'document'
                }}
                autoUpload={false}
                isDeleteConfirm
                // 附件密级
                secretProtect
                secretLevel={secretLevel}  // 设置附件密级信息
                secretLevelValidity={secretLevelValidity}
            />
            <h3>主动上传</h3>
            <MUpload
                wrappedComponentRef={this.uploadInsRef}
                uploadParams={{
                    module: 'document'
                }}
                autoUpload={false}
                isDeleteConfirm
                // 附件密级
                secretProtect
                secretLevel={secretLevel}  // 设置附件密级信息
                secretLevelValidity={secretLevelValidity}
                localSecurityAllNonCompliantConfirm={false}
            />
            <MButton onClick={this.startUpload}>上传到服务器</MButton>

        </div>
    );
  }
}

export default UploadDemo;
```

### 密级自动调整

```jsx
import React, { Component } from 'react';
import { MUpload, MSecretSelect, MButton, SecretSelectValueType } from '@weapp/ui';

const { getSecretLevelInfo } = MSecretSelect;
const { getAttachmentLocalSecurityInfo } = MUpload;

class UploadDemo extends Component {

  state = {
    isAllow: false,
    verifyFormat: '',
    isOpenClassification: false,
    secretLevel: '',
    secretLevelValidity: '',
  }

  uploadInsRef = React.createRef<any>()

  componentDidMount() {
    getSecretLevelInfo()
      .then(res => {
        this.setState({ isOpenClassification: res.isOpenClassification })
      })

    getAttachmentLocalSecurityInfo()
      .then(res => {
        this.setState({ isAllow: res.isAllow, verifyFormat: res.verifyFormat })
      })
  }

  startUpload = () => {
    this.uploadInsRef?.current?.startUpload()
  }

  secretChange = (value: SecretSelectValueType) => {
    this.setState({ secretLevel: value.secretLevel, secretLevelValidity: value.secretLevelValidity })
  }

  render() {
    const { isOpenClassification, isAllow, verifyFormat, secretLevel, secretLevelValidity } = this.state;

    return (
      <div>
        <h4>{isAllow ? `已开启本地标密上传，格式：${verifyFormat}` : '未开启本地标密上传'}</h4>
        {isOpenClassification ?
          <MSecretSelect
            onChange={this.secretChange}
          /> : <div>未开启密级，请先开启密级后再使用该 demo</div>}

        <MUpload
         
          wrappedComponentRef={this.uploadInsRef}
          uploadParams={{
            module: 'document'
          }}
          isDeleteConfirm
          autoUpload={false}
          // 附件密级
          secretProtect
          secretLevel={secretLevel}  // 设置附件密级信息
          secretLevelValidity={secretLevelValidity}
          secretLevelAutoAdjust
        />
        <MButton onClick={this.startUpload}>上传到服务器</MButton>
      </div >
    );
  }
}

export default UploadDemo;
```

### 附件附加提示

组件默认读取：【后台管理中心】-【全局基础】-【文件设置】-【附件设置】-【附件附加提示】设置，支持通过 props.isUploadCustomMsg、props.uploadCustomMsg 覆盖全局配置

```jsx
import React from 'react';
import { MButton, MDialog, MUpload, Upload, utils } from "@weapp/ui";
import { RouteComponentProps, withRouter } from "react-router-dom";

const { formatParentPath } = utils;

const uploadParams = {
  module: 'document'
}

class Demo extends React.Component<RouteComponentProps, any> {

  state = {
    isUploadCustomMsg: true,
    uploadCustomMsg: '本平台为非涉密平台，严禁处理、传输国家秘密及核心商密内容',
  }

  componentDidMount() {
    Upload.getSystemUploadConfigAsync().then(res => {
      if (res.uploadCustomMsgEnable) {
        this.setState({
          isUploadCustomMsg: res.uploadCustomMsgEnable,
          uploadCustomMsg: res.uploadCustomMsg,
        })
      }
    })
  }

  showMDialogByRoute = () => {
    let parentPath = formatParentPath(this.props as any)
    this.props.history.push(`${parentPath}/route2`);
  }

  render() {
    const { isUploadCustomMsg, uploadCustomMsg, } = this.state;
    let parentPath = formatParentPath(this.props as any)
    return <div>
      <h3>默认</h3>
      <MUpload
        isUploadCustomMsg={isUploadCustomMsg}
        uploadCustomMsg={uploadCustomMsg}
       
        uploadParams={uploadParams}
        batchDownload={true}
      />
      <h3>图片</h3>
      <MUpload

        isUploadCustomMsg={isUploadCustomMsg}
        uploadCustomMsg={uploadCustomMsg}
       
        buttonType={'image'}
        listType={'img'}
        uploadParams={uploadParams}
      />
      <h3>直接使用详情页面</h3>
      <MButton onClick={this.showMDialogByRoute} type="primary">
        打开详情页面
      </MButton>
      <MDialog
       
        destroyOnClose
        path={`${parentPath}/route2`}
        isRouteLayout={true}
      >
        <MUpload.MUploadDetail
         
          uploadParams={uploadParams}
          isUploadCustomMsg={isUploadCustomMsg}
          uploadCustomMsg={uploadCustomMsg}
        />
      </MDialog>
      <h3>自定义按钮 - 文本提示</h3>
      <h4>移动端自定义上传按钮时默认会隐藏文本提示，可以通过设置 uploadCustomMsgTips 为 true 启用文本提示 </h4>
      <MUpload
        isUploadCustomMsg={isUploadCustomMsg}
        uploadCustomMsg={uploadCustomMsg}
       
        uploadParams={uploadParams}
        batchDownload={true}
        uploadCustomMsgTips={true}
      >
        <MButton>自定义按钮</MButton>
      </MUpload>
      <h3>自定义按钮 - 弹框提示</h3>
      <h4>移动端自定义上传按钮时，也可以通过设置 isSelectFileConfirm 为 true 启用弹框提示 </h4>
      <MUpload
        isUploadCustomMsg={isUploadCustomMsg}
        uploadCustomMsg={uploadCustomMsg}
       
        uploadParams={uploadParams}
        batchDownload={true}
        isSelectFileConfirm={true}
      >
        <MButton>自定义按钮</MButton>
      </MUpload>
    </div>;
  }
}

export default withRouter(Demo);
```

### 自定义文件选择

自定义选择文件上传，支持File及Base64格式

```jsx
import {base64Data, base64Data1} from '../mock'
import {useState} from 'react';
import {MDialog, MUpload, Textarea, Upload, UploadBase64Data, UploadData} from '@weapp/ui'
const CusChooseFile = (props:any) => {
  const [imageData, setImageData] = useState(base64Data)
  const [uploadData,setUploadData]= useState([] as any[]);
  let customChooseFile = (params?:any) => {
    return new Promise<{
      base64: UploadBase64Data | UploadBase64Data[]
    }>((resolve, reject) => {
      const {reUpload} = params||{};
      // 模拟 app 自定义文件选择
      MDialog.prompt({
        title: reUpload ? '重新上传' :'自定义文件选择',
        prompt: false,
        onOk: () => {
          // 返回 file 或者 base64
          resolve({
            base64: [{
              base64: reUpload?base64Data1:imageData,
              fileName: reUpload?'测试1.png':'测试.png'
            }]
          })
        },
        onClose: () => {
          reject(false);
        }
      })
    });
  }
  let onChangeFile = (data?:UploadData[], uploading?:UploadData[],reUpload?: boolean)=>{
    setUploadData(data||[])
  }
  return (
      <div>
        <div style={{display: 'flex',flexDirection : 'column', gap: '16px'}}>
          <div>
            <div>base64图片：</div>
            <img src={imageData} alt=""/>
          </div>
          <div style={{flex: 1}}>
            <div>base64图片内容：</div>
            <Textarea
               
                value={imageData}
                onChange={setImageData}
                style={{width:"100%",height:"90%"}}
            />
          </div>
        </div>
        <div>
          <div>文件上传</div>
          <MUpload
                  customChooseFile={customChooseFile}
                  uploadParams={{
                    module: 'document'
                  }}
                   data={uploadData}
                   onChange={onChangeFile}
          />
        </div>
      </div>
  )
}

export default CusChooseFile
```

### 图片压缩

```jsx
import {Component, createRef} from 'react';
import {Textarea, MUpload} from '@weapp/ui';

const uploadParams = {
    module: 'document'
}

class UploadDemo extends Component<any> {
    state = {
        browserImageCompressionConfig:JSON.stringify({
            initialQuality: 0.5,
            minSize: 5*1024 * 1024,//文件大于5M的图片会进行压缩
            maxWidthOrHeight: 1920,
            usePlugin:"browser-image-compression"
        }),
        CompressorConfig:JSON.stringify({
            quality: 1,
            minSize: 5*1024 * 1024,//文件大于5M的图片会进行压缩
            strict: true,
            usePlugin: "Compressor"
        })
    }

    uploadInsRef = createRef<any>()

    startUpload = () => {
        this.uploadInsRef?.current?.startUpload()
    }

    handleChange = (data: any) => {
        console.error(data)
    }

    onChangeConfig = (type: any) => {
        return (value:string)=>{
            this.setState({
                [type]:value
            })

        }
    }

    render() {
        const {browserImageCompressionConfig, CompressorConfig} = this.state;
        let browserImageCompressionConfigData = {};
        try {
            browserImageCompressionConfigData = JSON.parse(browserImageCompressionConfig)
        }catch (e){

        }
        let CompressorConfigData = {};
        try {
            CompressorConfigData = JSON.parse(CompressorConfig)
        }catch ( e){}
        return (
            <div>
                <div>
                    <h2>原图：</h2>
                    <MUpload
                       
                        listType="img"
                        buttonType="image"
                        imgListType="horizontal"
                        uploadParams={uploadParams}
                        limitType='png,jpg,jpeg'
                    />
                </div>
                <div>
                    <h2>前端browser-image-compression压缩：</h2>
                    <div>支持多线程，如果参数设置不合适会慢，保留原格式</div>
                    <div>
                        配置参考：https://www.npmjs.com/package/browser-image-compression
                    </div>
                    <div>
                        <Textarea
                            value={browserImageCompressionConfig}
                            onChange={this.onChangeConfig('browserImageCompressionConfig')}
                        />
                    </div>
                    <MUpload
                       
                        listType="img"
                        buttonType="image"
                        imgListType="horizontal"
                        uploadParams={uploadParams}
                        limitType='png,jpg,jpeg'
                        jsCompressImg
                        //@ts-ignore
                        jsCompressImgOptions={browserImageCompressionConfigData}
                    />
                    <MUpload
                            uploadParams={uploadParams}
                            limitType='png,jpg,jpeg'
                            jsCompressImg
                        //@ts-ignore
                            jsCompressImgOptions={browserImageCompressionConfigData}
                    />
                </div>
                <div>
                    <h2>前端Compressor.js压缩：</h2>
                    <div> 速度快，效果差，canvas.toBlob压缩，除jpg格式和wedp格式，其他都会转换成jpg</div>
                    <div>
                        配置参考：https://www.npmjs.com/package/compressorjs
                    </div>
                    <div>
                        <Textarea
                            value={this.state.CompressorConfig}
                            onChange={this.onChangeConfig('CompressorConfig')}
                        />
                    </div>
                    <MUpload
                       
                        listType="img"
                        buttonType="image"
                        imgListType="horizontal"
                        uploadParams={uploadParams}
                        limitType='png,jpg,jpeg'
                        jsCompressImg
                        //@ts-ignore
                        jsCompressImgOptions={CompressorConfigData}
                    />
                    <MUpload
                            uploadParams={uploadParams}
                            limitType='png,jpg,jpeg'
                            jsCompressImg
                        //@ts-ignore
                            jsCompressImgOptions={CompressorConfigData}
                    />
                </div>
                <div>
                    <h2>后端压缩：</h2>
                    <MUpload

                            listType="img"
                            buttonType="image"
                            imgListType="horizontal"
                            isCompressImg={true}
                            uploadParams={uploadParams}
                            limitType='png,jpg,jpeg'
                    />
                </div>
            </div>
        );
    }
}

export default UploadDemo;
```

## API

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |  |  |
| --- | --- | --- | --- | --- | --- | --- |
| fileDataName | 上传附件参数名称 | string | 否 | `file` |  |  |
| data | 附件数据 | UploadData[] | 否 |  |  |  |
| headers | 接口请求的 header | UploadRequestHeader | 否 |  |  |  |
| uploadTitle | 上传图标（按钮）显示名称 | string | 否 |  |  |  |
| uploadUrl | 文件上传服务器接口地址 | string | 否 |  |  |  |
| uploadParams | 上传参数 | object \| ((file: IFile \| string \| Blob) => object) | 否 |  |  |  |
| maxCount | 限制文件个数 | number | 否 |  |  |  |
| maxSize | 最大上传大小限制，单位为 MB | number | 否 |  |  |  |
| minSize | 最小上传大小限制，单位为 MB | number | 否 |  |  |  |
| totalMaxSize | 总上传大小限制，单位为 MB | number | 否 |  |  |  |
| limitType | 允许上传的文件类型，文件后缀名以逗号隔开 | string | 否 |  |  |  |
| autoUpload | 自动上传或手动批量上传 | boolean | 否 |  |  |  |
| sortable | 是否可拖拽排序 | boolean | 否 |  |  |  |
| onSortEnd | 拖拽回调事件 | (data?: UploadData[]) => void | 否 |  |  |  |
| listType | 已上传附件列表展现形式 | 'list' \| 'img' | 否 | 'list' |  |  |
| imgListType | 图片列表横向排列或纵向排列 移动端不支持该参数 | 'horizontal' \| 'vertical' | 否 |  |  |  |
| showUpload | 是否启用显示上传附件按钮 | boolean | 否 | true |  |  |
| imgStyle | 图片样式 | CSSProperties | 否 |  |  |  |
| prohibitType | 禁止上传的文件类型，文件后缀名以逗号隔开 | string | 否 |  |  |  |
| dragUpload | 是否支持拖拽上传 | boolean | 否 |  |  |  |
| buttonType | 上传按钮类型 | 'default' \| 'image' | 否 |  |  |  |
| showListUploaded | 显示已上传文件列表 | boolean | 否 | true |  |  |
| showListUploading | 显示上传中文件列表 | boolean | 否 | true |  |  |
| disabled | 禁用上传(禁用的时候应该是只有下载，预览，查看历史版本以及签署的权限，模块自定义权限不做控制，请在禁用时自行屏蔽) | boolean | 否 | false |  |  |
| readOnly | 是否只读(只读的时候应该是只有下载，预览，查看历史版本以及签署的权限，模块自定义权限不做控制，请在只读时自行屏蔽) | boolean | 否 | false |  |  |
| multiple | 单选多选 | boolean | 否 | true |  |  |
| onChange | 组件状态变化，抛出最新列表 | (data?: UploadData[]) => void | 否 |  |  |  |
| onDelete | 删除的回调 | () => void | 否 |  |  |  |
| onAdd | 添加的回调（第一个参数是本次添加的文件，第二个参数是整体的待上传文件） | (file: IFile[], files: IFile[]) => void | 否 |  |  |  |
| renderListUploaded | 自定义渲染已上传列表 | (data?: UploadData[]) => ReactNode | 否 |  |  |  |
| renderListUploading | 自定义渲染待上传列表 | (data?: UploadData[]) => ReactNode | 否 |  |  |  |
| onStart | 开始上传 | (file: IFile) => void | 否 |  |  |  |
| customRequest | 自定义上传请求 | (option: UploadRequestOption) => void | 否 |  |  |  |
| onOptionClick | options 事件回调(通过第一个参数判断事件类型) | (value: string \| SelectOptionData, fileData: UploadData, fileIndex: number) => void | 否 |  |  |  |
| onBeforeOptionClick | options 事件触发前回调(通过第一个参数判断事件类型) | (value: string \| SelectOptionData, fileData: UploadData, fileIndex: number) => void \| boolean \| Promise<any> | 否 |  |  |  |
| customErrorInfo | 自定义上传错误提示信息 | (file: IFile, type: number) => string | 否 |  |  |  |
| customSuccessInfo | 自定义上传成功提示信息 | (file: IFile, type: number) => string | 否 |  |  |  |
| customRenameInfo | 自定义重命名完成提示信息 | (data: ListData, type: string, response?: any) => string | 否 |  |  |  |
| customDeleteInfo | 自定删除完成提示信息 | (data: ListData, type: string, response?: any) => string | 否 |  |  |  |
| renderUploadButton | 自定义上传按钮 | (eventProps: any, inputDom: ReactNode) => ReactNode | 否 |  |  |  |
| children | 自定义上传按钮 | ReactNode | 否 |  |  |  |
| onUploading | 上传状态回调 | (status:string,listT:UploadData[],listB:ListData[]) => void status:'uploading'\|\|'uploaded' |  |  |  |  |
| onError | 上传失败回调 | (file: File, errorInfo:string,response:any) => void |  |  |  |  |
| isShowAll | 是否展示所有已上传列表数据 | boolean | 否 | false |  |  |
| label | label 名称 | string | 否 | 附件上传 |  |  |
| labelSpan | 单选多选 | number | 否 | label 占比 |  |  |
| isShowLabel | 单选多选 | boolean | 否 | 是否展示 label |  |  |
| routeId | outeId（用作 corsLink，非必须，不指定时，组件内部随机生成） | string | 否 |  |  |  |
| batchUploadCompleted | 批量上传完成回调 | (successFiles: IFile[], failedFiles: IFile[]) => void | 否 |  |  |  |
| isDeleteInterface | 组件内删除是否走接口 | boolean | 否 | false |  |  |
| deleteUrl | 自定义删除 api | string | 否 | '' |  |  |
| deleteParams | 删删除接口参数 | AnyObj | 否 | {} |  |  |
| isDeleteConfirm | 删除前是否确认 | boolean | 否 | false |  |  |
| onDeleteCancel | 删除取消回调 | () => void | 否 |  |  |  |
| onDeleteSure | 删除确认回调 | (item: UploadData, listT: UploadData[], listB: ListData[]) => void | 否 |  |  |  |
| onError | 上传失败回调 (Em 上传不会返回文件本身) | (file: File,errorInfo:string,response:any) => void | 否 |  |  |  |
| onSuccess | 上传成功回调 (Em 上传不会返回文件本身) | (file: File ,errorInfo:string,response:any,data?: UploadData) => void | 否 |  |  |  |
| timeout | 超时设置 | number | 否 | 30000 |  |  |
| loginFree | 免登录标识(免登陆目前仅支持上传（分片上传）、重上传、预览、下载)【注意：如果要使用上免登陆的上传功能，必须通过 `uploadParams` 传递 `tenantKey`，但此时客户没有登陆，所有取不到 `tenantKey`，可以传递 `all_teams`，后端不做校验】 | boolean | 否 |  |  |  |
| onUploadComplete | 上传完成回调 | (successFiles: UploadData[], failedFiles: UploadData[], total?: number, otherParams?: AnyObj) | 否 |  |  |  |
| capture | h5 模式下的 input capture 设置，详情见 文档 | string | 否 | - |  |  |
| accept | h5 模式下 input accept 设置（优先级高于 limitype，详情见 文档 ） | string | 否 | - |  |  |
| sourceType(仅 em 中生效) | 功能选择 | sourceType[]（`camera`(照相)\| `video`(录视频) \| `album`(相册) \| `file`(选文件)） | 否 | ["camera", "video", "album", "file"] |  |  |
| ablumType(仅 em 中生效) | 相册选择（可控制只能选照片、只能选视频、以及照片和视频都可以选择）（`album` 时可用） | "all" \| "photo" \| "video" | 否 | `all` |  |  |
| isAddWaterMark(仅 em 中生效) | 图片是否生成水印（EM sdk 生效） | boolean | 否 | false |  |  |
| isSaveAlbum(仅 em 中生效) | 拍摄的照片/视频是否保存在相册中 | boolean | 否 | true |  |  |
| isEditAlbumPhoto(仅 em 中生效) | 拍拍摄、选择的照片是否允许编辑 | boolean | 否 | true |  |  |
| compressType(仅 em 中生效) | 图片压缩类型，1 表示用户可以选择是否原图，2 表示固定压缩，3 表示固定原图 | `1`,`2`,`3` | 否 | `1` |  |  |
| commonParams | 接口通用参数（该 api 的参数，会添加到所有上传组件相关接口中） | AnyObj | 否 | - |  |  |
| renderContentUploaded | 自定义渲染已上传文件信息 | (item: UploadData) => ReactNode | 否 | - |  |  |
| renderTitleUploaded | 自定义渲染已上传文件名称 | (item: UploadData) => ReactNode |  |  |  |  |
| fileListType | FileList 的模式 | "useDetail"\"noUseDetail" | 否 | - |  |  |
| checkSensitiveWords | 是否启用敏感词检测功能 | boolean | 否 | true |  |  |
| checkName | 启用附件名称校验功能 | boolean | 否 | false |  |  |
| directoryId | 校验附件的目录 | string | 否 | - |  |  |
| customRenderFileIcon | 自定义渲染文件图标 | (extName?: string, item?: UploadData | IFile) => ReactNode | 否 | - |  |
| onUploadFinally | 上传结束事件（所有操作都结束才会触发） | () => void | 否 | - |  |  |
| selectNum | 设置单次可选数量（仅 em 生效，仅大于 0 生效） | number | 否 | - |  |  |
| beforeUploadFile | 传前拦截事件（在文件上传接事件前触发，可以通过该事件在文件上传前最后一次复写 uploadParams） | (file: IFile, uploadParams?: AnyObj) => boolean \| AnyObj \| Promise<boolean \| AnyObj> | 否 | - |  |  |
| requestHeaderParams | 接口 headers 参数 | AnyObj | 否 |  |  |  |
| uploadedOptionsWhites | 已上传文件操作按钮配置白名单 | string[] | 否 | - |  |  |
| uploadedOptionsBlacks | 已上传文件操作按钮配置黑名单 | string[] | 否 | - |  |  |
| uploadingOptionsWhites | 待上传文件操作按钮配置白名单 | string[] | 否 | - |  |  |
| uploadingOptionsBlacks | 待上传文件操作按钮配置黑名单 | string[] | 否 | - |  |  |
| showFileSize | 是否显示附件大小 | boolean | 否 | true |  |  |
| thumbnailFormat | 缩略图展示类型 | `small`: 小图（不压缩） \| `big`: 大图（不压缩） \| `imagePreview`: 原图（不压缩） \| `high`: 质量压缩-高 \| `medium`: 压缩质量-中 \| `low`: 压缩质量-低 \| `image`: 跟随系统设置 | 否 | `small` |  |  |
| batchDownloadParams | 批量下载接口参数（传递 zipName 自定义压缩包名称） | AnyObj | 否 | {} |  |  |
| batchDeleteParams | 批量删除接口参数 | AnyObj | 否 | {} |  |  |
| downloadParams | 下载接口参数 | AnyObj | 否 | {} |  |  |
| previewParams | 预览接口参数                                                     uploadTips.tsx | AnyObj | 否 | {} |  |  |
| editParams | 编辑接口参数 | AnyObj | 否 | {} |  |  |
| renameParams | 重命名接口参数 | AnyObj | 否 | {} |  |  |
| isUploadCustomMsg | 附件附加提示开关 | boolean | 否 |  |  |  |
| uploadCustomMsg | 附件附加提示 | string | 否 | '' |  |  |
| uploadCustomMsgTips | 附件附加文本提示开关（仅自定义上传按钮生效，自定义上传按钮时默认无文本提示，需主动开启） | boolean | 否 | false |  |  |
| isCustomThumbnailUrl | 是否自定义缩略图地址（为 true 时会取附件数据中的 imgUrl） | boolean | 否 | false |  |  |
| beforeBatchDownload | 批量下载触发前事件 | (params: AnyObj) => AnyObj \| boolean \| Promise<AnyObj \| boolean> | 否 | - |  |  |
| beforeUploadFile | 批量下载触发前事件 | (file: any, uploadParams?: AnyObj) => boolean \| AnyObj \| Promise<boolean \| AnyObj> | 否 | - |  |  |
| isSelectFileConfirm | 是否开启选择文件前弹框确认提示 | boolean | 否 |  |  |  |
| customChooseFile | 自定义文件选择 | () => Promise<{ file?: File | FileList, base64?: base64Data | base64Data[] }> | 否 |  |
### Tip

``,``,``,``,``,`` 这几天参数，需要依赖 em 提供的 sdk 支持，因此仅在 em 中生效。（因此企业微信中这些参数无效）

移动端拍照与文件（图片）选择权限控制，优先使用 em 的 sdk，当没有检测到 em 的 sdk 时，才会使用 h5 逻辑。（企业微信中无 em sdk，走 h5 逻辑）

## 附件密级

### 使用方法

模块可通过 `` 参数开启附件密级保护，该参数默认 ``。

> 当在系统后台设置（ `` - ``） 中开启 `` 后，该接口返回信息会开启附件密级校验。
> 
> 如系统后台设置未开启 ``，附件上传则不触发附件密级校验，依然会按照普通上传处理。

如触发附件密级校验（后台开启 ``），`` 为必填参数，如未传递，会触发 `` 提示。

如未触发附件密级校验（后台未开启 ``），将按照普通上传处理，前端附件上传将不携带密级参数，后端将附件密级和生成的文档的密级一律设置为公开。

密级确认框默认开启，模块可通过 `` 手动关闭密级确认框（开启本地标密上传后，不会弹出密级确认框）。

关闭密级确认框后，优先读取模块传递的 `` 和 ``，如无传递 ``，将以当前密级等级的默认保密期限进行附件密级设置。

对于待上传附件，密级模式下支持修改当前附件的密级信息（仅 `` 为 `` 时启用），可通过 uploadingOptions 进行统一配置，也可用 item.options 对单个待上传附件进行功能配置。

目前 uploadingOptions 默认配置如下：

```
[
  {
    id: 'editSecLevel',
    icon: 'Icon-daily-o',
    content: getLabel('90913', '修改密级'),
    moreType: true,
  },
  {
    id: 'delete',
    icon: 'Icon-cancel',
    content: getLabel('21778', '删除')
  },
]
```

对于已上传附件，根据 `` 中的 `` 进行密级信息修改的启用：

```
{
  id: 'editSecLevel',
  icon: 'Icon-rename',
  content: '修改密级',
  moreType: true
}
```

### API

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| secretProtect | 是否启用密级保护 | boolean | 否 | false |
| secretConfim | 是否开启密级确认框（最低密级时，默认无确认框，该参数无效） | boolean | 否 | true |
| secretLevel | 密级等级 | string | 是 | - |
| secretLevelValidity | 保密期限 | string | 否 | - |
| secretLevelInfo | 缺少密级提示 | string | 否 | `请填写密级！` |
| secretLevelHelpTip | 密级填写辅助信息 | string | 否 | `保密期限填写格式：3个月、10年、20年、长期…不能是纯数字` |
| uploadingOptions | 待上传启用功能 | UploadOptionType[] | 否 | 默认支持 `取消上传`、`修改密级` |
| secretLevelAutoAdjust | 是否启用密级自动调整 | boolean | 否 | false |
### 获取本地标密配置方法：getAttachmentLocalSecurityInfo

返回结果：

```
{
    isAllow?: boolean;  // 是否开启本地附件标密上传
    verifyFormat?: string;  // 标密格式
}
```

## 列表复写返回事件说明

### 已上传（renderListUploaded）eventProps 说明

通常情况下，onOptionClick 即满足所有列表功能

Tips：如果单独调用功能的事件，需要确认该附件有对应的功能。

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| onOptionClick | 更多操作事件 | (option: SingleType, fileData: ListData, fileIndex: number) => void | 否 | - |
| onDownload | 下载 | (item: UploadData, index?: number) => void | 否 | - |
| onReUpload | 重上传 | (item: UploadData, index?: number) => void | 否 | - |
| onDelete | 删除 | (item: UploadData, index?: number) => void | 否 | - |
| onPreview | 预览 | (item: UploadData, index?: number) => void | 否 | - |
| onEdit | 编辑 | (item: UploadData, index?: number) => void | 否 | - |
| onReName | 重命名 | (item: UploadData, index?: number) => void | 否 | - |
| onAppeal | 申诉 | (item: UploadData, index?: number) => void | 否 | - |
| onEditSecLevel | 调整密级 | (item: UploadData, index?: number) => void | 否 | - |
| onVersion | 打开历史记录 | (item: UploadData, index?: number) => void | 否 | - |
| onSignFirst | 对方先签 | (item: UploadData, index?: number) => void | 否 | - |
| onSignBack | 退回签署 | (item: UploadData, index?: number) => void | 否 | - |
| onStartSign | 发起签署 | (item: UploadData, index?: number) => void | 否 | - |
| onSignShare | 签署链接 | (item: UploadData, index?: number) => void | 否 | - |
| onNullifySign | 作废签署 | (item: UploadData, index?: number) => void | 否 | - |
| onApplySign | 申请签署 | (item: UploadData, index?: number) => void | 否 | - |
### 待上传（renderListUploading）eventProps 说明

通常情况下，onOptionClick 即满足所有列表功能（如果单独使用调整密级功能，需要先确保密级功能已开启）

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |  |
| --- | --- | --- | --- | --- | --- |
| onOptionClick | 更多操作事件 | (option: string | SelectOptionData, fileData: ListData, fileIndex: number) => void | 否 | - |
| onCancel | 取消上传 | (file: IFile) => void | 否 | - |  |
| onEditSecLevel | 调整密级 | (fileData: IFile, fileIndex: number) => void | 否 | - |  |
