npm package: @shujujiang/doc-form
Description: Doc-Form展示模块
Author: appleskiller@163.com
Latest version: 1.0.49

# doc-form

## 介绍
带有表单项的文书内容渲染库

## 查看demo

`npm start`

## 使用示例

#### 场景A： 显示文书内容、获取文书内容及数据

```javascript
import { docform } from '@shujujiang/doc-form';

const template = `
<h2 style="text-align: center;">标题</h2>
<p>内容</p>
<!--dockform:9bd2ba7c-fcdc-4131-9aaa-0dc7e1768087--><!--dockform:3d263bcc-9188-4d21-a2d6-b9745c4ef4ce-->
`;
const metadata = {
    pageSetting: {
        direction: "vertical",
        paddingBottom: 96,
        paddingLeft: 120,
        paddingRight: 120,
        paddingTop: 96,
        paper: "A4",
    },
    formItems: [
        {
            "id": "9bd2ba7c-fcdc-4131-9aaa-0dc7e1768087",
            "type": "SIGNATURE",
            "mode": "block",
            "name": "当事人签字"
        },
        {
            "id": "3d263bcc-9188-4d21-a2d6-b9745c4ef4ce",
            "type": "SIGNDATE",
            "mode": "block",
            "name": "签字日期"
        }
    ]
}
const values = {}
// 填充内容数据并设置访问权限
const ref = docform.display(container, template, metadata, values, DocformRole.client);
// 监听onSign，做签字按印的后续处理
ref.formControl.onSign.listen(event => {
    // 回调传回签印图片
    event.sign(signImg);
})
// 监听表单项目的值变更事件
ref.formControl.onValueChange.listen(event => {
    console.log('value change:', event);
    console.log('data:', ref.toSave());
});
// 获得当前内容文本（html内容文本）
ref.toContent();
// 获得当前内容数据
ref.toSave();
```

**关于表单项编辑权限的说明：**

```typescript
export const DocformRole = {
    // 当事人
    'client': 'client',
    // 责任人（办事民警）
    'responsible': 'responsible',
    // 只读（不可编辑）
    'none': 'none',
    // 任何角色可编辑
    'any': 'any',
}
```

表单项的元数据中定义了可以修改该项的角色（假设为item.role），同时当调用`docform.display(...)`接口创建文档实例时需要指定当前场景的角色(假设设为role)，此时决定各表单项目是否可被编辑的检查逻辑如下：

1. 如果`role === none`则无论`item.role`为何值，该表单项不可编辑
2. 如果`role === any`则无论`item.role`为何值，该表单项都允许编辑
3. 如果`item.role === any`则无论`role`为何值，该表单项允许编辑
4. 如果`item.role === none`则无论`role`为何值，该表单项不可编辑
5. 最后当`item.role === role`时表单项允许编辑，否则不可编辑

#### 场景B： 表单项单步编辑（问答项目）

```javascript
import { docform } from '@shujujiang/doc-form';
const datas: IFormShowItem[] = [{
    id: 1,
    // 审讯问题
    sxwt: '输入框：',
    // 问题序号
    wtxh: 1,
    // 父级问题
    fjwt: null,
    // 元数据
    ysj: {
        id: uuid(),
        type: WidgetType.INPUT,
        mode: 'inline',
        name: '输入框：',
        prefix: '￥',
        suffix: '万',
    },
}, {
    id: 2,
    // 审讯问题
    sxwt: '数值输入框：',
    // 问题序号
    wtxh: 2,
    // 父级问题
    fjwt: null,
    // 元数据
    ysj: {
        id: uuid(),
        type: WidgetType.NUMBER,
        mode: 'inline',
        name: '数值输入框：',
        prefix: '￥',
        suffix: '万',
    },
}];
const values = {
    1: '内容文本',
    2: 100
}
// 设置容器、表单项数据及表单项目值
const ref = docform.show(container, datas, values);
// 监听表单项目的值变更事件
ref.formControl.onValueChange.listen(event => {
    console.log(event);
});
// 获得当前正在编辑的表单项信息。
// 首次初始化ref后调用ref.current()，程序将自动查找最近的一个未填写完成的表单项作为当前项目
ref.current();
// 检查当前项目是否为第一项
ref.isFirst();
// 检查当前项目是否为最后一项
ref.isLast();
// 检查当前项目是否已经填写完整
ref.isInvalidCurrent();
// 检查全部项目是否已经填写完整
ref.isCompleted();
// 跳转到前一个表单项
ref.previous();
// 跳转到下一个表单项
ref.next();
```

