---
source: "https://weapp.eteams.cn/build/techdoc/wdoc/index.html#/public/doc/06d57a05-ae69-48c7-b6c2-f37ffbc7df92"
publicId: "06d57a05-ae69-48c7-b6c2-f37ffbc7df92"
---

# 文档比对后端二开

**第一步：新建一个类继承com.weaver.doc.client.compare.remote.DocCompareProviderService类**

**第二步：根据第三方比对接口功能重写实现DocCompareProviderService类中的方法，必须实现的方法参考下文中的代码示例**

特别说明：

1. 此二开不是在二开服务里面开发，新建一个项目开发。开发完成后打成jar包上传到weaver-doccompare-service服务
2. 本地项目开发环境中的依赖去服务器weaver-doccompare-service服务的class目录下拿，拿过来放在/devLib/classes目录下。build.gradle配置文件增加以下配置项：

**注意：本地开发必须的jar包依赖**

weaver-doccompare-client（文档比对接口依赖）、weaver-file-upload-download（文件服务SDK依赖）

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

**第三步：二开代码生效后通过在租户后台配置文档比对的方式，选中二开新增的文档比对服务商配置并保存。在OA页面文档比对模块中执行文档比对操作（支持通过跳转第三方链接的方式获取比对结果 以及 支持后端RPC接口调用方式获取文档比对结果详情）。**

**租户后台-文档比对配置**

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

**比对模块执行文档比对操作**

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

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

# 代码示例：

