liweifan 3 gadi atpakaļ
vecāks
revīzija
7c088101ee
25 mainītis faili ar 932 papildinājumiem un 178 dzēšanām
  1. 7 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/constant/SysConfigConstant.java
  2. 26 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/ContractTemplateSourceEnum.java
  3. 13 4
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/ContractTemplateTypeEnum.java
  4. 7 6
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/ContractTemplateController.java
  5. 6 9
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ContractTemplateDao.java
  6. 8 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/SysUserContractRecordDao.java
  7. 14 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/SysUserTsignDao.java
  8. 17 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ContractTemplate.java
  9. 94 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/SysUserTsign.java
  10. 0 35
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/ContractTypeEnum.java
  11. 10 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/ContractTemplateQueryInfo.java
  12. 17 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ContractService.java
  13. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ContractTemplateService.java
  14. 10 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/SysUserContractRecordService.java
  15. 14 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/SysUserTsignService.java
  16. 258 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ContractServiceImpl.java
  17. 36 47
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ContractTemplateServiceImpl.java
  18. 8 12
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserContractRecordServiceImpl.java
  19. 27 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserTsignServiceImpl.java
  20. 132 0
      cooleshow-user/user-biz/src/main/resources/config/contracts/latest_contract_template.ftl
  21. 28 25
      cooleshow-user/user-biz/src/main/resources/config/mybatis/ContractTemplateMapper.xml
  22. 31 8
      cooleshow-user/user-biz/src/main/resources/config/mybatis/SysUserContractRecordMapper.xml
  23. 71 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/SysUserTsignMapper.xml
  24. 26 20
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/SysUserContractRecordController.java
  25. 70 0
      cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/UploadFileController.java

+ 7 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/constant/SysConfigConstant.java

@@ -174,4 +174,11 @@ public interface SysConfigConstant {
 
     /** 老师分享曲目二维码跳转链接 */
     String TEACHER_MUSIC_SHEET_SHARE_URL = "teacher_music_sheet_share_url";
+
+    /** 公司名称 */
+    String COMPANY_NAME = "company_name";
+    /** 公司签章 */
+    String COMPANY_SEAL_PICTURE = "company_seal_picture";
+    /** 统一社会信用代码 */
+    String COMPANY_ORGAN_CODE = "company_organ_code";
 }

+ 26 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/ContractTemplateSourceEnum.java

@@ -0,0 +1,26 @@
+package com.yonge.cooleshow.common.enums;
+
+import com.yonge.toolset.base.enums.BaseEnum;
+
+public enum ContractTemplateSourceEnum implements BaseEnum<String, ContractTemplateSourceEnum> {
+    PLATFORM("平台协议"), LINGXINPAY("灵薪付");
+
+    private String code;
+
+    private String desc;
+
+    ContractTemplateSourceEnum(String desc) {
+        this.code = this.name();
+        this.desc = desc;
+    }
+
+    @Override
+    public String getCode() {
+        return this.code;
+    }
+
+    public String getDesc() {
+        return this.desc;
+    }
+
+}

+ 13 - 4
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/ContractTemplateTypeEnum.java

