# Sign 协议签署

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

## 代码演示

### 基础用法

直接引入组件进行使用

```jsx
import { Component, ReactText } from 'react';
import { Sign, Checkbox, constants, CheckboxValueType, Input, EditableTable, FormItemProps, utils } from '@weapp/ui';
import { classUseMemo } from '@weapp/utils';

const prefixCls = `${constants.uiPcClsPrefix}-demo-sign`;
const { getRandom } = utils;
class SignDemo extends Component<any, any> {

  constructor(props: any) {
    super(props);
    this.state = {
      visible: false,
      visibleMul: false,
      checked: false,
      agreementValue: '1030644344063680513',
      agreementValues: [{
        id: getRandom(),
        agreementId: '1030644344063680513',
      }, {
        id: getRandom(),
        agreementId: '1030670380216950784',
      }],
    }
  }
  changeVisible = () => this.setState({ visible: true })
  changeVisibleMul = () => this.setState({ visibleMul: true })
  onVisibleChange = (visible: boolean) => this.setState({ visible: visible });
  onVisibleMulChange = (visible: boolean) => this.setState({ visibleMul: visible });
  onClose = () => {
    console.log('---onClose---');
  }
  onAgree = () => {
    console.log('---onAgree---');
  }
  onDisagree = () => {
    console.log('---onDisagree---');
  }
  onAgreeChecked = () => {
    console.log('---onAgree---');
    this.onChangeChecked(true);
  }

  onDisagreeChecked = () => {
    console.log('---onDisagree---');
  }

  onChangeChecked = (value: CheckboxValueType) => this.setState({ checked: value });

  columns = [
    {
      title: '协议Id',
      dataIndex: 'agreementId',
      comKey: 'agreementId',
      width: '80%',
    }
  ]
  comProps = {
    agreementId: {
      itemType: 'INPUT',
      placeholder: "请输入协议id"
    }
  } as FormItemProps
  
  onChangeAgreementValue = (value: ReactText) => this.setState({ agreementValue: value });

  onChangeAgreementsValue = (data: any) => this.setState({ agreementValues: data });

  topTools = [
    {
      type: 'batchDelete',
      icon: 'Icon-Batch-delete',
      title: '批量删除',
    },
    {
      type: 'add',
      icon: 'Icon-add-to03',
      title: '新增',
    },
  ];

  render() {
    const { agreementValue, agreementValues } = this.state;

    const agreementIds = classUseMemo('agreementIds', this, () => agreementValues?.map((v: { agreementId: string; }) => v.agreementId), [agreementValues]);
    return (
      <div className={prefixCls}>

        <h3>单协议</h3>
        <div className={`${prefixCls}-inputContainer`}>
          <div className={`${prefixCls}-inputContainer-tip`}>协议id数据来源对应<span>{`后台中心 -> 数据安全 -> 隐私协议 -> 隐私协议设置`}</span>页面设置的列表数据Id</div>
          <div className={`${prefixCls}-input`}>
            <span className={`${prefixCls}-input-label`}>协议Id</span>
            <Input placeholder="请输入协议id" value={agreementValue} onChange={this.onChangeAgreementValue} />
          </div>
        </div>
        <div className={`${prefixCls}-signContainer`}>
          <Sign
            readOnly
            onClose={this.onClose}
            agreementIds={agreementValue}
          />

          <Sign
            visible={this.state.visible}
            onVisibleChange={this.onVisibleChange}
            onAgree={this.onAgree}
            onDisagree={this.onDisagree}
            agreementIds={agreementValue}
          >
            <span className="btn" onClick={this.changeVisible}>签署协议</span>
          </Sign>
        </div>

        <h3>多协议</h3>
        <div className={`${prefixCls}-edittable`}>
          <span>协议Id</span>
          <EditableTable
            columns={this.columns}
            comProps={this.comProps}
            data={agreementValues}
            topTools={this.topTools}
            onChange={this.onChangeAgreementsValue}
          />
        </div>
        <div className={`${prefixCls}-signContainer`}>
          <Sign
            readOnly
            onClose={this.onClose}
            agreementIds={agreementIds}
          />

          <Sign
            visible={this.state.visibleMul}
            onVisibleChange={this.onVisibleMulChange}
            onAgree={this.onAgreeChecked}
            onDisagree={this.onDisagreeChecked}
            agreementIds={agreementIds}
          >
            <div className="sign">
              <Checkbox value={this.state.checked} onChange={this.onChangeChecked} />
              <span className="title" onClick={this.changeVisibleMul}>签署协议</span>
            </div>
          </Sign>
        </div>

      </div>
    );
  }
}

export default SignDemo;
```

