# Signature 签批

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/signature/freepass)
- 平台：PC
- 维护者：屈正巍
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[Signature]

## 代码演示

### 基础用法

直接引入组件进行使用

```jsx
import { Component } from 'react';
import { Signature, Button, constants } from '@weapp/ui';
import { img1 } from '../mock'

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;
class SignatureDemo extends Component {

  state = {
    value: img1,
    value1: img1,
    visible: false,
    readonly: false,
    value2: img1,
  }

  onChange = (value: string) => console.info('onChange', value)
  onValueChange = (value: string) => {
    console.info('onValueChange', value)
    this.setState({ value })
  }
  onValue2Change = (value: string) => {
    console.info('onValueChange', value)
    this.setState({ value2: value, readonly: true })
  }
  onDialogOpen = () => this.setState({ visible: true })
  onDialogClose = () => this.setState({ visible: false })
  onClear = () => console.info('onClear')

  render() {
    return (
      <div className={prefixCls}>
        <p>基础用法</p>
        <Signature
          onChange={this.onChange}
        />
        <br />
        <br />
        <p>受控</p>
        <Signature
          value={this.state.value}
          onChange={this.onValueChange}
          onClear={this.onClear}
        />
        <br />
        <br />
        <p>受控后变为只读模式</p>
        <Signature
          value={this.state.value2}
          onChange={this.onValue2Change}
          onClear={this.onClear}
          readOnly={this.state.readonly}
        />
        <br />
        <br />
        <p>受控不改变值</p>
        <Signature
          value={this.state.value1}
          onChange={this.onChange}
          showDelete
        />
        <br />
        <br />
        <p>自定义控制 visible </p>
        <Signature
          onChange={this.onChange}
          visible={this.state.visible}
          onDialogOpen={this.onDialogOpen}
          onDialogClose={this.onDialogClose}
        />
        <Button type={'primary'} onClick={this.onDialogOpen}>打开Signature弹窗</Button>
        <br />
        <br />
        <p>禁用</p>
        <Signature
          disabled />
        <br />
        <br />
        <p>只读</p>
        <Signature
          defaultValue={img1}
          readOnly />
        <br />
        <br />
        <p>含值时的展示状态</p>
        <Signature
          defaultValue={img1} />
        <br />
        <br />
        <p>含有value值时且禁用时</p>
        <Signature
          defaultValue={img1}
          disabled />
        <br />
        <br />
        <p>通过 showDelete 来配置是否显示删除按钮</p>
        <Signature
          defaultValue={img1}
          showDelete />
        <p>通过 showScaleControl 来配置是否需要尺寸控制器</p>
        <Signature
          showScaleControl={false}
        />
        <br />
        <br />
        <p>隐藏图片上传模式</p>
        <Signature
          onChange={this.onChange}
          hideUploadImage
        />
      </div>
    );
  }
}

export default SignatureDemo;
```

### 自定义渲染

自定义渲染组件、二维码与电子签名

```jsx
import { Component } from 'react';
import { Signature, constants, Button } from '@weapp/ui';
import { img1 } from '../mock';

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;

class SignatureDemo extends Component {

  onChange = (value: string, menuValue: any) => console.info('onChange', value, menuValue)
  customPreview = (value: string) => (
    <div>
      <p>2019.8.3</p>
      <h5>艾伦</h5>
      <img style={{ opacity: 0.3 }} className="ui-signature-canvas" src={value} alt='' />
    </div>
  )
  render() {
    return (
      <div className={prefixCls}>
        <h3>签名模式</h3>
        <p>自定义按钮</p>
        <Signature
          onChange={this.onChange}
        >
          <Button type={'primary'}>自定义签名按钮</Button>
        </Signature>
        <br />
        <br />
        <p>自定义预览图</p>
        <Signature
          defaultValue={img1}
          previewCustomRender={this.customPreview}
        />
        <br />
        <br />
        <p>自定义预览图只读模式</p>
        <Signature
          defaultValue={img1}
          previewCustomRender={this.customPreview}
          readOnly
        />
        <br />
        <br />
        <p>自定义预览图（禁用点击事件）</p>
        <Signature
          defaultValue={img1}
          previewCustomRender={this.customPreview}
          readOnly
          readOnlyPreventDefaultClickEvent
        />
      </div>
    );
  }
}

export default SignatureDemo;
```