@@ -3,24 +3,33 @@ package com.yonge.cooleshow.common.enums;
 import com.yonge.toolset.base.enums.BaseEnum;
 
 public enum ContractTemplateTypeEnum implements BaseEnum<String, ContractTemplateTypeEnum> {
-    PLATFORM("平台协议"), WITHDRAW("提现协议(三方)");
+    REGISTER(ContractTemplateSourceEnum.PLATFORM, "注册"),
+    COURSES(ContractTemplateSourceEnum.PLATFORM, "课程购买"),
+    PRODUCT(ContractTemplateSourceEnum.PLATFORM, "产品"),
+    WITHDRAW(ContractTemplateSourceEnum.LINGXINPAY, "用户提现");
 
     private String code;
 
+    private ContractTemplateSourceEnum source;
+
     private String desc;
 
-    ContractTemplateTypeEnum(String desc) {
+    ContractTemplateTypeEnum(ContractTemplateSourceEnum source, String desc) {
         this.code = this.name();
+        this.source = source;
         this.desc = desc;
     }
 
     @Override
     public String getCode() {
-        return this.code;
+        return code;
     }
 
     public String getDesc() {
-        return this.desc;
+        return desc;
     }
 
+    public ContractTemplateSourceEnum getSource() {
+        return source;
+    }
 }

+ 7 - 6
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/ContractTemplateController.java

@@ -1,6 +1,6 @@
 package com.yonge.cooleshow.admin.controller;
 
-import com.yonge.cooleshow.biz.dal.enums.ContractTypeEnum;
+import com.yonge.cooleshow.common.enums.ContractTemplateSourceEnum;
 import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -24,7 +24,7 @@ import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.base.page.PageInfo;
 
 @RequestMapping("contractTemplate")
-@Api(tags = "机构协议模板")
+@Api(tags = "协议模板")
 @RestController
 public class ContractTemplateController extends BaseController {
 
@@ -38,6 +38,7 @@ public class ContractTemplateController extends BaseController {
 	@GetMapping(value = "/list")
 	@PreAuthorize("@pcs.hasPermissions('contractTemplate/list')")
 	public HttpResponseResult<PageInfo<ContractTemplateDto>> getList(ContractTemplateQueryInfo queryInfo) {
+		queryInfo.setSource(ContractTemplateSourceEnum.PLATFORM.getCode());
 		return succeed(contractTemplateService.queryPageList(queryInfo));
 	}
 
@@ -52,7 +53,7 @@ public class ContractTemplateController extends BaseController {
 	@ApiOperation("查询最新启用的协议模板")
 	@GetMapping(value = "/queryLatestContractTemplate")
 	@PreAuthorize("@pcs.hasPermissions('contractTemplate/queryLatestContractTemplate')")
-	public HttpResponseResult<ContractTemplate> queryLatestContractTemplate(@ApiParam(value = "业务类型 REGISTER 注册 COURSES 课程购买 PRODUCT 产品 WITHDRAW 提现", required = true) @RequestParam("contractType") ContractTypeEnum contractType) {
+	public HttpResponseResult<ContractTemplate> queryLatestContractTemplate(@ApiParam(value = "业务类型 REGISTER 注册 COURSES 课程购买 PRODUCT 产品 WITHDRAW 提现", required = true) @RequestParam("contractType") ContractTemplateTypeEnum contractType) {
 		return succeed(contractTemplateService.queryLatestContractTemplate(contractType));
 	}
 
@@ -60,13 +61,13 @@ public class ContractTemplateController extends BaseController {
 	@PostMapping(value = "/add", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
 	@PreAuthorize("@pcs.hasPermissions('contractTemplate/add')")
 	public HttpResponseResult<Object> add(@RequestBody ContractTemplate contractTemplate) {
-		contractTemplate.setType(ContractTemplateTypeEnum.PLATFORM.getCode());
+		contractTemplate.setSource(ContractTemplateSourceEnum.PLATFORM.getCode());
+
         SysUser sysUser = sysUserFeignService.queryUserInfo();
-        
         if(sysUser == null || sysUser.getId() == null){
         	return failed(HttpStatus.FORBIDDEN, "请登录");
         }
-		
+
 		contractTemplate.setStatus(false);
 		contractTemplate.setModifyBy(sysUser.getId());
 		contractTemplateService.createContractTemplate(contractTemplate);

+ 6 - 9
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ContractTemplateDao.java

@@ -11,13 +11,10 @@ import com.yonge.toolset.mybatis.dal.BaseDAO;
 
 public interface ContractTemplateDao extends BaseDAO<Integer, ContractTemplate> {
 
-	List<ContractTemplateDto> queryPageList(Map<String, Object> params);
-	
-	ContractTemplate queryLatestContractTemplate( @Param("type") String type);
-	
-	int disableContract(@Param("owner") String owner, @Param("type") String type);
-	
-	Integer queryMaxVersion();
-
-	
+    List<ContractTemplateDto> queryPageList(Map<String, Object> params);
+
+    ContractTemplate queryLatestContractTemplate(@Param("contractSource") String contractSource, @Param("type") String type);
+
+    int disableContract(@Param("type") String type);
+
 }

+ 8 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/SysUserContractRecordDao.java

@@ -4,12 +4,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.biz.dal.dto.search.SysUserContractRecordSearch;
 import com.yonge.cooleshow.biz.dal.entity.SysUserContractRecord;
-import com.yonge.cooleshow.biz.dal.enums.ContractTypeEnum;
 import com.yonge.cooleshow.biz.dal.vo.SysUserContractRecordVo;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * 用户协议记录表-一个用户一种协议一个版本一条记录(SysUserContractRecord)表数据库访问层
@@ -20,13 +18,16 @@ import java.util.Map;
 public interface SysUserContractRecordDao extends BaseMapper<SysUserContractRecord> {
     /**
      * 查询详情
+     *
      * @author liweifan
      * @date 2022-06-16 13:47:21
      * @return: com.yonge.cooleshow.biz.dal.vo.SysUserContractRecordVo
      */
     SysUserContractRecordVo detail(@Param("id") Long id);
+
     /**
      * 分页查询
+     *
      * @author liweifan
      * @date 2022-06-16 13:47:21
      * @return: com.yonge.cooleshow.biz.dal.vo.SysUserContractRecordVo
@@ -35,11 +36,15 @@ public interface SysUserContractRecordDao extends BaseMapper<SysUserContractReco
 
     int insertBatch(@Param("entities") List<SysUserContractRecord> entities);
 
-    Boolean checkContractSign(@Param("userId") Long userId, @Param("contractType") String contractType);
+    Boolean checkContractSign(@Param("userId") Long userId, @Param("userType") String userType, @Param("contractSource") String contractSource, @Param("contractType") String contractType);
+
+    SysUserContractRecord queryLatestContract(@Param("userId") Long userId, @Param("userType") String userType, @Param("contractSource") String contractSource, @Param("contractType") String contractType);
 
     void contractCallbackUpdate(@Param("status") String status,
                                 @Param("serialNo") String serialNo,
                                 @Param("url") String url,
                                 @Param("errMsg") String errMsg);
+
+
 }
 

+ 14 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/SysUserTsignDao.java

@@ -0,0 +1,14 @@
+package com.yonge.cooleshow.biz.dal.dao;
+
+import com.yonge.cooleshow.biz.dal.entity.SysUserTsign;
+import com.yonge.toolset.mybatis.dal.BaseDAO;
+
+public interface SysUserTsignDao extends BaseDAO<Long, SysUserTsign> {
+
+	/**
+	 * 根据证件号码查询
+	 * @param cardNo
+	 * @return
+	 */
+	SysUserTsign queryByCardNo(String cardNo);
+}

+ 17 - 5
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ContractTemplate.java

@@ -10,13 +10,16 @@ public class ContractTemplate {
 
 	@ApiModelProperty(value = "",required = false)
 	private Integer id;
-	
-	@ApiModelProperty(value = "协议名称",required = false)
-	private String name;
-	
+
+	@ApiModelProperty(value = "协议来源 PLATFORM 平台 LINGXINPAY 灵薪付",required = false)
+	private String source;
+
 	@ApiModelProperty(value = "协议类型",required = false)
 	private String type ;
 	
+	@ApiModelProperty(value = "协议名称",required = false)
+	private String name;
+
 	@ApiModelProperty(value = "协议内容",required = false)
 	private String contractTemplateContent;
 	
@@ -151,7 +154,16 @@ public class ContractTemplate {
 	public String getOwner(){
 		return this.owner;
 	}
-			
+
+	public String getSource() {
+		return source;
+	}
+
+	public ContractTemplate setSource(String source) {
+		this.source = source;
+		return this;
+	}
+
 	@Override
 	public String toString() {
 		return ToStringBuilder.reflectionToString(this);

+ 94 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/SysUserTsign.java

@@ -0,0 +1,94 @@
+package com.yonge.cooleshow.biz.dal.entity;
+
+import com.yonge.cooleshow.common.entity.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import java.util.Date;
+
+/**
+ * 对应数据库表(sys_user_tsign):
+ */
+public class SysUserTsign extends BaseEntity {
+
+	/**  */
+	private Long userId;
+
+	/** e签宝账户ID */
+	private String accountId;
+
+	/** 电子印章数据 */
+	private String sealData;
+
+	private String name;
+
+	private String cardNo;
+
+	/**  */
+	private Date createTime = new Date();
+
+	public SysUserTsign() {
+		// TODO Auto-generated constructor stub
+	}
+
+    public SysUserTsign(Long userId, String accountId, String sealData, String name, String cardNo) {
+        this.userId = userId;
+        this.accountId = accountId;
+        this.sealData = sealData;
+        this.name = name;
+        this.cardNo = cardNo;
+    }
+
+	public void setUserId(Long userId) {
+		this.userId = userId;
+	}
+
+	public Long getUserId() {
+		return this.userId;
+	}
+
+	public void setAccountId(String accountId) {
+		this.accountId = accountId;
+	}
+
+	public String getAccountId() {
+		return this.accountId;
+	}
+
+	public void setSealData(String sealData) {
+		this.sealData = sealData;
+	}
+
+	public String getSealData() {
+		return this.sealData;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getCardNo() {
+		return cardNo;
+	}
+
+	public void setCardNo(String cardNo) {
+		this.cardNo = cardNo;
+	}
+
+	public void setCreateTime(Date createTime) {
+		this.createTime = createTime;
+	}
+
+	public Date getCreateTime() {
+		return this.createTime;
+	}
+
+    @Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+
+}

+ 0 - 35
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/ContractTypeEnum.java

@@ -1,35 +0,0 @@
-package com.yonge.cooleshow.biz.dal.enums;
-
-import com.baomidou.mybatisplus.annotation.EnumValue;
-import com.yonge.toolset.base.enums.BaseEnum;
-
-/**
- * 协议模板类型枚举
- */
-public enum ContractTypeEnum implements BaseEnum<String, ContractTypeEnum> {
-
-    REGISTER("注册"),
-    COURSES("课程购买"),
-    PRODUCT("产品"),
-    WITHDRAW("用户提现")
-    ;
-
-    @EnumValue
-    private String code;
-
-    private String desc;
-
-    ContractTypeEnum(String desc) {
-        this.code = this.name();
-        this.desc = desc;
-    }
-
-    @Override
-    public String getCode() {
-        return code;
-    }
-
-    public String getDesc() {
-        return desc;
-    }
-}

+ 10 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/ContractTemplateQueryInfo.java

@@ -4,8 +4,18 @@ import com.yonge.toolset.base.page.QueryInfo;
 
 public class ContractTemplateQueryInfo extends QueryInfo {
 
+	private String source;
+
     private Boolean status;
 
+	public String getSource() {
+		return source;
+	}
+
+	public void setSource(String source) {
+		this.source = source;
+	}
+
 	public Boolean getStatus() {
 		return status;
 	}

+ 17 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ContractService.java

@@ -0,0 +1,17 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
+import com.yonge.cooleshow.common.enums.SysUserType;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+public interface ContractService {
+
+	@Async
+	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
+	HttpResponseResult<String> transferProduceContract(Long userId, SysUserType userType, ContractTemplateTypeEnum contractType, Boolean isShowVisualSeal);
+}

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ContractTemplateService.java

@@ -2,7 +2,7 @@ package com.yonge.cooleshow.biz.dal.service;
 
 import com.yonge.cooleshow.biz.dal.dto.ContractTemplateDto;
 import com.yonge.cooleshow.biz.dal.entity.ContractTemplate;
-import com.yonge.cooleshow.biz.dal.enums.ContractTypeEnum;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
 import com.yonge.toolset.base.page.PageInfo;
 import com.yonge.toolset.base.page.QueryInfo;
 import com.yonge.toolset.mybatis.service.BaseService;
@@ -35,7 +35,7 @@ public interface ContractTemplateService extends BaseService<Integer, ContractTe
 	 * @param contractType
 	 * @return
 	 */
-	ContractTemplate queryLatestContractTemplate(ContractTypeEnum contractType);
+	ContractTemplate queryLatestContractTemplate(ContractTemplateTypeEnum contractType);
 	
 	boolean createContractTemplate(ContractTemplate contractTemplate);
 	

+ 10 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/SysUserContractRecordService.java

@@ -5,9 +5,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dao.SysUserContractRecordDao;
 import com.yonge.cooleshow.biz.dal.dto.search.SysUserContractRecordSearch;
 import com.yonge.cooleshow.biz.dal.entity.SysUserContractRecord;
-import com.yonge.cooleshow.biz.dal.enums.ContractTypeEnum;
 import com.yonge.cooleshow.biz.dal.vo.SysUserContractRecordVo;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
+import com.yonge.cooleshow.common.enums.SysUserType;
 
 /**
  * 用户协议记录表-一个用户一种协议一个版本一条记录(SysUserContractRecord)表服务接口
@@ -36,6 +37,13 @@ public interface SysUserContractRecordService extends IService<SysUserContractRe
      * @param contractType
      * @return
      */
-    HttpResponseResult<Boolean> checkContractSign(Long userId, ContractTypeEnum contractType);
+    Boolean checkContractSign(Long userId, SysUserType userType, ContractTemplateTypeEnum contractType);
+    /**
+     * 获取用户最新版签署中的协议
+     * @param userId
+     * @param contractType
+     * @return
+     */
+    SysUserContractRecord queryLatestContract(Long userId, SysUserType userType, ContractTemplateTypeEnum contractType);
 }
 

+ 14 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/SysUserTsignService.java

@@ -0,0 +1,14 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+import com.yonge.cooleshow.biz.dal.entity.SysUserTsign;
+import com.yonge.toolset.mybatis.service.BaseService;
+
+public interface SysUserTsignService extends BaseService<Long, SysUserTsign> {
+
+	/**
+	 * 根据证件号码查询
+	 * @param cardNo
+	 * @return
+	 */
+	SysUserTsign queryByCardNo(String cardNo);
+}

+ 258 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ContractServiceImpl.java

@@ -0,0 +1,258 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.auth.api.enums.CertificateTypeEnum;
+import com.yonge.cooleshow.biz.dal.entity.ContractTemplate;
+import com.yonge.cooleshow.biz.dal.entity.SysUserTsign;
+import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.vo.StudentVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
+import com.yonge.cooleshow.common.constant.SysConfigConstant;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
+import com.yonge.cooleshow.common.enums.SysUserType;
+import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.thirdparty.eseal.ESealPlugin;
+import com.yonge.toolset.thirdparty.storage.StoragePluginContext;
+import com.yonge.toolset.thirdparty.storage.provider.KS3StoragePlugin;
+import com.yonge.toolset.thirdparty.user.realname.RealnameAuthenticationPluginContext;
+import com.yonge.toolset.thirdparty.user.realname.provider.LinkfaceRealnameAuthenticationPlugin;
+import com.yonge.toolset.utils.date.DateUtil;
+import com.yonge.toolset.utils.freemarker.FreemarkerTemplateEngine;
+import com.yonge.toolset.utils.pdf.PDFUtil;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.*;
+
+@Service
+public class ContractServiceImpl implements ContractService {
+    @Autowired
+    private SysUserService sysUserService;
+    @Autowired
+    private SysUserTsignService sysUserTsignService;
+    @Autowired
+    private ContractTemplateService contractTemplateService;
+    @Autowired
+    private SysUserContractRecordService contractRecordService;
+    @Autowired
+    private StudentService studentService;
+    @Autowired
+    private TeacherService teacherService;
+    @Autowired
+    private SysConfigService sysConfigService;
+    @Autowired
+    private RealnameAuthenticationPluginContext realnameAuthenticationPluginContext;
+    @Autowired
+    private StoragePluginContext storagePluginContext;
+    @Autowired
+    private ESealPlugin eSealPlugin;
+
+    @Value("${contract.baseDir:/var/pdf}")
+    private String contractBaseDir;
+
+    @Value("${message.debugMode}")
+    private boolean debugMode;
+
+    private DateFormat dateFormatOss = new SimpleDateFormat("yyyy/MM/dd");
+
+    private DateFormat dateFormat1 = new SimpleDateFormat("yyMMddHHmmSS");
+
+    private final Logger logger = LoggerFactory.getLogger(ContractService.class);
+
+    @Override
+    @Async
+    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
+    public HttpResponseResult<String> transferProduceContract(Long userId, SysUserType userType, ContractTemplateTypeEnum contractType, Boolean isShowVisualSeal) {
+        SysUser user = sysUserService.findUserById(userId);
+        if (user == null) {
+            logger.error("用户不存在({})", userId);
+            return HttpResponseResult.failed("用户不存在");
+        }
+
+        if (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCardNo())) {
+            logger.error("身份信息缺失({})", userId);
+            return HttpResponseResult.failed("身份信息缺失");
+        }
+
+        SysUserTsign sysUserTsign = sysUserTsignService.get(userId);
+        if (sysUserTsign == null) {
+            try {
+                sysUserTsign = register(userId, user.getRealName(), user.getIdCardNo(), user.getPhone());
+            } catch (Exception e) {
+                logger.error("用户电子签章注册失败", e);
+                return HttpResponseResult.failed("用户电子签章注册失败");
+            }
+        }
+        Date date = new Date();
+
+        // 合成freemarker
+        String srcPdfPath = contractBaseDir + "/product/" + dateFormat1.format(date) + "/" + userId + "_" + LocalDateTime.now().getSecond() + ".pdf";
+
+        File srcFile = new File(srcPdfPath);
+
+        File debtFile = new File(srcFile.getParent());
+        if (!debtFile.exists()) {
+            debtFile.mkdirs();
+        }
+
+        FreemarkerTemplateEngine templateEngine = FreemarkerTemplateEngine.getInstance();
+        templateEngine.setClassForTemplateLoading(ContractServiceImpl.class, "/config/contracts/");
+
+        Boolean signflag = contractRecordService.checkContractSign(userId,userType, contractType);
+        if (signflag) {
+            return HttpResponseResult.failed("用户已经签署协议");
+        }
+
+        // 查询最新协议模板
+        ContractTemplate tenantContractTemplate = contractTemplateService.queryLatestContractTemplate(contractType);
+        if(tenantContractTemplate == null){
+            logger.error("最新协议模板查询失败");
+            return HttpResponseResult.failed("最新协议模板查询失败");
+        }
+        String mainContent = tenantContractTemplate.getContractTemplateContent();
+
+        Map<String, Object> params = new HashMap<>();
+        String companyName = sysConfigService.findConfigValue(SysConfigConstant.COMPANY_NAME);
+        params.put("companyName",companyName);
+        params.put("companySealPicture",sysConfigService.findConfigValue(SysConfigConstant.COMPANY_SEAL_PICTURE));
+        params.put("contractMainContent",mainContent);
+        params.put("isShowVisualSeal", isShowVisualSeal);
+
+
+        Map<String,Object> userInfo = new HashMap<>();
+        userInfo.put("realName",user.getRealName());
+        userInfo.put("phone",user.getPhone());
+        userInfo.put("idCardNo",user.getIdCardNo());
+
+        if(SysUserType.STUDENT.equals(userType)){
+            StudentVo detail = studentService.detail(userId);
+            userInfo.put("subjectName",detail.getSubjectName());
+        }else if(SysUserType.TEACHER.equals(userType)){
+            TeacherVo detail = teacherService.detail(userId);
+            userInfo.put("subjectName",detail.getSubjectName());
+        }
+        params.put("userInfo", userInfo);
+
+        templateEngine.render(params, "latest_contract_template.ftl", srcFile);
+
+        // 生成借款协议PDF
+        try {
+            PDFUtil.renderToPDFByData(ContractServiceImpl.class.getResource("/").getFile(), FileUtils.readFileToString(srcFile), srcPdfPath, "simsun.ttc");
+        } catch (IOException e) {
+            logger.error("生成产品协议失败", e);
+            return HttpResponseResult.failed("生成产品协议失败");
+        }
+
+        String organCode = sysConfigService.findConfigValue(SysConfigConstant.COMPANY_ORGAN_CODE);
+        SysUserTsign organTsign = sysUserTsignService.queryByCardNo(organCode);
+        if (organTsign == null) {
+            //创建企业签章
+            addTsign(0L, organCode, companyName);
+        }
+
+        eSealPlugin.organSign(organTsign.getSealData(), srcPdfPath, srcPdfPath);
+        if (sysUserTsign != null && CertificateTypeEnum.IDENTITY.getCode().equals(user.getCertificateType())) {
+            eSealPlugin.userSign(sysUserTsign.getAccountId(), sysUserTsign.getSealData(), srcPdfPath, srcPdfPath);
+        }
+
+        // 上传到oss
+        String dateStrOss = dateFormatOss.format(date);
+        dateStrOss = "product/" + dateStrOss + "/" + DateUtil.getHour(date);
+        String pdfFilePath = storagePluginContext.uploadFile(KS3StoragePlugin.PLUGIN_NAME, dateStrOss, srcFile);
+        FileUtils.deleteQuietly(srcFile);
+        return HttpResponseResult.succeed(pdfFilePath);
+    }
+
+
+
+    public SysUserTsign register(Long userId, String realName, String idCardNo, String mobileNo) {
+
+        if (StringUtils.isBlank(realName) || StringUtils.isBlank(idCardNo) || StringUtils.isBlank(mobileNo)) {
+            return null;
+        }
+
+        SysUserTsign sysUserTsign = sysUserTsignService.get(userId);
+        if (sysUserTsign == null) {
+
+            String accountId = "";
+            String sealData = "";
+
+            SysUser user = sysUserService.findUserById(userId);
+            if (user == null) {
+                throw new BizException("用户信息查询失败");
+            }
+
+            if (CertificateTypeEnum.IDENTITY.getCode().equals(user.getCertificateType())) {
+                if (!debugMode) {
+                    realnameAuthenticationPluginContext.getRealnameAuthenticationPlugin(LinkfaceRealnameAuthenticationPlugin.getName()).verify(realName, idCardNo);
+                }
+
+                accountId = eSealPlugin.createUserAccount(realName, idCardNo, mobileNo);
+
+                if (StringUtils.isBlank(accountId)) {
+                    throw new BizException("创建电子存证账户失败");
+                }
+
+                sealData = eSealPlugin.createUserSeal(accountId);
+
+                if (StringUtils.isBlank(sealData)) {
+                    throw new BizException("创建电子存证印章失败");
+                }
+            }
+            sysUserTsign = new SysUserTsign(userId, accountId, sealData, realName, idCardNo);
+
+            sysUserTsignService.insert(sysUserTsign);
+            return sysUserTsign;
+        }
+        return null;
+    }
+
+    public void addTsign(Long userId, String organCode, String orgName) {
+        Optional.ofNullable(organCode).orElseThrow(() -> new BizException("营业执照编号不能为空!"));
+        Optional.ofNullable(orgName).orElseThrow(() -> new BizException("营业名称不能为空"));
+
+        SysUserTsign sysUserTsign = null;
+
+        SysUserTsign orignSysUserTsign = sysUserTsignService.queryByCardNo(organCode);
+
+        if (orignSysUserTsign == null) {
+
+            String accountId = eSealPlugin.createOrganAccount(orgName, organCode);
+            if (StringUtils.isBlank(accountId)) {
+                throw new BizException("创建企业电子存证账户失败");
+            }
+
+            String sealData = eSealPlugin.createOrganSeal(accountId, "", "");
+            if (StringUtils.isBlank(sealData)) {
+                throw new BizException("创建电子存证印章失败");
+            }
+
+            sysUserTsign = new SysUserTsign(-userId, accountId, sealData, orgName, organCode);
+            sysUserTsignService.insert(sysUserTsign);
+
+        } else if (!StringUtils.equals(orignSysUserTsign.getName(), orgName)) {
+            if (eSealPlugin.updateOrganAccount(orignSysUserTsign.getAccountId(), orgName, organCode)) {
+                orignSysUserTsign.setName(orgName);
+                sysUserTsignService.update(orignSysUserTsign);
+            }
+        }
+
+    }
+
+}

+ 36 - 47
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ContractTemplateServiceImpl.java

@@ -7,7 +7,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
-import com.yonge.cooleshow.biz.dal.enums.ContractTypeEnum;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
 import com.yonge.toolset.mybatis.service.impl.BaseServiceImpl;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
@@ -55,7 +55,7 @@ public class ContractTemplateServiceImpl extends BaseServiceImpl<Integer, Contra
             dataList = contractTemplateDao.queryPageList(params);
         }
         if (count == 0) {
-            dataList = new ArrayList<ContractTemplateDto>();
+            dataList = new ArrayList<>();
         }
         pageInfo.setRows(dataList);
         return pageInfo;
@@ -64,34 +64,25 @@ public class ContractTemplateServiceImpl extends BaseServiceImpl<Integer, Contra
     @Override
     @Transactional
     public boolean enableContract(Integer id, Long userId) {
-        ContractTemplate contractTemplate = contractTemplateDao.get(id);
-
-        if (contractTemplate == null) {
-            throw new BizException("未查询到协议模板");
-        }
-
-        if (contractTemplate.getStatus()) {
-            return true;
-        }
-
         RLock lock = redissonClient.getLock(LOCK_NAME);
-
         try {
             if (lock.tryLock(10, 10, TimeUnit.SECONDS)) {
+                ContractTemplate contractTemplate = contractTemplateDao.get(id);
 
-                Integer maxVersion = contractTemplateDao.queryMaxVersion();
-                int version = maxVersion == null ? 1 : maxVersion + 1;
+                if (contractTemplate == null) {
+                    throw new BizException("未查询到协议模板");
+                }
 
-                contractTemplate.setVersion(version);
-
-                contractTemplateDao.disableContract(contractTemplate.getOwner(), contractTemplate.getType());
-
-                Date date = new Date();
+                if (contractTemplate.getStatus()) {
+                    return true;
+                }
+                contractTemplate.setVersion(contractTemplate.getVersion() == null ? 1 : contractTemplate.getVersion() + 1);
+                //关闭类型下的所有协议,只启用当前这个协议
+                contractTemplateDao.disableContract(contractTemplate.getType());
 
                 contractTemplate.setStatus(true);
-                contractTemplate.setUpdateTime(date);
+                contractTemplate.setUpdateTime(new Date());
                 contractTemplate.setModifyBy(userId);
-
                 contractTemplateDao.update(contractTemplate);
                 return true;
             }
@@ -100,7 +91,6 @@ public class ContractTemplateServiceImpl extends BaseServiceImpl<Integer, Contra
         } finally {
             lock.unlock();
         }
-
         return false;
     }
 
@@ -111,29 +101,29 @@ public class ContractTemplateServiceImpl extends BaseServiceImpl<Integer, Contra
     }
 
     @Override
-    public ContractTemplate queryLatestContractTemplate(ContractTypeEnum contractType) {
-        ContractTemplate ContractTemplate = contractTemplateDao.queryLatestContractTemplate(contractType.getCode());
+    public ContractTemplate queryLatestContractTemplate(ContractTemplateTypeEnum contractType) {
+        String code = contractType.getSource().getCode();
+        ContractTemplate ContractTemplate = contractTemplateDao.queryLatestContractTemplate(
+                code , contractType.getCode());
         return ContractTemplate;
     }
 
     @Override
     @Transactional
-    public boolean createContractTemplate(ContractTemplate ContractTemplate) {
-
+    public boolean createContractTemplate(ContractTemplate contractTemplate) {
         RLock lock = redissonClient.getLock(LOCK_NAME);
-
         try {
             if (lock.tryLock(10, 10, TimeUnit.SECONDS)) {
-
-                Integer maxVersion = contractTemplateDao.queryMaxVersion();
-                int version = maxVersion == null ? 1 : maxVersion + 1;
-
-                ContractTemplate.setVersion(version);
+                ContractTemplate latestContractTemplate = contractTemplateDao.queryLatestContractTemplate(contractTemplate.getSource(), contractTemplate.getType());
+                if(null == latestContractTemplate || null == latestContractTemplate.getVersion()){
+                    contractTemplate.setVersion(1);
+                }else{
+                    contractTemplate.setVersion(latestContractTemplate.getVersion() + 1);
+                }
                 Date date = new Date();
-                ContractTemplate.setCreateTime(date);
-                ContractTemplate.setUpdateTime(date);
-                insert(ContractTemplate);
-
+                contractTemplate.setCreateTime(date);
+                contractTemplate.setUpdateTime(date);
+                insert(contractTemplate);
                 return true;
             }
         } catch (InterruptedException e) {
@@ -147,20 +137,20 @@ public class ContractTemplateServiceImpl extends BaseServiceImpl<Integer, Contra
 
     @Override
     @Transactional
-    public boolean updateContractTempalte(ContractTemplate ContractTemplate) {
-
+    public boolean updateContractTempalte(ContractTemplate contractTemplate) {
         RLock lock = redissonClient.getLock(LOCK_NAME);
 
         try {
             if (lock.tryLock(10, 10, TimeUnit.SECONDS)) {
-                Integer maxVersion = contractTemplateDao.queryMaxVersion();
-                int version = maxVersion == null ? 1 : maxVersion + 1;
-
-                ContractTemplate.setVersion(version);
+                ContractTemplate latestContractTemplate = contractTemplateDao.queryLatestContractTemplate(contractTemplate.getSource(), contractTemplate.getType());
+                if(null == latestContractTemplate || null == latestContractTemplate.getVersion()){
+                    contractTemplate.setVersion(1);
+                }else{
+                    contractTemplate.setVersion(latestContractTemplate.getVersion() + 1);
+                }
                 Date date = new Date();
-                ContractTemplate.setUpdateTime(date);
-
-                update(ContractTemplate);
+                contractTemplate.setUpdateTime(date);
+                update(contractTemplate);
                 return true;
             }
         } catch (InterruptedException e) {
@@ -168,7 +158,6 @@ public class ContractTemplateServiceImpl extends BaseServiceImpl<Integer, Contra
         } finally {
             lock.unlock();
         }
-
         return false;
     }
 

+ 8 - 12
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserContractRecordServiceImpl.java

@@ -5,11 +5,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.biz.dal.dao.SysUserContractRecordDao;
 import com.yonge.cooleshow.biz.dal.dto.search.SysUserContractRecordSearch;
 import com.yonge.cooleshow.biz.dal.entity.SysUserContractRecord;
-import com.yonge.cooleshow.biz.dal.enums.ContractTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.ContractTemplateService;
 import com.yonge.cooleshow.biz.dal.service.SysUserContractRecordService;
 import com.yonge.cooleshow.biz.dal.vo.SysUserContractRecordVo;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
+import com.yonge.cooleshow.common.enums.SysUserType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -41,23 +42,18 @@ public class SysUserContractRecordServiceImpl extends ServiceImpl<SysUserContrac
     }
 
     @Override
-    public IPage<SysUserContractRecordVo> selectPage(IPage<SysUserContractRecordVo> page, SysUserContractRecordSearch query){
+    public IPage<SysUserContractRecordVo> selectPage(IPage<SysUserContractRecordVo> page, SysUserContractRecordSearch query) {
         return page.setRecords(baseMapper.selectPage(page, query));
     }
 
     @Override
-    public HttpResponseResult<Boolean> checkContractSign(Long userId, ContractTypeEnum contractType) {
-        return HttpResponseResult.succeed(getDao().checkContractSign(userId, contractType.getCode()));
+    public Boolean checkContractSign(Long userId, SysUserType userType, ContractTemplateTypeEnum contractType) {
+        return getDao().checkContractSign(userId, userType.getCode(), contractType.getSource().getCode(), contractType.getCode());
     }
 
-    /**
-     * 校验当前用户签署的协议是否是最新版本
-     */
-    public void checkContractRecord(Long userId, String type) {
-        //根据人员id及协议类型查询最新协议记录
-        //查询对应类型的最新的协议
-        //对比当前类型及人员id的协议版本
-        //如果不是最新版本,则返回false
+    @Override
+    public SysUserContractRecord queryLatestContract(Long userId, SysUserType userType, ContractTemplateTypeEnum contractType) {
+        return getDao().queryLatestContract(userId, userType.getCode(), contractType.getSource().getCode(), contractType.getCode());
     }
 
 }

+ 27 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserTsignServiceImpl.java

@@ -0,0 +1,27 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.yonge.cooleshow.biz.dal.dao.SysUserTsignDao;
+import com.yonge.cooleshow.biz.dal.entity.SysUserTsign;
+import com.yonge.cooleshow.biz.dal.service.SysUserTsignService;
+import com.yonge.toolset.mybatis.dal.BaseDAO;
+import com.yonge.toolset.mybatis.service.impl.BaseServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SysUserTsignServiceImpl extends BaseServiceImpl<Long, SysUserTsign> implements SysUserTsignService {
+	
+	@Autowired
+	private SysUserTsignDao sysUserTsignDao;
+
+	@Override
+	public BaseDAO<Long, SysUserTsign> getDAO() {
+		return sysUserTsignDao;
+	}
+
+	@Override
+	public SysUserTsign queryByCardNo(String cardNo) {
+		return sysUserTsignDao.queryByCardNo(cardNo);
+	}
+	
+}

+ 132 - 0
cooleshow-user/user-biz/src/main/resources/config/contracts/latest_contract_template.ftl

@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <meta http-equiv="Cache-Control" content="no-cache" />
+    <meta http-equiv="Expires" content="0" />
+    <title>产品与服务协议</title>
+    <style>
+        body { margin: 0; }
+        header {
+            height: 40px;
+            line-height: .40px;
+            color: #000;
+            font-size: 17px;
+            background: #fff;
+            box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.07);
+            text-align: center;
+        }
+        header .back {
+            width: 20px;
+            height: 20px;
+            position: absolute;
+            left: 12px;
+            top: 10px;
+        }
+        .container {
+            padding: 22px 20px 3px;
+            font-size: 14px;
+        }
+        h1 {
+            font-size: 18px;
+            text-align: center;
+            margin-bottom: 8px;
+        }
+        h2 {
+            font-size: 16px;
+            font-weight: bold;
+            padding-top: 15px;
+        }
+        h3 {
+            font-size: 14px;
+            font-weight: bold;
+        }
+        .signature {
+            padding-top: 50px;
+        }
+        .signature .sign {
+            position: relative;
+            width: 49%;
+            display: inline-block;
+        }
+        .signature span {
+            display: block;
+        }
+        .signature .cachet {
+            position: absolute;
+            top: -60px;
+            left: 0;
+            width: 150px;
+            height: 150px;
+        }
+        .iInfo {
+            display: flex;
+        }
+        .iInfo span {
+            flex: 1;
+        }
+        .iInfoContent, .iInfoContent span {
+            display: block;
+        }
+
+        .underline {
+            text-decoration: underline;
+        }
+        .bold {
+            font-weight: bold;
+        }
+    </style>
+</head>
+<body style="font-family:'SimSun'">
+    <div class="container">
+        <h1>《产品与服务协议》</h1>
+                            甲方:${companyName} <br/>
+
+        <div style="display: flex;">乙方:
+            <div style="flex: 1 auto;">
+                <div class="iInfo">
+                    <span>用户姓名:${userInfo.realName!}</span>
+                    <span>电话:${userInfo.phone!}</span>
+                </div>
+                <#if userInfo.idCardNo?default("")?trim?length gt 1>
+                    <div class="iInfo">
+                        <span>身份证号:${userInfo.idCardNo!}</span>
+                    </div>
+                </#if>
+                <#if userInfo.subjectName?default("")?trim?length gt 1>
+                <div class="iInfo">
+                    <span>所在声部:${userInfo.subjectName!}</span>
+                </div>
+                </#if>
+            </div>
+        </div>
+        <div>(本协议中“乙方“指学员及家长;”乙方学员“指购买甲方产品或服务的学员;”乙方家长“仅指乙方学员的法定监护人。)</div>
+
+        <p class="underline bold">重要须知:在注册或购买使用甲方提供的产品、服务之前,请您务必审慎阅读、充分理解本使用协议各条款内容, 特别是免除或者限制甲方责任的条款、对您权利进行限制的条款、约定争议解决方式和司法管辖的条款等。 限制、免责条款或者其他涉及您重大权益的条款可能以加粗、加下划线等形式提示您重点注意。您注册或购买使用甲方提供的产品和服务,均视为您同意本使用协议,以及同意接受本使用协议的约束。</p>
+        <p class="underline bold">如无特别说明 ,下列术语在本协议中的定义为:管乐迷平台(下称“本平台”),即管乐迷APP;(下称“本平台”)指由甲方提供的器乐教学全流程辅助系统,包括媒体资料,教师点评,课前、课中、课后管理等服务;乐器练习云教练 (下称“本系统”),指由甲方提供和维护的器乐辅助练习系统;具体以该系统实际提供为准。该系统将根据实际需要进行调整和增减,乙方使用平台时需遵守本服务协议。</p>
+
+		${contractMainContent!}
+        
+        <div class="signature">
+        	<#if isShowVisualSeal>
+                <div class="sign">甲方签章:${companyName}<img class="cachet" src="${companySealPicture!}" alt="" />
+                    <span>日期:${.now?string("yyyy年MM月dd日")}</span>
+                </div>
+                <div class="sign">乙方签章:${userInfo.realName!}
+                    <span>日期:${.now?string("yyyy年MM月dd日")} </span>
+                </div>
+                <#else>
+                <div class="sign">甲方签章:${companyName}
+                    <span>日期:${.now?string("yyyy年MM月dd日")}</span>
+                </div>
+                <div class="sign">乙方签章:
+                    <span>日期:${.now?string("yyyy年MM月dd日")} </span>
+                </div>
+        	</#if>
+        </div>
+    </div>
+</body>
+</html>

+ 28 - 25
cooleshow-user/user-biz/src/main/resources/config/mybatis/ContractTemplateMapper.xml

@@ -6,8 +6,9 @@
 	<resultMap type="com.yonge.cooleshow.biz.dal.entity.ContractTemplate"
 		id="BaseResultMap">
 		<result column="id_" property="id" />
-		<result column="name_" property="name" />
+		<result column="source_" property="source" />
 		<result column="type_" property="type" />
+		<result column="name_" property="name" />
 		<result column="contract_template_content_" property="contractTemplateContent" />
 		<result column="origanal_file_url_" property="origanalFileUrl" />
 		<result column="contract_no_" property="contractNo" />
@@ -18,7 +19,7 @@
 		<result column="create_time_" property="createTime" />
 		<result column="owner_" property="owner" />
 	</resultMap>
-	
+
 	<resultMap type="com.yonge.cooleshow.biz.dal.dto.ContractTemplateDto"
 		id="ContractTemplateDto">
 		<result column="latest_operator_" property="latestOperator" />
@@ -39,8 +40,8 @@
 		useGeneratedKeys="true" keyColumn="id" keyProperty="id">
 		INSERT INTO
 		contract_template
-		(id_,name_,type_,contract_template_content_,origanal_file_url_,contract_no_,status_,version_,modify_by_,update_time_,create_time_,owner_)
-		VALUES(#{id},#{name},#{type},#{contractTemplateContent},#{origanalFileUrl},#{contractNo},#{status},#{version},#{modifyBy},#{updateTime},#{createTime},#{owner})
+		(id_,source_,name_,type_,contract_template_content_,origanal_file_url_,contract_no_,status_,version_,modify_by_,update_time_,create_time_,owner_)
+		VALUES(#{id},#{source},#{name},#{type},#{contractTemplateContent},#{origanalFileUrl},#{contractNo},#{status},#{version},#{modifyBy},#{updateTime},#{createTime},#{owner})
 	</insert>
 
 	<!-- 根据主键查询一条记录 -->
@@ -74,6 +75,9 @@
 			<if test="type != null">
 				type_ = #{type},
 			</if>
+			<if test="source != null">
+				source_ = #{source},
+			</if>
 			<if test="contractNo != null">
 				contract_no_ = #{contractNo},
 			</if>
@@ -96,10 +100,12 @@
 	<select id="queryPage" resultMap="BaseResultMap" parameterType="map">
 		SELECT tct.*,ifnull(u.real_name_,u.username_) latest_operator_ FROM contract_template tct left join sys_user u on tct.modify_by_ = u.id_
 		<where>
-			tct.type_ = 'PLATFORM'
 			<if test="status != null">
 				and tct.status_ = #{status}
 			</if>
+			<if test="source != null">
+				and tct.source_ = #{source}
+			</if>
 			<if test="type != null">
 				and tct.type_ = #{type}
 			</if>
@@ -115,10 +121,12 @@
 	<select id="queryPageList" resultMap="ContractTemplateDto" parameterType="map">
 		SELECT tct.*,ifnull(u.real_name_,u.username_) latest_operator_ FROM contract_template tct left join sys_user u on tct.modify_by_ = u.id_
 		<where>
-			tct.type_ = 'PLATFORM'
 			<if test="status != null">
 				and tct.status_ = #{status}
 			</if>
+			<if test="source != null">
+				and tct.source_ = #{source}
+			</if>
 			<if test="type != null">
 				and tct.type_ = #{type}
 			</if>
@@ -135,10 +143,13 @@
 	<select id="queryCount" resultType="int">
 		SELECT COUNT(tct.id_) FROM contract_template tct
 		<where>
-			tct.type_ = 'PLATFORM'
+			tct.source_ = 'PLATFORM'
 			<if test="status != null">
 				and tct.status_ = #{status}
 			</if>
+			<if test="source != null">
+				and tct.source_ = #{source}
+			</if>
 			<if test="type != null">
 				and tct.type_ = #{type}
 			</if>
@@ -148,28 +159,20 @@
 		</where>
 	</select>
 
-	<select id="queryLatestContractTemplate" resultMap="BaseResultMap" parameterType="map">
+	<select id="queryLatestContractTemplate" resultMap="BaseResultMap">
 		SELECT a.* FROM (
 			select
-				type_,MAX(version_) as version_
-			from contract_template where status_ = 1 and type_ = #{type}
-			group by type_
+				source_,type_,MAX(version_) as version_
+			from contract_template where status_ = 1 and source_ = #{contractSource} and type_ = #{type}
+			group by source_ ,type_
 		) t
-		left join contract_template a on t.type_ = a.type_ and t.version_ = a.version_
-		where a.type_ = #{type}
+		left join contract_template a on t.source_ =a.source_ and t.type_ = a.type_ and t.version_ = a.version_
+		where a.source_ = #{contractSource} and a.type_ = #{type}
 	</select>
-	
-	<update id="disableContract" parameterType="map">
-		update contract_template set status_ = 0 where status_ = 1
-		<if test="type != null">
+
+	<update id="disableContract">
+		update contract_template set status_ = 0 where status_ = 1 and source_ = 'PLATFORM'
 			and type_ = #{type}
-		</if>
-		<if test="owner != null">
-			and owner_ = #{owner}
-		</if>
 	</update>
-	
-	<select id="queryMaxVersion" resultType="java.lang.Integer">
-		SELECT max(version_) FROM contract_template 
-	</select>
+
 </mapper>

+ 31 - 8
cooleshow-user/user-biz/src/main/resources/config/mybatis/SysUserContractRecordMapper.xml

@@ -64,19 +64,42 @@
     </insert>
     <update id="contractCallbackUpdate" parameterType="java.util.Map">
         UPDATE sys_user_contract_record
-        set status_ = #{status},err_msg_ = #{errMsg},url_ = #{url}
+        set status_ = #{status}
+          <if test="url != null">
+              ,url_ = #{url}
+          </if>
+          <if test="errMsg != null">
+              ,err_msg_ = #{errMsg}
+          </if>
         WHERE contract_no_ = #{serialNo}
     </update>
 
     <select id="checkContractSign" resultType="java.lang.Boolean">
-        select count(b.id_) from (
+        select count(t.id_) from (
             select
-                type_,MAX(version_) as version_
-            from contract_template where status_ = 1 and type_ = #{contractType} group by type_
-        ) t
-        left join contract_template a on t.type_ = a.type_ and t.version_ = a.version_
-        left join sys_user_contract_record b on a.id_ = b.contract_id_ and b.status_ = SUCCESS
-        where b.user_id_ = #{userId}
+                source_,type_,MAX(version_) as version_
+            from contract_template
+            where status_ = 1 and source_ = #{contractSource} and type_ = #{contractType}
+            group by source_,type_
+        ) a
+        left join contract_template b on a.source_ = b.source_ and a.type_ = b.type_ and a.version_ = b.version_
+        left join sys_user_contract_record t on b.id_ = t.contract_id_ and t.status_ in ('SUCCESS')
+        where t.user_id_ = #{userId} and t.user_type_ = #{userType}
+    </select>
+
+    <select id="queryLatestContract" resultType="com.yonge.cooleshow.biz.dal.entity.SysUserContractRecord">
+        select
+            <include refid="baseColumns"/>
+        from (
+            select
+                source_,type_,MAX(version_) as version_
+            from contract_template
+            where status_ = 1 and source_ = #{contractSource} and type_ = #{contractType}
+            group by source_,type_
+        ) a
+        left join contract_template b on a.source_ = b.source_ and a.type_ = b.type_ and a.version_ = b.version_
+        left join sys_user_contract_record t on b.id_ = t.contract_id_ and t.status_ in ('SUCCESS','DONG ')
+        where t.user_id_ = #{userId} and t.user_type_ = #{userType}
     </select>
 
 </mapper>

+ 71 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/SysUserTsignMapper.xml

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.yonge.cooleshow.biz.dal.dao.SysUserTsignDao">
+	
+	<resultMap type="com.yonge.cooleshow.biz.dal.entity.SysUserTsign" id="SysUserTsign">
+		<result column="user_id_" property="userId" />
+		<result column="account_id_" property="accountId" />
+		<result column="seal_data_" property="sealData" />
+		<result column="name_" property="name" />
+		<result column="card_no_" property="cardNo" />
+		<result column="create_time_" property="createTime" />
+	</resultMap>
+	
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="SysUserTsign" >
+		SELECT * FROM sys_user_tsign WHERE user_id_ = #{userId} 
+	</select>
+	
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="SysUserTsign">
+		SELECT * FROM sys_user_tsign  ORDER BY user_id_
+	</select>
+	
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.yonge.cooleshow.biz.dal.entity.SysUserTsign" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		INSERT INTO sys_user_tsign (user_id_,account_id_,seal_data_,name_,card_no_,create_time_) VALUES(#{userId},#{accountId},#{sealData},#{name},#{cardNo},now())
+	</insert>
+	
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.yonge.cooleshow.biz.dal.entity.SysUserTsign">
+		UPDATE sys_user_tsign <set>
+		<if test="userId != null">
+		user_id_ = #{userId},
+		</if>
+		<if test="accountId != null">
+		account_id_ = #{accountId},
+		</if>
+		<if test="sealData != null">
+		seal_data_ = #{sealData},
+		</if>
+		<if test="name != null">
+		name_ = #{name},
+		</if>
+		<if test="cardNo != null">
+		card_no_ = #{cardNo},
+		</if>
+		<if test="createTime != null">
+		create_time_ = #{createTime},
+		</if>
+		</set> WHERE user_id_ = #{userId}
+	</update>
+	
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete" >
+		DELETE FROM sys_user_tsign WHERE user_id_ = #{userId} 
+	</delete>
+	
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="SysUserTsign" parameterType="map">
+		SELECT * FROM sys_user_tsign ORDER BY user_id_ <include refid="global.limit"/>
+	</select>
+	
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM sys_user_tsign
+	</select>
+	
+	<select id="queryByCardNo" resultMap="SysUserTsign">
+		SELECT * FROM sys_user_tsign where card_no_ = #{cardNo}
+	</select>
+</mapper>

+ 26 - 20
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/SysUserContractRecordController.java

@@ -1,12 +1,13 @@
 package com.yonge.cooleshow.teacher.controller;
 
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.service.ContractService;
+import com.yonge.cooleshow.common.enums.ContractTemplateSourceEnum;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
 import com.yonge.cooleshow.common.enums.SysUserType;
 import com.yonge.cooleshow.biz.dal.entity.ContractTemplate;
 import com.yonge.cooleshow.biz.dal.entity.SysUserContractRecord;
-import com.yonge.cooleshow.biz.dal.enums.ContractTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.DealStatusEnum;
 import com.yonge.cooleshow.biz.dal.sdk.WithdrawSdk;
 import com.yonge.cooleshow.biz.dal.service.ContractTemplateService;
@@ -41,61 +42,66 @@ public class SysUserContractRecordController extends BaseController {
     @Resource
     private SysUserContractRecordService sysUserContractRecordService;
     @Autowired
+    private ContractService contractService;
+    @Autowired
     private WithdrawSdk withdrawSdk;
     @Autowired
     private IdGeneratorService idGeneratorService;
 
     @ApiOperation("判断用户是否签署协议")
     @GetMapping(value = "/checkContractSign", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
-    public HttpResponseResult<Boolean> checkContractSign(@ApiParam(value = "业务类型 REGISTER 注册 COURSES 课程购买 PRODUCT 产品 WITHDRAW 提现", required = true) @RequestParam("contractType") ContractTypeEnum contractType) {
+    public HttpResponseResult<Boolean> checkContractSign(@ApiParam(value = "业务类型 REGISTER 注册 COURSES 课程购买 PRODUCT 产品 WITHDRAW 提现", required = true) @RequestParam("contractType") ContractTemplateTypeEnum contractType) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {
             return failed(HttpStatus.FORBIDDEN, "请登录");
         }
-        return sysUserContractRecordService.checkContractSign(user.getId(), contractType);
+        return HttpResponseResult.succeed(sysUserContractRecordService.checkContractSign(user.getId(), SysUserType.TEACHER, contractType));
     }
 
     @ApiOperation("查询最新启用的协议模板")
     @GetMapping(value = "/queryLatestContractTemplate")
-    public HttpResponseResult<ContractTemplate> queryLatestContractTemplate(@ApiParam(value = "业务类型 REGISTER 注册 COURSES 课程购买 PRODUCT 产品 WITHDRAW 提现", required = true) @RequestParam("contractType") ContractTypeEnum contractType) {
+    public HttpResponseResult<ContractTemplate> queryLatestContractTemplate(@ApiParam(value = "业务类型 REGISTER 注册 COURSES 课程购买 PRODUCT 产品 WITHDRAW 提现", required = true) @RequestParam("contractType") ContractTemplateTypeEnum contractType) {
         return succeed(contractTemplateService.queryLatestContractTemplate(contractType));
     }
 
     @ApiOperation("签署协议")
     @GetMapping(value = "/sign", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
     public HttpResponseResult<Boolean> sign(
-            @ApiParam(value = "模板id", required = true) @RequestParam("templateId") Integer templateId) {
+            @ApiParam(value = "协议类型", required = true) @RequestParam("contractType") ContractTemplateTypeEnum contractType) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {
             return failed(HttpStatus.FORBIDDEN, "请登录");
         }
         //是否签署标识,签署了才入库
         boolean flag = false;
-
-        //查询库中正在签署的协议
-        SysUserContractRecord contractRecord = sysUserContractRecordService.getOne(Wrappers.<SysUserContractRecord>lambdaQuery()
-                .eq(SysUserContractRecord::getUserId, user.getId())
-                .eq(SysUserContractRecord::getContractId, templateId)
-                .in(SysUserContractRecord::getStatus, DealStatusEnum.SCCESS.getCode(), DealStatusEnum.DOING.getCode()));
+        SysUserContractRecord contractRecord = sysUserContractRecordService.queryLatestContract(user.getId(), SysUserType.TEACHER, contractType);
 
         //未签署协议
         if (null == contractRecord) {
+            ContractTemplate contractTemplate = contractTemplateService.queryLatestContractTemplate(contractType);
+            if (null == contractTemplate) {
+                return failed(HttpStatus.FORBIDDEN, "未找到协议");
+            }
             contractRecord = new SysUserContractRecord();
             Long contractNo = idGeneratorService.generatorId("contractNo");
             contractRecord.setContractNo(contractNo.toString());
             contractRecord.setUserId(user.getId());
+            contractRecord.setContractId(contractTemplate.getId());
+            //注意 老师端默认用户为teacher
+            contractRecord.setUserType(SysUserType.TEACHER.getCode());
 
-            ContractTemplate contractTemplate = contractTemplateService.get(templateId);
-            if(null == contractTemplate){
-                return failed(HttpStatus.FORBIDDEN, "未找到协议");
-            }
-            contractRecord.setContractId(templateId);
-
-            if (ContractTypeEnum.WITHDRAW.getCode().equals(contractTemplate.getType())) {
+            if (ContractTemplateSourceEnum.LINGXINPAY.getCode().equals(contractTemplate.getSource())
+                    && ContractTemplateTypeEnum.WITHDRAW.getCode().equals(contractTemplate.getType())) {
                 //签署提现协议
-                contractRecord.setUserType(SysUserType.TEACHER.getCode());
                 contractRecord.setStatus(DealStatusEnum.DOING.getCode());
                 flag = withdrawSdk.signContract(user.getRealName(), user.getIdCardNo(), user.getPhone(), contractNo.toString());
+            } else {
+                HttpResponseResult<String> stringHttpResponseResult = contractService.transferProduceContract(contractRecord.getUserId(), SysUserType.TEACHER, contractType, true);
+                if (stringHttpResponseResult.getStatus()) {
+                    contractRecord.setUrl(stringHttpResponseResult.getData());
+                    contractRecord.setStatus(DealStatusEnum.SCCESS.getCode());
+                    flag = true;
+                }
             }
             if (flag) {
                 sysUserContractRecordService.save(contractRecord);

+ 70 - 0
cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/UploadFileController.java

@@ -0,0 +1,70 @@
+package com.yonge.cooleshow.website.controller;
+
+import com.ksyun.ks3.dto.PostObjectFormFields;
+import com.yonge.cooleshow.biz.dal.service.UploadFileService;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.entity.UploadReturnBean;
+import com.yonge.toolset.thirdparty.entity.UploadSign;
+import com.yonge.toolset.utils.upload.UploadUtil;
+import io.swagger.annotations.*;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 上传控制层
+ */
+@RestController
+@Api(tags = "文件上传服务")
+public class UploadFileController extends BaseController {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(UploadFileController.class);
+
+    @Autowired
+    private UploadFileService uploadFileService;
+
+    @PostMapping("/uploadFile")
+    public Object uploadFile(@ApiParam(value = "上传的文件", required = true) @RequestParam("file") MultipartFile file) {
+        try {
+            if (file != null && StringUtils.isNotBlank(file.getOriginalFilename())) {
+                UploadReturnBean bean = uploadFileService.uploadFile(file.getInputStream(), UploadUtil.getExtension(file.getOriginalFilename()));
+                bean.setName(file.getOriginalFilename());
+                if (bean.isStatus()) {
+                    return succeed(bean);
+                }
+                return failed(bean.getMessage());
+            }
+        } catch (Exception e) {
+            LOGGER.error("上传失败", e);
+        }
+        return failed("上传失败");
+    }
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "bucketName", dataType = "String", value = "为空时默认使用daya"),
+            @ApiImplicitParam(name = "fileName", dataType = "String", value = "要上传的文件名称,不包含路径信息"),
+            @ApiImplicitParam(name = "postData", dataType = "Map", value = "1.如果使用js sdk上传的时候设置了ACL请设置,例\"acl\":\"public-read\"值要与SDK中一致,没有则删除该项</br>" +
+                    "2.提供js sdk中的key值,例\"key\":\"20150115/中文/${filename}\""),
+            @ApiImplicitParam(name = "unknowValueField", dataType = "List", value = "对于用户无法确定表单值的放在unknownValueField中(比如有的上传控件会添加一些表单项,但表单项的值可能是随机的)"),
+    })
+    @ApiOperation(value = "获取上传文件签名", notes = "{\n" +
+            "    \"bucketName\":\"\",\n" +
+            "    \"filename\":\"test.png\",\n" +
+            "    \"postData\":{\n" +
+            "        \"acl\":\"public-read\",\n" +
+            "        \"key\":\"20150115/中文/${filename}\"\n" +
+            "    },\n" +
+            "    \"unknowValueField\":[\"test\"]\n" +
+            "}")
+    @PostMapping("/getUploadSign")
+    public HttpResponseResult<PostObjectFormFields> getUploadSign(@RequestBody UploadSign uploadSign) {
+        return succeed(uploadFileService.getUploadSign(uploadSign));
+    }
+}