#### 场景C：显示自述书内容、获取自述书内容及数据


```javascript
import { docform } from '@shujujiang/doc-form';

const template = 
const metadata = {
    pageSetting: {
        direction: "vertical",
        paddingBottom: 96,
        paddingLeft: 120,
        paddingRight: 120,
        paddingTop: 96,
        paper: "A4",
    },
    formItems: [
        {
            "id": "9bd2ba7c-fcdc-4131-9aaa-0dc7e1768087",
            "type": "SIGNATURE",
            "mode": "block",
            "name": "当事人签字"
        },
        {
            "id": "3d263bcc-9188-4d21-a2d6-b9745c4ef4ce",
            "type": "SIGNDATE",
            "mode": "block",
            "name": "签字日期"
        }
    ]
}

const doc = {
    template: `
        <h2 style="text-align: center;">标题</h2>
        <p>内容</p>
        <p><!--dockform:6f64258e-9542-4401-adbd-10a99f1cdbfb--></p>
        <!--dockform:ff9d3fb9-88ba-4f34-b8db-38750a625b3b--><!--dockform:6d66c355-6adc-47df-b8da-8a2efc5e7dc9-->
    `,
    ysj: {
        "pageSetting": {
            "direction": "vertical",
            "paper": "A4",
            "paddingTop": 96,
            "paddingBottom": 96,
            "paddingLeft": 120,
            "paddingRight": 120
        },
        "formItems": [
            {
                "id": "ff9d3fb9-88ba-4f34-b8db-38750a625b3b",
                "type": "SIGNATURE",
                "mode": "block",
                "name": "当事人签字",
                "role": "client"
            },
            {
                "id": "6d66c355-6adc-47df-b8da-8a2efc5e7dc9",
                "type": "SIGNDATE",
                "mode": "block",
                "name": "签字日期",
                "role": "client"
            }
        ]
    }
}

const wentis = [
    {
        "id": 36,
        "sxtg_id": 18,
        "sxwt": "输入框（inline）",
        "wtxh": 1,
        "bxda": [],
        "flfg": null,
        "dasjlx": null,
        "fjwt": null,
        "ysj": {
            "id": "6f64258e-9542-4401-adbd-10a99f1cdbfb",
            "type": "INPUT",
            "name": "输入框（inline）",
            "dataProvider": [],
            "role": "client",
            "mode": "inline",
            "prefix": "",
            "suffix": "",
            "isQAItem": true,
            "disableEditingInDoc": true,
            "disableCloneInDoc": true
        }
    }
]

const values = {
    "6f64258e-9542-4401-adbd-10a99f1cdbfb": '文本',
}

const template = doc.template;
const metadata = {
    ...doc.ysj,
    formItems: doc.ysj.formItems.concat(wentis.map(wenti => wenti.ysj))
};

// 填充内容数据并设置访问权限
const ref = docform.display(container, template, metadata, values, DocformRole.client);
// 监听onSign，做签字按印的后续处理
ref.formControl.onSign.listen(event => {
    // 回调传回签印图片
    event.sign(signImg);
})
// 监听表单项目的值变更事件
ref.formControl.onValueChange.listen(event => {
    console.log('value change:', event);
});
// 获得当前内容文本（html内容文本）
ref.toContent();
// 获得当前内容数据
// 因自述书存储结构与文书存储结构的差异，保存时需要拆分出问题及自述书ysj内容
const data = ref.toSave();
const formItems = data.metadata && data.metadata.formItems ? data.metadata.formItems : [];
// 剔除问题
const saveItems = formItems.filter(item => !item.isQAItem);
// 剔除问题结果
const wentis = formItems.filter(item => !!item.isQAItem);
const values = {...(data.values || {})};
wentis.forEach(item => {
    delete values[item.id];
});
// 构造最终自述书部分的模板
const saveTemplate = data.template || '';
// 构造最终自述书部分的元数据内容
const ysj = {
    pageSetting: data.metadata && data.metadata.pageSetting ? data.metadata.pageSetting : null,
    formItems: saveItems,
    values: values
}
console.log('自述书部分的模板', saveTemplate);
console.log('自述书部分的元数据', ysj);
```