### 签批模式

签批组件

```jsx
import { Component } from 'react';
import { Signature, Button, constants } from '@weapp/ui';
import { img1 } from '../mock';

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;
class SignatureDemo extends Component {

  state = {
    value: img1,
    value1: img1,
    visible: false,
    value2: img1,
    readonly: false
  }

  onChange = (value: string) => console.info('onChange', value)
  onValueChange = (value: string) => {
    console.info('onValueChange', value)
    this.setState({ value })
  }
  onValue2Change = (value: string) => {
    console.info('onValueChange', value)
    this.setState({ value2: value, readonly: true })
  }
  onDialogOpen = () => this.setState({ visible: true })
  onDialogClose = () => this.setState({ visible: false })
  onClear = () => console.info('onClear')

  render() {
    return (
      <div className={prefixCls}>
        <p>基础用法</p>
        <Signature
          mode={'review'}
          onChange={this.onChange}
        />
        <br />
        <br />
        <p>受控</p>
        <Signature
          mode={'review'}
          value={this.state.value}
          onChange={this.onValueChange}
          onClear={this.onClear}
        />
        <br />
        <br />
        <p>受控后变为只读</p>
        <Signature
          mode={'review'}
          value={this.state.value2}
          onChange={this.onValue2Change}
          onClear={this.onClear}
          readOnly={this.state.readonly}
        />
        <br />
        <br />
        <p>受控不改变值</p>
        <Signature
          mode={'review'}
          value={this.state.value1}
          onChange={this.onChange}
          showDelete
        />
        <br />
        <br />
        <p>自定义控制 visible </p>
        <Signature
          mode={'review'}
          onChange={this.onChange}
          visible={this.state.visible}
          onDialogOpen={this.onDialogOpen}
          onDialogClose={this.onDialogClose}
        />
        <Button type={'primary'} onClick={this.onDialogOpen}>打开Signature弹窗</Button>
        <br />
        <br />
        <p>禁用</p>
        <Signature
          mode={'review'}
          disabled />
        <br />
        <br />
        <p>只读</p>
        <Signature
          mode={'review'}
          readOnly />
        <br />
        <br />
        <p>含值时的展示状态</p>
        <Signature
          mode={'review'}
          defaultValue={img1} />
        <br />
        <br />
        <p>含有value值时且禁用时</p>
        <Signature
          mode={'review'}
          defaultValue={img1}
          disabled />
        <br />
        <br />
        <p>通过 showDelete 来配置是否显示删除按钮</p>
        <Signature
          mode={'review'}
          defaultValue={img1}
          showDelete />
        <p>通过 showScaleControl 来配置是否需要尺寸控制器</p>
        <Signature
          mode={'review'}
          showScaleControl={false}
        />
      </div>
    );
  }
}

export default SignatureDemo;
```

### 签批自定义渲染

自定义渲染组件、二维码与电子签名

