# 意见放表单二开口子

> 负责人: 李佳（前端）、李盛平（后端）

## 一、前端js-sdk

### 1、获取所有意见放表单控件的id
>getSignLayoutIds

* 注意：获取当前页面上已加载的所有意见放表单控件的id，未产生数据的获取不到。
#### 1.1、示例
```javascript
const wffpSdk = weappWorkflow.getFlowPageSDK();
const signLayoutIds =  wffpSdk.getSignLayoutIds();
```

### 2、获取指定意见放表单控件的意见数据
>getSignLayoutByIds
#### 2.1、方法入参
| 参数名称             | 必填 | 类型      | 说明                          |
| :--------------- | :- | :------ | :-------------------------- |
| signLayoutId       | 是  | string    | 意见放表单控件的id                      |
| isGetOriginData           | 否  | boolean    | 是否获取接口返回的意见数据，默认true                  |

#### 2.2、示例
```javascript
const wffpSdk = weappWorkflow.getFlowPageSDK();
const layout1 =  wffpSdk.getSignLayoutByIds("942330526657593354");//获取指定意见的意见数据（从接口获取来的默认数据）
const layout2 =  wffpSdk.getSignLayoutByIds("942330526657593354",false);//获取指定意见的意见数据（当前正在渲染的数据）
```
### 3、修改指定意见放表单控件的意见数据
>filterSignLayout
#### 3.1、方法入参
| 参数名称             | 必填 | 类型      | 说明                          |
| :--------------- | :- | :------ | :-------------------------- |
| signLayoutId       | 是  | string    | 意见放表单控件的id                      |
| managerList           | 是  | Array    | 新的意见数据，格式见getSignLayoutByIds方法返回的数据格式                 |
#### 3.2、示例
```javascript
const wffpSdk = weappWorkflow.getFlowPageSDK();
const layout =  wffpSdk.getSignLayoutByIds("942330526657593354");//获取指定意见的意见数据（从接口获取来的默认数据）
wffpSdk.filterSignLayout("942330526657593354",layout.filter(it=>it.groupId === "938995325584400391"));//给指定的意见控件修改意见内容
```

### 4、重置/刷新指定意见放表单控件中的数据
>resetSignLayout
#### 4.1、方法入参
| 参数名称             | 必填 | 类型      | 说明                          |
| :--------------- | :- | :------ | :-------------------------- |
| signLayoutId       | 是  | string    | 意见放表单控件的id                      |
| needReq           | 是  | boolean    | 是否走接口重刷意见控件数据，默认false               |
#### 4.2、示例
```javascript
const wffpSdk = weappWorkflow.getFlowPageSDK();
wffpSdk.resetSignLayout("942330526657593354")//还原意见数据，用修改前的意见数据渲染
wffpSdk.resetSignLayout("942330526657593354",true)//走接口重刷意见控件内容
```

### 5、勾子事件，签字意见数据加载完成后执行
#### 方法一：
- 说明：开启预加载意见的情况使用，开启预加载的效果是，不管表单中有多少个签字意见插入表单控件，这些控件的意见内容信息都是一次性加载完毕，此勾子执行的时候，签字意见控件并没有初始化完毕，注意不要在这里面直接使用getSignLayoutIds方法
- 注册事件关键字：SignInFormPreLoadComplete
```javascript
const wffpSdk = window.weappWorkflow.getFlowPageSDK();
wffpSdk.registerHookEvent("SignInFormPreLoadComplete", function (config) {
 //签字意见数据加载完成，此时不能使用getSignLayoutByIds、getSignLayoutByIds、filterSignLayout、resetSignLayout等方法，由于意见控件未渲染完成，使用这些方法得到的结果是不符合预期的


}, true);
```
#### 方法二：
- 说明：签字意见控件渲染完毕后执行，表单中有多个签字意见插入表单控件，每个控件内的意见内容都是独立执行的，有多少个意见控件，就会执行多少次，这种情况，一定要注意防止代码重复执行
- 注册事件关键字：SignInFormLoadComplete
```javascript
const wffpSdk = window.weappWorkflow.getFlowPageSDK();
wffpSdk.registerHookEvent("SignInFormLoadComplete", function (config) {
  const { componentKey } = config;
  //意见放表单组件加载完成后执行此事件
  const layout = wffpSdk.getSignLayoutByIds(componentKey)
  console.log("componentKey_layout", componentKey, layout)

  let new_layout = [{
    ...layout,
    groupItemEntities: []
  }]
  wffpSdk.filterSignLayout(componentKey, new_layout);
}, true);
```

注意：可以按照下图顺序点击获取意见控件的componentKey

![](/api/ecode/resource/view/${appRes}/1717500930-image.png)