### 自定义内容

```jsx
import { Component } from 'react';
import { Sign, Checkbox, constants, CheckboxValueType } from '@weapp/ui';

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

class SignDemo extends Component<any, any> {

  constructor(props: any) {
    super(props);
    this.state = {
      visible: false,
      visibleMul: false,
      checked: false,
    }
  }
  renderContent = () => {
    return (<div>
      <h3 className={`${prefixCls}-content`}>e-cology用户协议隐私政策</h3>
      <div className={`${prefixCls}-content`}>前言</div>
      <br/>
      <div>
        xxxxx（以下统称"职尚"或者"我们"）非常重视用户的隐私和个人信息保护。您在使用我们的产品和服务时，我们可能会收集和使用您的相关信息。我们希望通过本《隐私保护政策》（以下简称"本政策"或者“本隐私政策”）向您说明在您接受我们的产品服务时，我们如何收集、使用、储存、共享和转让这些信息，以及我们为您提供的访问、更新、控制和保护这些信息的方式。<br/>
        我们深知个人信息对您的重要性，并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任，恪守以下原则，保护您的个人信息：权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公括银行账号、口令、交易和消费记录、虚拟货币、虚拟交易、兑换码等虚拟财产信息）、通讯录信息、个人上网记录。<br/>
        请在使用我们的服务前，仔细阅读并了解本政策，特别是免除或者限制责任的条款、法律适用和争议解决条款。如果您不同<br/>
        xxxxx（以下统称"职尚"或者"我们"）非常重视用户的隐私和个人信息保护。您在使用我们的产品和服务时，我们可能会收集和使用您的相关信息。我们希望通过本《隐私保护政策》（以下简称"本政策"或者“本隐私政策”）向您说明在您接受我们的产品服务时，我们如何收集、使用、储存、共享和转让这些信息，以及我们为您提供的访问、更新、控制和保护这些信息的方式。<br/>
        我们深知个人信息对您的重要性，并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任，恪守以下原则，保护您的个人信息：权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公括银行账号、口令、交易和消费记录、虚拟货币、虚拟交易、兑换码等虚拟财产信息）、通讯录信息、个人上网记录。<br/>
        请在使用我们的服务前，仔细阅读并了解本政策，特别是免除或者限制责任的条款、法律适用和争议解决条款。如果您不同我们深知个人信息对您的重要性，并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任，恪守以下原则，保护您的个人信息：权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公括银行账号、口令、交易和消费记录、虚拟货币、虚拟交易、兑换码等虚拟财产信息）、通讯录信息、个人上网记录。我们深知个人信息对您的重要性，并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任，恪守以下原则，保护您的个人信息：权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公括银行账号、口令、交易和消费记录、虚拟货币、虚拟交易、兑换码等虚拟财产信息）、通讯录信息、个人上网记录。
      </div>
    </div>)
  }
  menus = [
    {
      id: 'protocol1',
      content: 'e-cology用户协议隐私政策',
    },
    {
      id: 'protocol2',
      content: '隐私政策1',
    },
    {
      id: 'protocol3',
      content: '隐私政策2',
    }
  ]
  mulContent = {
    'protocol1': this.renderContent(),
    'protocol2': "隐私协议1内容",
    'protocol3': "隐私协议2内容",
  }
  changeVisible = () => this.setState({ visible: true })
  changeVisibleMul = () => this.setState({ visibleMul: true })
  onVisibleChange = (visible: boolean) => this.setState({ visible: visible });
  onVisibleMulChange = (visible: boolean) => this.setState({ visibleMul: visible });
  onClose = () => {
    console.log('---onClose---');
  }
  onAgree = () => {
    console.log('---onAgree---');
  }
  onDisagree = () => {
    console.log('---onDisagree---');
  }
  onAgreeChecked = () => {
    console.log('---onAgree---');
    this.onChangeChecked(true);
  }

  onDisagreeChecked = () => {
    console.log('---onDisagree---');
  }

  onChangeChecked = (value: CheckboxValueType) => this.setState({ checked: value });

  render() {
    return (
      <div className={prefixCls}>

        <h3>单协议</h3>
        <div className={`${prefixCls}-signContainer`}>
          <Sign
            content={this.renderContent()}
            title="隐私协议"
            readOnly
            onClose={this.onClose}
            mode="custom"
          />

          <Sign
            content={this.renderContent()}
            title="隐私协议"
            visible={this.state.visible}
            onVisibleChange={this.onVisibleChange}
            onAgree={this.onAgree}
            onDisagree={this.onDisagree}
            mode="custom"
          >
            <span className="btn" onClick={this.changeVisible}>签署协议</span>
          </Sign>
        </div>

        <h3>多协议</h3>

        <div className={`${prefixCls}-signContainer`}>
          <Sign
            menus={this.menus}
            content={this.mulContent}
            title="隐私协议"
            readOnly
            onClose={this.onClose}
            mode="custom"
          />

          <Sign
            title="隐私协议"
            menus={this.menus}
            content={this.mulContent}
            visible={this.state.visibleMul}
            onVisibleChange={this.onVisibleMulChange}
            onAgree={this.onAgreeChecked}
            onDisagree={this.onDisagreeChecked}
            mode="custom"
          >
            <div className="sign">
              <Checkbox value={this.state.checked} onChange={this.onChangeChecked} />
              <span className="title" onClick={this.changeVisibleMul}>签署协议</span>
            </div>
          </Sign>
        </div>

      </div>
    );
  }
}

export default SignDemo;
```