```jsx
import { Component } from 'react';
import { Signature, constants, Button } from '@weapp/ui';
import { img1 } from '../mock';

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;

class SignatureDemo extends Component {

  onChange = (value: string) => console.info('onChange', value)
  customPreview = (value: string) => (
    <div>
      <p>2019.8.3</p>
      <h5>艾伦</h5>
      <img style={{ opacity: 0.3 }} className="ui-signature-canvas" src={value} alt='' />
    </div>
  )
  render() {
    return (
      <div className={prefixCls}>
        <p>自定义按钮</p>
        <Signature
          mode={'review'}
          onChange={this.onChange}
        >
          <Button type={'primary'}>自定义按钮</Button>
        </Signature>
        <br />
        <br />
        <p>自定义预览图</p>
        <Signature
          mode={'review'}
          defaultValue={img1}
          previewCustomRender={this.customPreview}
        />
        <br />
        <br />
        <p>自定义预览图只读模式</p>
        <Signature
          mode={'review'}
          defaultValue={img1}
          previewCustomRender={this.customPreview}
          readOnly
        />
        <br />
        <br />
        <p>自定义预览图只读模式（禁用点击事件）</p>
        <Signature
          mode={'review'}
          defaultValue={img1}
          previewCustomRender={this.customPreview}
          readOnlyPreventDefaultClickEvent
          readOnly
        />
      </div>
    );
  }
}

export default SignatureDemo;
```

### 扫码签名签批

自定义二维码

```jsx
import { Component, ReactNode } from 'react';
import { Signature, constants, Button, Qrcode } from '@weapp/ui';
import { img1 } from '../mock';
import { handleSiteDomain } from "@weapp/utils";
const qrcodeSettings = {
  src: "/favicon.ico",
  height: 24,
  width: 24,
  excavate: true,
}

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;

class SignatureDemo extends Component {

  onChange = (value: string) => console.info('onChange', value)
  customPreview = (value: string) => (
    <div>
      <p>2019.8.3</p>
      <h5>艾伦</h5>
      <img style={{ opacity: 0.3 }} className="ui-signature-canvas" src={value} alt='' />
    </div>
  )
  qrcodeCustomRender = (node: ReactNode) => {
    return <div style={{ textAlign: 'center' }}>
      展示用户自定义内容
      <div style={{ height: 50, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>展示用户自定义内容：此处可以采用组件库的二维码组件</div>
      <Qrcode
        url={handleSiteDomain("https://weapp.eteams.cn/ui")}
        size={150}
        bgColor={"#ffffff"}
        fgColor={"#000000"}
        level={"L"}
        imageSettings={qrcodeSettings}
      />
      {node}
    </div>
  }
  render() {
    return (
      <div className={prefixCls}>
        <h2>扫码签名</h2>
        <p>自定义二维码url</p>
        <Signature
          qrcodeUrl={img1}
          qrcodeStyle={{ maxWidth: 400 }}
        />
        <br />
        <br />
        <p>自定义二维码dom</p>
        <Signature
          icon="Icon-like"
          qrcode={(<div><img src={img1} alt={img1} style={{ maxWidth: 400 }} /></div>)}
          onChange={this.onChange}
        />
        <br />
        <br />
        <p>自定义二维码function</p>
        <Signature
          defaultValue={img1}
          qrcodeCustomRender={this.qrcodeCustomRender}
        />
        <br />
        <br />
        <p>自定义二维码url（popover模式）</p>
        <Signature
          qrcodeUrl={img1}
          qrcodeStyle={{ maxWidth: 400 }}
          qrcodeMode={'popover'}
        />
        <br />
        <br />
        <p>自定义二维码dom（popover模式）</p>
        <Signature
          icon="Icon-like"
          qrcode={(<div><img src={img1} alt={img1} style={{ maxWidth: 400 }} /></div>)}
          onChange={this.onChange}
          qrcodeMode={'popover'}
        />
        <br />
        <br />
        <p>自定义二维码function（popover模式）</p>
        <Signature
          defaultValue={img1}
          qrcodeCustomRender={this.qrcodeCustomRender}
          qrcodeMode={'popover'}
        />
        <h2>扫码签批</h2>
        <p>自定义二维码url</p>
        <Signature
          mode={'review'}
          qrcodeUrl={img1}
          qrcodeStyle={{ maxWidth: 400 }}
        />
        <br />
        <br />
        <p>自定义二维码dom</p>
        <Signature
          mode={'review'}
          icon="Icon-like"
          qrcode={(<div><img src={img1} alt={img1} style={{ maxWidth: 400 }} /></div>)}
          onChange={this.onChange}
        />
        <br />
        <br />
        <p>自定义二维码function</p>
        <Signature
          mode={'review'}
          defaultValue={img1}
          qrcodeCustomRender={this.qrcodeCustomRender} />
        <br />
        <br />
        <p>自定义二维码url（popover模式）</p>
        <Signature
          mode={'review'}
          qrcodeUrl={img1}
          qrcodeStyle={{ maxWidth: 400 }}
          qrcodeMode={'popover'}
        />
        <br />
        <br />
        <p>自定义二维码dom（popover模式）</p>
        <Signature
          mode={'review'}
          icon="Icon-like"
          qrcode={(<div><img src={img1} alt={img1} style={{ maxWidth: 400 }} /></div>)}
          onChange={this.onChange}
          qrcodeMode={'popover'}
        />
        <br />
        <br />
        <p>自定义二维码function（popover模式）</p>
        <Signature
          mode={'review'}
          defaultValue={img1}
          qrcodeCustomRender={this.qrcodeCustomRender}
          qrcodeMode={'popover'}
        />
      </div>
    );
  }
}

export default SignatureDemo;
```