```java
package com.weaver.doc.compare.service.compare.provider;

import com.alibaba.fastjson.util.TypeUtils;
import com.qcloud.cos.utils.Jackson;
import com.weaver.common.component.form.item.WeaFormItem;
import com.weaver.common.component.form.item.WeaFormItemType;
import com.weaver.common.component.form.layout.WeaFormLayout;
import com.weaver.common.i18n.label.SystemEnv;
import com.weaver.doc.client.compare.entity.request.*;
import com.weaver.doc.client.compare.remote.DocCompareProviderService;
import com.weaver.doc.compare.common.utils.UserUtil;
import com.weaver.doc.compare.exception.GlobalException;
import com.weaver.doc.compare.service.compare.NewDocCompareService;
import com.weaver.eteams.file.client.file.FileData;
import com.weaver.eteams.file.client.remote.FileClientService;
import com.weaver.file.ud.api.FileDownloadService;
import com.weaver.framework.rpc.annotation.RpcReference;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.io.InputStream;
import java.util.*;

import static com.weaver.doc.compare.common.utils.DocCompareCommonUtil.getCompareOpSetting;

@Component
public class CustomCompareProvider implements DocCompareProviderService {

    private static final Logger logger = LoggerFactory.getLogger(CustomCompareProvider.class);

    private static final List<String> COMPARE_PROVIDER_ITEMS = new ArrayList<>();

    @Autowired
    @Qualifier("getRestTemplate")
    private RestTemplate restTemplate;

    @Autowired
    private FileDownloadService fileDownloadService;

    @Autowired
    private NewDocCompareService newDocCompareService;

    @Autowired
    private UserUtil userUtil;

    @RpcReference
    private FileClientService fileClientService;

    /**
     * 第三方比对元数据配置定义，确保不同的比对服务元数据配置唯一
     *
     * @return
     */
    @Override
    public DocCompareSetting getDocCompareSetting() {
        DocCompareSetting docCompareSetting = new DocCompareSetting();
        docCompareSetting.setCompareProviderId("second-compare");
        docCompareSetting.setCompareProviderName("第三方文档比对");
        docCompareSetting.setCompareProviderVersion("第三方文档比对-本地部署");
        return docCompareSetting;
    }

    /**
     * 后端-初始化文档比对所有配置参数，参数和getCompareProviderInfo方法中定义的保持统一
     * @return
     */
    @Override
    public List<String> getCompareProviderItems() {
        if (CollectionUtils.isNotEmpty(COMPARE_PROVIDER_ITEMS)) {
            return COMPARE_PROVIDER_ITEMS;
        }
        COMPARE_PROVIDER_ITEMS.add("user");
        COMPARE_PROVIDER_ITEMS.add("secret");
        COMPARE_PROVIDER_ITEMS.add("compare_address");
        COMPARE_PROVIDER_ITEMS.add("ignoreHandwriting");
        return COMPARE_PROVIDER_ITEMS;
    }

    /**
     * 租户后台-前端页面元素结构组装，自定义页面元素
     *
     * @param langId
     * @param layouts
     * @param data
     * @param items
     */
    @Override
    public void getCompareProviderInfo(Integer langId, List<List<WeaFormLayout>> layouts, Map<String, Object> data, Map<String, WeaFormItem> items) {
        // 账号
        WeaFormItem app_id = new WeaFormItem(WeaFormItemType.INPUT);
        app_id.setPlaceholder(SystemEnv.getHtmlLabelName(52341, langId, "请输入"));
        app_id.setRequired(true);
        items.put("user", app_id);
        List<WeaFormLayout> app_idLayout = new ArrayList<>();
        app_idLayout.add(new WeaFormLayout("user", "账号", "g1", new String[]{"user"}));
        layouts.add(app_idLayout);
        app_idLayout.get(0).setHide(true);

        // 密码
        WeaFormItem app_secret = new WeaFormItem(WeaFormItemType.PASSWORD);
        app_secret.setPlaceholder(SystemEnv.getHtmlLabelName(52341, langId, "请输入"));
        app_secret.setRequired(true);
        items.put("secret", app_secret);
        List<WeaFormLayout> app_secretLayout = new ArrayList<>();
        app_secretLayout.add(new WeaFormLayout("secret", "密码", "g1", new String[]{"secret"}));
        layouts.add(app_secretLayout);
        app_secretLayout.get(0).setHide(true);

        // 忽略符号
        items.put("compare_address", new WeaFormItem(WeaFormItemType.SWITCH));
        List<WeaFormLayout> ignore_symbolLayout = new ArrayList<>();
        ignore_symbolLayout.add(new WeaFormLayout("compare_address", "比对地址", "g2", new String[]{"compare_address"}));
        layouts.add(ignore_symbolLayout);
        ignore_symbolLayout.get(0).setHide(true);

        // 忽略手写....
        items.put("ignoreHandwriting", new WeaFormItem(WeaFormItemType.SWITCH));
        List<WeaFormLayout> ignore_handwritingLayout = new ArrayList<>();
        ignore_handwritingLayout.add(new WeaFormLayout("ignoreHandwriting", "忽略手写", "g2", new String[]{"ignoreHandwriting"}));
        layouts.add(ignore_handwritingLayout);
        ignore_handwritingLayout.get(0).setHide(true);
    }

    /**
     * 自定义前端 和 后台参数映射，默认保持一致
     * @param data
     * @param compareEntity
     */
    @Override
    public void addProviderInfoData(Map<String, Object> data, CompareEntity compareEntity) {
        Map extSetting = Optional.ofNullable(Jackson.fromJsonString(compareEntity.getExtSetting(), Map.class)).orElse(new HashMap<>());
        if (!ObjectUtils.isEmpty(extSetting) && !ObjectUtils.isEmpty(extSetting.get("user"))) {
            data.put("user", extSetting.get("user"));
        }
        if (!ObjectUtils.isEmpty(extSetting) && !ObjectUtils.isEmpty(extSetting.get("secret"))) {
            data.put("secret", extSetting.get("secret"));
        }
        if (!ObjectUtils.isEmpty(extSetting) && !ObjectUtils.isEmpty(extSetting.get("compare_address"))) {
            data.put("compare_address", extSetting.get("compare_address"));
        }
        if (!ObjectUtils.isEmpty(extSetting) && !ObjectUtils.isEmpty(extSetting.get("ignoreHandwriting"))) {
            data.put("ignoreHandwriting", extSetting.get("ignoreHandwriting"));
        }
    }

    /**
     * 文档比对模块-组装文档比对功能按钮，g2分组
     * @param compareEntity
     * @return
     */
    @Override
    public Map<String, Map<String, Object>> getCompareOptionSetting(CompareEntity compareEntity) {
        Map<String, Map<String, Object>> map = new LinkedHashMap<>();
        if (Objects.nonNull(compareEntity) && StringUtils.isNotBlank(compareEntity.getExtSetting())) {
            Map extSetting = Optional.ofNullable(Jackson.fromJsonString(compareEntity.getExtSetting(), Map.class)).orElse(new HashMap<>());
            map.put("ignoreHandwriting", getCompareOpSetting(TypeUtils.castToBoolean(extSetting.get("ignoreHandwriting")),
                    "忽略手写"));
        }
        return map;
    }

    /**
     * 根据传参生成第三方文档比对链接
     *
     * @param compareEntity
     * @param uploadCompareDto
     * @param baseEntityRs
     * @param param
     * @return
     */
    @Override
    public Map<String, Object> uploadCompareDto(CompareEntity compareEntity, UploadCompareDto uploadCompareDto, NewDocComparedBaseEntity baseEntityRs, UploadDto param) {
        // 获取租户后台比对设置
        Map extSettingMap = Optional.ofNullable(Jackson.fromJsonString(compareEntity.getExtSetting(), Map.class)).orElseThrow(() -> new GlobalException("extSettingMap is empty"));
        // uploadCompareDto包含了前端传递的比对参数内容
        // 基准文件ID
        uploadCompareDto.getLeftFileId();
        // 比对文件ID
        uploadCompareDto.getRightFileId();
        // 额外参数
        uploadCompareDto.getExtraOptions();

        // 根据文件ID获取文件流方法，用于获取文件上传文件到第三方文档比对服务
        FileData fileData = fileDownloadService.downloadFile(uploadCompareDto.getLeftFileId());
        try (InputStream inputStream = fileData.getInputStream()) {

        } catch (Exception e) {

        }

        // 返回第三方的文档比对结果链接用于前端页面跳转，compareLink是固定值不能修改
        Map<String, Object> result = new HashMap<>();
        result.put("compareLink", "");
        return result;
    }
}
```