## API

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| visible | 显示受控 | boolean | 否 | false |
| onVisibleChange | 显示受控回调 | (visible: boolean) => void | 否 |  |
| destroyOnClose | 关闭时全量销毁 | boolean | 否 | true |
| dialogProps | 自定义弹框配置 | DialogProps | 否 |  |
| title | 自定义弹框标题 | string | 否 |  |
| onAgree | 同意按钮回调 | () => void | 否 |  |
| onDisagree | 不同意按钮回调 | () => void | 否 |  |
| onClose | 弹框关闭回调 | () => void | 否 |  |
| content | 自定义协议内容 | SignContent \| SignContentType | 否 |  |
| menus | 自定义页签项 | MenuItemData[] | 否 |  |
| readOnly | 只读(即只查看协议) | boolean | 否 | false |
| mode | 组件模式 | "url" \| "custom" | 否 | "url" |
| agreementIds | 协议Id(url模式使用) | string\| string[] | 否 |  |
| tabParams | 请求页签项接口自定义参数(url模式使用) | AnyObj | 否 |  |
| contentParams | 请求内容项接口自定义参数(url模式使用) | AnyObj | 否 |  |
| commonParams | 请求接口公共自定义参数(url模式使用) | AnyObj | 否 |  |
| contentType | 内容区数据展示类型 | 'richtext' \| 'html' \| 'string' | 否 | richtext |
| delay | 自定义按钮禁用时间(协议强制阅读时间) | number | 否 | 3 |
### type类似详细说明如下：

#### 1.SignContent

```
type SignContent = string | ReactNode;
```

#### 2.SignContentType

```
interface SignContentType {
  [key: string]: SignContent;
}
```

### 判断是否需要签署协议公共方法 (Sign.isNeedSignAgreement)

```
isNeedSignAgreement: (agreementIds: string[], otherParams?: AnyObj) => AnyObj;

1.参数说明
  agreementIds：协议ids
  otherParams：自定义参数
2.接口返回值说明：接口/api/bs/datasecurity/privacy/assembly/isNeedSignAgreement的返回值
```