### 大面板模式

大面板模式

```jsx
import { Component } from 'react';
import { Signature, Button, constants } from '@weapp/ui';
import { img1 } from '../mock'

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;
class SignatureDemo extends Component {

  state = {
    value: img1,
    value1: img1,
    visible: false
  }

  onChange = (value: string, menuValue?: string) => console.info('onChange', value, 'menuValue', menuValue)
  onValueChange = (value: string, menuValue?: string) => {
    console.info('onValueChange', value, 'menuValue', menuValue)
    this.setState({ value })
  }
  onDialogOpen = () => this.setState({ visible: true })
  onDialogClose = () => this.setState({ visible: false })
  onCanvasClear = () => console.info('onCanvasClear')
  onClear = () => console.info('onClear')
  onUploadChange = (data: any) => console.log('onUploadChange', data)

  render() {
    return (
      <div className={prefixCls}>
        <p>基础用法</p>
        <Signature
          type="large"
          onChange={this.onChange}
          mode={'review'}
        />
        <br />
        <br />
        <p>受控</p>
        <Signature
          type="large"
          showDelete
          value={this.state.value}
          onChange={this.onValueChange}
          onCanvasClear={this.onCanvasClear}
          onClear={this.onClear}
          onUploadChange={this.onUploadChange}
        />
        <p>受控不改变值</p>
        <Signature
          type="large"
          value={this.state.value1}
          onChange={this.onChange}
          showDelete
        />
        <br />
        <br />
        <p>自定义控制visible</p>
        <Signature
          type="large"
          onChange={this.onChange}
          visible={this.state.visible}
          onDialogOpen={this.onDialogOpen}
          onDialogClose={this.onDialogClose}
        />
        <Button type={'primary'} onClick={this.onDialogOpen}>打开Signature弹窗</Button>
      </div>
    );
  }
}

export default SignatureDemo;
```

### 电子签名

可以直接传入，也可以通过异步方式获取

```jsx
import { Component, } from 'react';
import { AnyObj, Signature, constants, } from '@weapp/ui';
import { img1, img2 } from '../mock';

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;

class SignatureDemo extends Component {

  onChange = (value: string) => console.info('onChange', value)
  handle = (res: AnyObj) => {
    return img1
  }
  render() {
    return (
      <div className={prefixCls}>
        <p>显示电子签名</p>
        <Signature
          eSignature={img2}
          eSignatureStyle={{ height: '200px' }}
          onChange={this.onChange}
        />
        <p>异步获取eSignature(不缓存图片地址)</p>
        <Signature
          getESignature={{
            requestParams: {
              url: '/api/hrm/common/browser/prop/resource',
              params: {
                "browserMultiple": true
              },
              method: 'post'
            },
            handle: this.handle
          }}
          eSignatureStyle={{ height: '200px' }}
          onChange={this.onChange}
        />
        <br />
        <br />
        <p>异步获取eSignature(缓存图片地址)</p>
        <Signature
          getESignature={{
            requestParams: {
              url: '/api/hrm/common/browser/prop/resource',
              params: {
                "browserMultiple": true
              },
              method: 'post'
            },
            handle: this.handle,
            useCache: true
          }}
          eSignatureStyle={{ height: '200px' }}
          onChange={this.onChange}
        />
      </div>
    );
  }
}

export default SignatureDemo;
```