### 6、获取指定意见放表单控件的配置信息
>getSignConfigById
#### 6.1、方法入参
| 参数名称             | 必填 | 类型      | 说明                          |
| :--------------- | :- | :------ | :-------------------------- |
| signLayoutId       | 是  | string    | 意见放表单控件的id                      |
#### 6.2、示例
```javascript
const wffpSdk = weappWorkflow.getFlowPageSDK();
wffpSdk.getSignConfigById("942330526657593354")//获取指定意见放表单控件的配置信息
```
## 二、前端组件复写
### 1、ecode复写意见放表单操作人
```
1201基线包含，操作人可以复写代理人信息

1202基线包含，操作人可以复写自定加入的信息，操作人组件接收整个signData

```
1.1 实现效果

![](https://weapp.eteams.cn/api/file/preview?fileId=975754790999064586&type=imgs)


1.2 props关键词释义
```javascript
interface propsType {
    agent: any,//代理人（封装了人员卡片的）
    separator?: string,//分割符（代理人与被代理人的）
    operator: any,//被代理人
    isMobile?: boolean,//是否是移动端
    showAgent?: boolean,//是否显示代理人信息
    signData: any,//当前意见信息，用于二开自定义复写渲染意见信息中的customInfoMap下数据
}

```
1.3 demo

entry.js
```javascript
import React from 'react';
import { regOvComponent } from '@weapp/utils';
import { asyncImport } from '@weapp/ecodesdk';

//复写操作者（含代理）的展示组件
const NewWfCusSignLayoutOperateContent = React.lazy(() => asyncImport('${appId}', 'NewWfCusSignLayoutOperateContent'));
const overwriteFunction1 = (Com) => {
  return React.forwardRef((props, ref) => {
    return (
      <React.Suspense fallback={() => {}}>
        <NewWfCusSignLayoutOperateContent ref={ref} {...props} OriginCom={Com} />
      </React.Suspense>
    )
  });
}
regOvComponent('weappWorkflow', 'WfCusSignLayoutOperateContent', overwriteFunction1, 0)
```
NewWfCusSignLayoutOperateContent.js
```javascript
export default class NewWfCusSignLayoutOperateContent extends React.Component<any>{
  constructor(props: propsType) {
    super(props);
  }

  render() {
    const { agent, operator, showAgent, signData, OriginCom } = this.props;
    console.log(this.props)
    if(showAgent){
      return <> {agent}[{operator}] </>
    }
    return <>[{operator}] </>
  }
}
```

### 2、ecode复写单条签字意见内容
2.1 、实现效果
![](/api/ecode/resource/view/${appRes}/1712047819-image.png)

2.2 props关键词释义

| key             |描述|
| :--------------- | :- |
| atContent       | 签字意见内容|
| agent           | 代理人 |
|atLinkMap|@人员信息|
|attachments|附件|
|beAgentUserId|被代理人id|
|beAgentUserName|被代理人名称|
|clientType|客户端类型|
|commentName|操作名称|
|content|签字意见内容|
|deptName|分部名称|
|fullTextAnnotation|全文批注|
|isAgent|是否是代理|
|logId|签字意见id|
|logType|签字意见类型|
|logTypeCode|意见类型编码|
|nodeId|节点id|
|nodeOrderId|节点顺序id|
|operateDatetime|操作时间|
|operator|操作者|
|operatorDept|操作者分部|
|operatorJob|操作者岗位|
|operatorSub|操作者部门|
|sevLevel|安全级别|
|showOrder|显示顺序|
|stepName|节点名称|
|subComName|团队名称|
|userName|用户名称|
|usertype|用户类型|

2.3 demo

entry.js
```javascript
import React from 'react';
import { regOvComponent } from '@weapp/utils';
import { asyncImport } from '@weapp/ecodesdk';

const NewWfSignLayoutContent = React.lazy(() => asyncImport('${appId}', 'NewWfSignLayoutContent'));
const overwriteFunction2 = (Com) => {
  return React.forwardRef((props, ref) => {
    return (
      <React.Suspense fallback={() => {}}>
        <NewWfSignLayoutContent ref={ref} {...props} OriginCom={Com} />
      </React.Suspense>
    )
  });
}
regOvComponent('weappWorkflow', 'WfSignLayoutContent', overwriteFunction2, 0)
```
NewWfSignLayoutContent.js
```javascript
import { Comment, HrmCard, Button } from '@weapp/ui';
const { CommentContent } = Comment;
const { openHrmCard } = HrmCard;

export default class NewWfSignLayoutContent extends React.Component<any>{
  constructor(props: propsType) {
    super(props);
  }
  //操作人点击人员卡片事件
  showCard = (e) => {
    const { signData = {} } = this.props;
    openHrmCard(e, signData.operator, 'inside', 'bs/hrm')
  }

   click=()=>{
      const {signData={}}=this.props;
      alert(signData.logId)
    }

  render() {
    console.log(this.props);
    const { signData = {}, isMobile = false } = this.props;
    const { userName = "", operateDatetime = "" } = signData;
    let userNameShow = signData.userName || '';
    if (signData.operator === "0" && userNameShow == '') {
      userNameShow = getLabel('67334', "审批机器人")
    }
    let showContent = <a onClick={this.showCard} >{userNameShow}</a>;//操作人
    return <div style={{ border: "1px dashed #ddd" }}>
      <CommentContent 
        weId={`${this.props.weId || ''}_umt7i2`}
        value={signData.atContent || ''}
        userData={signData.atLinkMap}
        isMobile={isMobile}
        textToRichText={true}
      />
      <div>操作人：{showContent} 操作时间：{operateDatetime}</div>
      <Button type="primary" onClick={this.click}>按钮</Button>
    </div>
  }
}
```
### 3、ecode/代码块复写意见分组分隔符
```
意见分组分隔符的class分别为：
wfp-nodesign-view-signGroup-divider-mobile 移动端独有
wfp-nodesign-view-signGroup-divider-pc  pc端独有
```
示例：
![](https://weapp.eteams.cn/api/file/preview?fileId=975760872639201290&type=imgs)
![](https://weapp.eteams.cn/api/file/preview?fileId=975760992971038724&type=imgs)
![](https://weapp.eteams.cn/api/file/preview?fileId=975761108974813187&type=imgs)
![](https://weapp.eteams.cn/api/file/preview?fileId=975761271970496518&type=imgs)

### 4、代码块控制不显示空意见时意见整行屏蔽
**背景：** 当设置不显示空意见的时候，流程详情中意见的内容不会显示，但是意见所在的单元格会显示，但大部分场景下，用户期待的是意见所在的单元格也不显示，所以需要特殊处理一下

**不能控制隐藏行的场景：**
意见放表单控件不占满整行所有列时，不能隐藏行，隐藏行会影响除意见控件外其他列单元格的显示

**不显示空意见配置：**
![](/api/ecode/resource/view/${appRes}/1715939680-image.png)

![](/api/ecode/resource/view/${appRes}/1715939804-image.png)

**代码块不做控制时流程详情中的展示：**

![](/api/ecode/resource/view/${appRes}/1715939874-image.png)

**代码块示例：**

```css
table.weapp-de-excel-render-main tr:has(.wfp-nodesign-view-sign-empty){
	display: none;
}
```
**添加代码后的效果：**

![](/api/ecode/resource/view/${appRes}/1715940009-image.png)

### 5、ecode复写意见放表单整个控件
> demo效果:意见放表单控件完全自定义渲染，控制分组，点击分组名称可以折叠改分组意见

![](${appMdRes}/1747203801-image.png)
**代码块示例：**

entry.js
```typescript
import { regOvComponent } from '@weapp/utils';
import { asyncImport } from '@weapp/ecodesdk';


const NewWfSignLayoutView = React.lazy(() => asyncImport('${appId}', 'NewWfSignLayoutView'));
const overwriteFunction = (Com) => {
  return React.forwardRef((props, ref) => {
    return (
      <React.Suspense fallback={() => {}}>
        <NewWfSignLayoutView ref={ref} {...props} OriginCom={Com} />
      </React.Suspense>
    )
  });
}
regOvComponent('weappWorkflow', 'WfSignLayoutView', overwriteFunction, 0)

```


NewWfSignLayoutView.js
```typescript
import {Comment} from '@weapp/ui';
class Group extends React.Component<any,any>{
  constructor(props){
    super(props);
    this.state={visible:true}
  }
  onClick=()=>{
    this.setState({visible:!this.state.visible});
  }
  render() {
    const { CommentContent } = Comment;
    const { groupData, groupid } = this.props;
    return <div className={"ecode-signlayout-group"}>
      <div className={"ecode-signlayout-group-name"} onClick={this.onClick}>分组名称{groupid}</div>
      <div style={{display: this.state.visible?"block":"none"}}>
      {
        groupData.map(logItem => {
          return <div className={"ecode-signlayout-item"}>
            <div>
                <CommentContent 
                                    value={logItem.atContent||''}
                                    userData={logItem.atLinkMap}
                                    isMobile={this.props.isMobile}
                                    textToRichText={true}/>
            </div>
            <div>
              {logItem.userName}
            </div>
          </div>
        })
      }
      </div>
    </div>
  }
}

export default class NewWfSignLayoutContent extends React.Component<any>{

  wffpSdk = null;
  constructor(props: propsType) {
    super(props);
    this.wffpSdk = weappWorkflow.getFlowPageSDK();
  }

  render() {
    const { OriginCom } = this.props;
    if(!this.wffpSdk || !this.wffpSdk.getSignLayoutByIds){//不是表单页面，不执行后面逻辑
      return <OriginCom {...this.props}/>
    }
    const {isMobile} = this.props;
    let layout = this.wffpSdk.getSignLayoutByIds(this.props.componentKey) || [];
    let config = this.wffpSdk.getSignConfigById(this.props.componentKey);
    if(config?.signGroupMould?.[0]?.id ) {//使用意见分组模板，不复写
      return <OriginCom {...this.props}/>
    } 
    console.log(this.props, layout, config);
    let dom=[];
    layout.map(item => {
      let group = [[], []];
      if (item.groupItemEntities && item.groupItemEntities.length > 0) {
        item.groupItemEntities.map((logItem, item) => {
          if (item % 2 == 0) {//偶数个分为一组
            group[0].push(logItem);
          } else {//基数个分为一组
            group[1].push(logItem);
          }
        })
      }
      console.log("group",group)
      dom.push(<div className={"ecode-signlayout-wrap" + item.groupId}>
        <Group groupData={group[0]} groupid="1" isMobile={isMobile}/>
        <Group groupData={group[1]} groupid="2" isMobile={isMobile}/>
      </div>);
    })
    console.log("dom",dom)
    return dom;
  }
}


```

index.css
```css
.ecode-signlayout-group{
  margin-bottom: 16px;
}
.ecode-signlayout-group-name{
  width: 100%;
  background-color: rgba(93, 156, 236, 0.2);
  font-size: 16px;
  font-weight: bold;
  border-left:2px solid #0470C1;
}
.ecode-signlayout-item{
  border-bottom: 1px dashed #ddd;
}
```
### 6、ecode复写意见放表单意见分组控件
> 支持的版本：250701及之后版本
> 涉及到的组件：WfSignGroupView

组件props中关键参数含义
| 参数名称 | 参数类型                       | 参数含义             |
| -------- | ------------------------------ | -------------------- |
| comName        |    signGroup\|groupName\| groupContent\|  groupDivider    |  signGroup:整个分组<br>groupName:意见分组名称<br>groupContent:意见分组内容<br>groupDivider:意见分组分隔符
|componentKey |string |意见控件唯一标识符|
|groupData|object|意见分组数据|
|isMobile|boolean|移动端标识|
|isPreview|boolean|是否是模板预览|

> demo效果：每一个分组单独加一个按钮，控制当前分组的隐藏

![](${appMdRes}/1751349977-image.png)

示例代码：
entry.js
```typescript
import { regOvComponent } from '@weapp/utils';
import { asyncImport } from '@weapp/ecodesdk';

const NewWfSignGroupView = React.lazy(() => asyncImport('${appId}', 'NewWfSignGroupView'));
const overwriteFunction = (Com) => {
  return React.forwardRef((props, ref) => {
    return (
      <React.Suspense fallback={() => {}}>
        <NewWfSignGroupView {...props} OriginCom={Com} ref={ref} forwardedRef={ref} />
      </React.Suspense>
    )
  });
}

regOvComponent('weappWorkflow', 'WfSignGroupView', overwriteFunction, 0)

```
NewWfSignGroupView.js

```typescript
export default class NewWfSignGroupView extends React.Component<any>{

  wffpSdk = null;
  constructor(props: propsType) {
    super(props);
    this.wffpSdk = weappWorkflow.getFlowPageSDK();
    this.state = {
      visible: true
    }
  }
  onClick = () => {
    this.setState({ visible: !this.state.visible });
  }
  render() {
    const { OriginCom, comName, componentKey , forwardedRef} = this.props;
    const { visible } = this.state;
    if (comName === 'signGroup') {//分组内容控制显示隐藏
      return <tbody className='group-content-wrap'>
         <tr >
            <td width='120px'><button onClick={this.onClick} className='group-content-visible-control'>显示/隐藏</button></td>
          </tr>
         
          {visible && <OriginCom {...this.props} ref={forwardedRef} />}
      </tbody>
    } else {
      //什么都不修改，返回原组件
      return <OriginCom {...this.props} ref={forwardedRef}/>
    }
  }
}


```
style.css
```css
.group-content-wrap .group-content-visible-control{ 
  background: #ddd;
  cursor: pointer;
}
```

### 7、ecode复写意见放表单单条意见每个意见类型控件
> 支持的版本：250701及之后版本
> 涉及到的组件：WfSignLayoutContentCom

组件props中关键参数含义
| 参数名称 | 参数类型                       | 参数含义             |
| -------- | ------------------------------ | -------------------- |
|comName        | string | 组件名称|
|componentKey |string |意见控件唯一标识符|
|signData|object|签字意见数据|
|isMobile|boolean|移动端标识|
|isPreview|boolean|是否是模板预览|

comName可配置范围
|关键词|释义|
| -------- | --------- | 
|remark | 签字意见内容 |
|remarkSource  |意见来源  |
|remarkLocation  | 位置 |
|remarkFile  |签字意见附件  |
|deptName  | 部门 |
|subComName   | 分部 |
|jobName  | 岗位 |
|nodeName  | 节点名称 |
|operateDate  | 操作日期 |
|operateTime | 操作时间 |
|commentName|操作|
|associated|关联事项|

> demo：复写意见放表单控件单条意见内每一种属性对应的内容

![](${appMdRes}/1751353376-image.png)

示例代码
entry.js
```typescript
import { regOvComponent } from '@weapp/utils';
import { asyncImport } from '@weapp/ecodesdk';

const NewSignLayoutContentCom = React.lazy(() => asyncImport('${appId}', 'NewSignLayoutContentCom'));
const overwriteFunction = (Com) => {
  return React.forwardRef((props, ref) => {
    return (
      <React.Suspense fallback={() => {}}>
        <NewSignLayoutContentCom {...props}  OriginCom={Com} ref={ref} forwardedRef={ref}/>
      </React.Suspense>
    )
  });
}

regOvComponent('weappWorkflow', 'WfSignLayoutContentCom', overwriteFunction, 0)


/**
 * 复写操作者信息，用这段逻辑，复写其他内容，用上面那段逻辑
 */
const NewWfCusSignLayoutOperateContent = React.lazy(() => asyncImport('${appId}', 'NewWfCusSignLayoutOperateContent'));
const overwriteFunction1 = (Com) => {
  return React.forwardRef((props, ref) => {
    return (
      <React.Suspense fallback={() => {}}>
        <NewWfCusSignLayoutOperateContent {...props} OriginCom={Com}   forwardedRef={ref} />
      </React.Suspense>
    )
  });
}
regOvComponent('weappWorkflow', 'WfCusSignLayoutOperateContent', overwriteFunction1, 0)
```

NewSignLayoutContentCom.js
```typescript
export default class NewSignLayoutContentCom extends React.Component<any>{

  wffpSdk = null;
  constructor(props: propsType) {
    super(props);
    this.wffpSdk = weappWorkflow.getFlowPageSDK();
  }
  render() {
    const { OriginCom, comName, componentKey, forwardedRef } = this.props;
    switch (comName) {
      case "remark":
      case "remarkSource":
      case "remarkLocation":
      case "remarkFile":
      case "deptName":
      case "subComName":
      case "jobName":
      case "nodeName":
      case "operateDate":
      case "operateTime":
      case "commentName":
      case "associated":
        return <div style={{ color: "red" }}>
          <OriginCom {...this.props} ref={forwardedRef}  />
        </div>
      default:
        return <OriginCom {...this.props} ref={forwardedRef} />
    }
  }
}


```
NewWfCusSignLayoutOperateContent.js
```typescript
export default class NewWfCusSignLayoutOperateContent extends React.Component<any>{
  constructor(props: propsType) {
    super(props);
  }

  render() {
    const { agent, operator, showAgent, signData, OriginCom } = this.props;
   // console.log(this.props,showAgent,operator,111111)
    if(showAgent){
      return <> {agent}[{operator}] </>
    }
    return <>[{operator}] </>
  }
}
```
### 8、代码块实现多内容的意见放表单控件空意见内容时不占高度


问题页面：
![](${appMdRes}/1755763929-image.png)
![](${appMdRes}/1755763887-image.png)
修改后的效果：

![](${appMdRes}/1755764007-image.png)

相关代码
```css
.wfp-nodesign-view:empty {
    display: none;
}
```
代码添加位置：
![](${appMdRes}/1755764069-image.png)

![](${appMdRes}/1755764093-image.png)

### 9、使用类似e9配置文件控制签字意见分隔符的控制
- e9配置文件地址：ecology/WEB-INF\prop\WFShowDotted.properties
- e10不用配置文件，改用ecode控制达到相同效果

> 支持的版本：260101及之后版本 

> 涉及到的方法 window.weappWorkflow?.writeConfig?.('WFP_SigninLayout_Content_Divider',obj)

obj释义
| 参数名称   | 参数类型   | 参数含义 |是否必传|  可以设置的值 |
| -------- | --------| --------|---- |--------|
|showdotted|number  |开关控制是否显示分割符| 是|0 关闭，不显示分隔符<br>1 开启，显示分隔符|
|color     | number |分隔符颜色 |否|1 黑色<br><br>2 蓝色<br>3 红色<br>4 黄色<br>5 绿色<br>6 灰色|
|style     |number  |分隔符样式  |否|1 点状线<br>2 虚线<br>3 实线|
|length    |number  |分隔符长度  |否|60，70，80 ...(在60～100中间的数字)|
|hr        |JSX     |自定义分割符 |否| 例如：`<hr size="1" style="text-align:left;border:2px dotted;color:black;width:60%;"/>`
  

效果图：待补充
示例代码
entry.js
```typescript
import { regHook } from '@weapp/utils';

regHook('weappWorkflow', 'libReady', () => {
  //移动的operarea组件等表单渲染完再加载
  window.weappWorkflow?.writeConfig?.('WFP_SigninLayout_Content_Divider', {
    showdotted:1,
    color: 1,
    style: 1,
    length: 60,
    hr: ` <hr style='"margin: "0";text-align: "left";border: "1px solid";color:"red";width:"60%"' />`
  });
});


```

### 10、自定义扩展签字意见内容

> 意见显示内容配置，支持扩展自定义，如下图：

![](/ecodestatic/txproduction/resources/978777575968571392/image.png)

#### 10.1、意见模版配置，脚本扩展自定义元素

在流程的数据库，执行如下脚本:
```
INSERT INTO wfp_sdk_config
(id, create_time, update_time, creator, delete_type, tenant_key, config_name, config_value, config_desc)
VALUES(20, now(), now(), NULL, 0, 'all_teams', 'customSignShowContent', '[{"id":"-1","labelName":"意见接收人","labelKey":"custom_label_receiver","contentName":"意见接收人","contentKey":"custom_content_receiver"}]', '自定义意见显示内容设置');
```
字段说明：
```
config_name: 配置名称，固定写死customSignShowContent
config_value：配置值，是个json数组字符串，json属性说明：
	id：配置ID，自定义的配置，必须是负数
	labelName：标签名称
  	labelKey：标签key
  	contentName：内容名称
  	contentKey：内容key
如果labelName和contentName要支持多语言，可以配置为：名称$多语言标签ID$
```

#### 10.2、前台意见显示时，接口复写增加返回内容

>参考文档第6点：
https://weapp.eteams.cn/build/techdoc/wdoc/index.html#/public/doc/0364caf2-9fdf-4411-bdb4-1b6ec88403ca


#### 10.3、前台意见显示时，ecode复写

> 其中custom_content_receiver名称与脚本中contentKey对应

示例效果：

![](${appMdRes}/1765278520-image.png)

示例代码
entry.js
```typescript
import React from 'react';
import { regOvComponent } from '@weapp/utils';
import { asyncImport } from '@weapp/ecodesdk';

//复写自定义的签字意见内容组件
const NewWfCusSignLayoutContent = React.lazy(() => asyncImport('${appId}', 'NewWfCusSignLayoutContent'));
const overwriteFunction = (Com) => {
  return React.forwardRef((props, ref) => {
    return (
      <React.Suspense fallback={() => {}}>
        <NewWfCusSignLayoutContent ref={ref} {...props} OriginCom={Com} />
      </React.Suspense>
    )
  });
}
regOvComponent('weappWorkflow', 'WfCusSignLayoutContent', overwriteFunction, 0)


```
NewWfCusSignLayoutContent.js
```typescript
export default class NewWfCusSignLayoutContent extends React.Component<any>{
    constructor(props:propsType){
        super(props);
    }

    render(){
        console.log("2222",this.props);
        if(this.props.labelContentKey =="custom_content_receiver"){
          return "这是复写的内容"
        }
        return this.props.OriginCom;
    }
}
```
## 三、意见控件运行时接口
### 3.1、意见放入表单支持修改返回的意见内容
> 意见放入表单可以通过拦截钩子实现返回结果的自定义开发，例如修改意见操作类型名称、自定义增加额外的显示内容等
#### 3.1.1 、参数信息
| 参数顺序 | 参数类型                       | 参数说明             |
| -------- | ------------------------------ | -------------------- |
| 0        | ResponseFormLogEntity          | 意见放入表单返回实体 |
| 1        | List<RequestLogEntity>         | 原始签字意见数据信息 |
| 2        | WfpLayoutSignShowConfigRpcDto  | 后台模板控件设置信息 |
| 3        | Long                           | 流程请求requestId    |
| 4        | Long                           | 工作流workflowId     |
| 5        | WeaUser                        | user对象             |
| 6        | RequestUserAuthorityDataEntity | 流程权限信息         |
  
#### 3.1.2 、复写口子案例
  
  ```java
package com.weaver.seconddev.hooks.flowcore;

import com.weaver.loom.api.annotation.RegHook;
import com.weaver.loom.context.register.AbstractRegHookEvent;
import com.weaver.workflow.common.dto.signshow.WfpLayoutSignShowConfigRpcDto;
import com.weaver.workflow.common.entity.core.flow.RequestLogEntity;
import com.weaver.workflow.common.entity.core.flow.RequestUserAuthorityDataEntity;
import com.weaver.workflow.common.entity.core.flow.log.formlog.ResponseFormLogEntity;
import com.weaver.workflow.common.entity.org.WeaUser;

import java.util.List;

/**
 * 对意见放入表单返回数据进行复写-demo
 *  java文件必须放到com.weaver.seconddev包下
 *  监听只对指定的module模块生效，
 *  module说明
 *  workflow:流程模块
 *  odoc:公文
 *  若需要对多个模块生效，需要开发多个文件，指定不同的module，放到对应的服务
 */
@RegHook(module = "workflow", event = "overwriteFormLog", order = 0)
public class overwriteFormLogHook extends AbstractRegHookEvent {
    @Override
    public Object handle(Object[] args) throws Exception {
        //意见放入表单返回实体
        ResponseFormLogEntity responseFormLogEntity = (ResponseFormLogEntity) args[0];
        //原始签字意见数据信息
        List<RequestLogEntity>  requestLogByNodeIdAndLogTypeList = (List<RequestLogEntity>) args[1];
        //后台模板控件设置信息
        WfpLayoutSignShowConfigRpcDto signConfig = (WfpLayoutSignShowConfigRpcDto) args[2];
        //流程请求requestId
        Long requestId = (Long) args[3];
        //工作流workflowId
        Long workflowId = (Long) args[4];
        //user对象
        WeaUser user = (WeaUser) args[5];
        //流程权限信息
        RequestUserAuthorityDataEntity userAuth = (RequestUserAuthorityDataEntity) args[6];
        /**
         * 修改responseFormLogEntity即可实现自定义返回意见放入表单信息
         */
        return responseFormLogEntity;
    }
}
```


## 四、意见控件配置（RPC）

### 4.1、获取模板中单个意见组件的显示设置

> 获取模板中单个意见组件的显示设置

#### 4.1.1 、请求信息

*   请求方式：RPC
*   请求group：workflow
*   请求地址：com.weaver.workflow\.pathdef.api.rest.signshow\.WfpSignShowRest#getLayoutSignShow

#### 4.1.2 、入参说明

> **入参说明：**

| 参数名称      | 参数描述               | 必选 | 类型                                                                              |
| :-------- | :----------------- | :- | :------------------------------------------------------------------------------ |
| paramsDto | 工作流id集合            | 是  | com.weaver.workflow\.common.dto.signshow\.WfpLayoutSignShowConfigRpcParamsDto对象 |
| userId    | 用户id，employee对象的id | 是  | long                                                                            |

> com.weaver.workflow\.common.dto.signshow\.WfpLayoutSignShowConfigRpcParamsDto参数属性说明

```java
```

| 属性名称             | 必填 | 类型      | 说明                          |
| :--------------- | :- | :------ | :-------------------------- |
| workflowId       | 是  | long    | 工作流id                       |
| nodeId           | 是  | long    | 节点id                        |
| layoutId         | 是  | long    | 模板id                        |
| componentKey     | 是  | String  | 组件id                        |
| source           | 否  | String  | 页面来源：如果是打印模板入口，传print\_page |
| hasPrintTemplate | 否  | boolean | 是否有打印模板：如果有打印模板，则传true      |

#### 4.1.3、调用示例

```java
@Autowired
public class Test {

    @RpcReference(group = "workflow")
    WfpSignShowRest wfpSignShowRest;

    public void test() {
        WfpLayoutSignShowConfigRpcDto layoutSignShow = wfpSignShowRest.getLayoutSignShow(paramsDto, user.getUserId());
    }
}
```

#### 4.1.4 、返回值说明

com.weaver.workflow\.common.dto.signshow\.WfpLayoutSignShowConfigRpcDto对象属性说明

```java
	/**
     * 工作流id
     */
    private long workflowId;

    /**
     * 关联id，节点关联nodeid/ 打印模板关联modeid/和设计器中单个意见组件关联组件id
     */
    private String targetId;

    /**
     * 应用场景，用于标识不同的功能入口 具体值参考WfpSignShowSceneEnum枚举
     */
    private int scene;

    /**
     * 显示类型下拉选择框，0全部、1选择、2排除
     */
    private int viewTypeSelect;

    /**
     * 显示类型 多选  数据库中以逗号分隔，具体值参考WfpSignShowViewTypeEnum枚举类
     */
    private String viewType;

    /**
     * 不显示空的意见
     */
    private boolean notShowEmpty;

    /**
     * 分栏显示
     */
    private int showColumn;

    /**
     * 显示方式  0：最后一次意见 1：全部意见
     */
    private int showType;

    /**
     * 意见是否按批次分组
     */
    private boolean isGroup;

    /**
     * 流转意见打印设置 0 始终不打印流转意见 1 流转意见放入模板时不打印 2 始终打印流转意见
     */
    private int printControl;

    /**
     * 选择格式  0:默认格式 1:自定义格式
     */
    private int selectFormat;

    /**
     * 显示内容，多选 具体值参考WfpSignShowViewContentTypeEnum枚举
     */
    private String viewContents;

    /**
     * 通用显示格式
     */
    private String showDesc;

    /**
     * 使用个性化签章时显示格式
     */
    private String signShowDesc;
	/**
     * 意见放入模板独有的设置====================开始==================
     */
	/**
     * 节点id 只有独立布局才有节点id
     */
    @JsonSerialize(using = ToStringSerializer.class)
    private long nodeId;

    /**
     * 模板id
     */
    @JsonSerialize(using = ToStringSerializer.class)
    private long layoutId;

    /**
     * 组件标识 组件唯一id
     */
    private String componentKey;

    /**
     * 选择审批流 0：当前审批流 1：子流程 2：主流程
     */
    private int workflowOption;
    /**
     * 选择的主/子审批流id
     */
    private long selectedWfid;

    /**
     * 选择模式 0：指定显示节点 1：意见自动分组
     */
    private int patternOption;

    /**
     * 选择的模式 如果是指定显示节点就是节点id；其他值参考WfpSignShowPatternTypeEnum枚举
     */
    /**
     * 需求变更。 当patternOption选择的意见自动分组时，selectedPattern存分组类型
     * 意见分组(节点意见):-1;意见分组(部门意见):-2;意见分组(分部意见):-3）
     * 指定显示节点不再存这个字段
     */
    private long selectedPattern;

    /**
     * 是否使用默认设置
     */
    private boolean isDefaultConfig;

    /**
     * 节点/分部/部门排序  0:正序;1:倒序;2:时间正序;3:时间倒序
     */
    private int groupOrderType;

    /**
     * 意见排序设置，存的json串
     */
    private String showorder;

    /**
     * 节点范围类型 0：全部 1：选择 2：排除选择 3：自由节点
     */
    private int nodescopeType;

    /**
     * 数据多选表外键关联的节点范围
     */
    private List<Long> nodeList = new ArrayList<>();

    /**
     * 模板中单元格标识,例如main-25-1，后续数据迁移存储e9workflow_signinput表的uuid
     */
    private String cellUuid;

    /**
     * 意见显示范围-关联的接收人范围id
     */
    private long receiverRangeKey;

    /**
     * 意见显示范围设置-接收人范围信息
     */
    private WfpReceiverRangeRpcDto receiverRangeInfo;

    /**
     * 意见放入模板独有的设置====================结束==================
     */

    /**
     * 前端用于替换标签
     */
    private List<Map<String,Object>> lableContentList;
    private List<Map<String,Object>> lableList;

    /**
     * 意见模板ID
     */
    private long signGroupMould;

    /**
     * 意见模板数据
     */
    private WfpSignGroupMouldDataDTO signGroupMouldDataDTO;
```

### 4.2、获取模板中所有意见组件的显示设置

> 获取模板中所有意见组件的显示设置

#### 4.2.1 、请求信息

*   请求方式：RPC
*   请求group：workflow
*   请求地址：com.weaver.workflow\.pathdef.api.rest.signshow\.WfpSignShowRest#getLayoutSignShowByLayoutId

#### 4.2.2 、入参说明

> **入参说明：**

| 参数名称      | 参数描述               | 必选 | 类型                                                                              |
| :-------- | :----------------- | :- | :------------------------------------------------------------------------------ |
| paramsDto | 工作流id集合            | 是  | com.weaver.workflow\.common.dto.signshow\.WfpLayoutSignShowConfigRpcParamsDto对象 |
| userId    | 用户id，employee对象的id | 是  | long                                                                            |

> com.weaver.workflow\.common.dto.signshow\.WfpLayoutSignShowConfigRpcParamsDto参数属性说明

```java
```

| 属性名称             | 必填 | 类型      | 说明                          |
| :--------------- | :- | :------ | :-------------------------- |
| workflowId       | 是  | long    | 工作流id                       |
| nodeId           | 是  | long    | 节点id                        |
| layoutId         | 是  | long    | 模板id                        |
| source           | 否  | String  | 页面来源：如果是打印模板入口，传print\_page |
| hasPrintTemplate | 否  | boolean | 是否有打印模板：如果有打印模板，则传true      |

#### 4.2.3、调用示例

```java
@Autowired
public class Test {

    @RpcReference(group = "workflow")
    WfpSignShowRest wfpSignShowRest;

    public void test() {
        List<WfpLayoutSignShowConfigRpcDto> layoutSignShowByLayoutId = wfpSignShowRest.getLayoutSignShowByLayoutId(paramsDto, user.getUserId());
    }
}
```
## 五、二开场景

### 5.1、意见放表单控件在多内容单元格中，出现空白问题解决方案
  
  下载文件中的附件，导入ecode平台：https://www.e-cology.com.cn/sp/doc/docShare/1269760725527470082?tenantKey=t7akvdnf84