### 删除状态

签批组件删除状态

```jsx
import { Component } from 'react';
import { Signature, constants } from '@weapp/ui';
import { img1 } from '../mock';

const prefixCls = `${constants.uiPcClsPrefix}-demo-signature`;
class SignatureDemo extends Component {

  state = {
    value: img1,
    value2: img1,
    value3: img1,
    value4: img1,
    value5: img1,
    fileStatus: 0,
    fileStatus2: 1,
    fileStatus3: 1,
    fileStatus4: 2,
    fileStatus5: 2,
  }

  onValueChange = (value: string) => {
    console.info('onValueChange', value)
    this.setState({ value })
  }
  onValueChange2 = (value: string) => {
    console.info('onValueChange2', value)
    this.setState({ value2: value, fileStatus2: 0 })
  }
  onValueChange3 = (value: string) => {
    console.info('onValueChange3', value)
    this.setState({ value3: value, fileStatus3: 0 })
  }
  onValueChange4 = (value: string) => {
    console.info('onValueChange2', value)
    this.setState({ value4: value, fileStatus4: 0 })
  }
  onValueChange5 = (value: string) => {
    console.info('onValueChange3', value)
    this.setState({ value5: value, fileStatus5: 0 })
  }

  render() {
    const { value, value2, value3, value4, value5, fileStatus, fileStatus2, fileStatus3, fileStatus4, fileStatus5 } = this.state
    return (
      <div className={prefixCls}>
        <p>通用状态</p>
        <Signature
          value={value}
          onChange={this.onValueChange}
          fileStatus={fileStatus}
        />
        <p>删除状态</p>
        <Signature
          value={value2}
          onChange={this.onValueChange2}
          fileStatus={fileStatus2}
        />
        <p>删除状态（大面板）</p>
        <Signature
          type="large"
          value={value3}
          onChange={this.onValueChange3}
          fileStatus={fileStatus3}
        />
        <p>文件不存在状态</p>
        <Signature
          value={value4}
          onChange={this.onValueChange4}
          fileStatus={fileStatus4}
        />
        <p>文件不存在状态（大面板）</p>
        <Signature
          type="large"
          value={value5}
          onChange={this.onValueChange5}
          fileStatus={fileStatus5}
        />
      </div>
    );
  }
}

export default SignatureDemo;
```

## API

### 类型说明：（请从@weapp/ui 中导出）

```typescript
type menuIndexType = '0' | '1' | '2' | '3' // '0':绘制签名,'1':扫码签名,'2':电子签名,'3':上传签名
/**
 * 文件状态
 * 0 或者没有值: 附件正常状态
 * 1: 删除状态【文件和当前业务去已除了关联关系，包括文件已经被彻底删除】
 * 2: 文件不存在状态【跟进此附件id，文件服务也查询不到任何信息】
 */
type fileStatus = number | string
```

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| disabled | 选择器是否禁用 | boolean | 否 | false |
| readOnly | 选择器是否完全只读 | boolean | 否 | false |
| dialogProps | 弹出框的 props | 参考 Dialog 组件参数 | 否 |  |
| confirmDialogProps | 清空确认框的 props | 参考 Dialog 组件参数 | 否 |  |
| emptyInfoDialogProps | 空白提示框的 props | 参考 Dialog 组件参数 | 否 |  |
| eSignatureStyle | 电子签名 img 标签样式 | CSSProperties | 否 |  |
| className | 自定义类名 | string | 否 |  |
| style | 自定义样式 | CSSProperties | 否 |  |
| icon | 弹出框头部icon图标 | IconNames  请参考 Icon 组件参数 | 否 |  |
| title | 弹出框头部title | string | 否 |  |
| showDelete | 是否显示删除预览按钮 | boolean | 否 | true |
| type | 签名模式 | 'small' \|'large' | 否 | 'small' |
| value | base64 格式的图片值 | string | 否 |  |
| defaultValue | base64 格式的图片值 | string | 否 |  |
| eSignature | 电子签名值 | string | 否 |  |
| getESignature | 异步获取电子签名值 | GetESignature | 否 |  |
| uploadParams | 上传附件参数 | 参考 Upload 组件参数 | 否 |  |
| qrcode | 扫码签名二维码显示内容 | ReactNode | 否 |  |
| qrcodeUrl | 二维码地址 | string | 否 |  |
| qrcodeStyle | 二维码样式 | CSSProperties | 否 |  |
| qrcodeDescription | 二维码下方描述 | ReactNode | 否 |  |
| qrcodeCustomRender | 扫码签名自定义渲染 | () => ReactNode | 否 |  |
| previewCustomRender | 签批预览内容自定义渲染 | () => ReactNode | 否 |  |
| onBeforeChange | onChange 之前的回调 | (value: string, menuIndex?: menuIndexType) => Promise | 否 |  |
| onChange | 签批确认后回调 | (value: string, menuIndex?: menuIndexType) => void | 否 |  |
| onClear | 清空后的回调 | () => void | 否 |  |
| onCanvasClear | 弹框中点击清空的回调 | () => void | 否 |  |
| onClickClearBtn | 大面板模式下点击清空按钮的回调 | () => void | 否 |  |
| onDialogOpen | 弹出框打开的回调 | () => void | 否 |  |
| onDialogClose | 弹出框关闭的回调 | () => void | 否 |  |
| onUploadChange | 上传成功后的回调 | (data?: UploadData[], uploading?: UploadData[], reUpload?: boolean) => void | 否 |  |
| showScopeControl | 是否需要画布缩放 | boolean | 否 | false |
| showScaleControl | 是否需要画布尺寸控制 | boolean | 否 | true |
| mode | 控制签名模式或签批模式 | 'name' \| 'review' | 否 | 'name' |
| onClickPrevImg | 点击预览图片的回调 | () => void | 否 |  |
| readOnlyPreventDefaultClickEvent | 只读模式是否禁用原生的点击预览事件 | boolean | 否 | false |
| canvasBarShowClear | 签批层工具栏是否展示清空按钮 | boolean | 否 | true |
| readOnlyImgFileId | 用于只读模式下图片预览的下载功能 | string | 否 |  |
| readOnlyPhotoViewParams | 只读模式图片预览props | PhotoViewProps | 否 |  |
| fileStatus | 文件状态 | number \| string | 否 |  |
| hideCorsESignature | 是否隐藏选择模块电子签 | boolean | 否 |  |
| corsESignatureProps | 模块电子签参数 | any | 否 |  |
| corsESignatureDialogProps | 模块电子签dialog参数 | any | 否 |  |
| loginFree | 是否免登录 | boolean | 否 |  |
| qrcodeMode | 扫码签名签批模式 | 'tab' \| 'popover' | 否 | 'tab' |
| hideUploadImage | 隐藏图片上传开关 | boolean | 否 | false |
### 特殊类型说明

#### getESignature与eSignature 不可同时传入

```typescript
type GetESignature ={
  /**
   * 请求参数与utils中的request一致
   */
  requestParams:RequestOptionConfig;
  /**
   * @param res 
   * @returns eSignature
   * 自定义处理方法，传入异步接口res结果，返回处理后的eSignature
   */
  handle:(res:AnyObj)=>string;
  //是否启用缓存
  useCache?:boolean
}
```
