From ca26281832698ce4820eb10146108adccb53f34a Mon Sep 17 00:00:00 2001
From: huangdeliang <huangdeliang@skieer.com>
Date: Sat, 24 Oct 2020 01:03:24 +0800
Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=8F=91=E5=90=88=E5=90=8C=E5=8A=9F?=
 =?UTF-8?q?=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ruoyi-admin/pom.xml                           |  17 +
 .../controller/common/CommonController.java   |  14 +-
 .../custom/SysContractController.java         | 112 +++++
 .../com/ruoyi/custom/domain/SysContract.java  | 114 +++++
 .../custom/mapper/SysContractMapper.java      |  61 +++
 .../custom/service/ISysContractService.java   |  61 +++
 .../service/impl/SysContractServiceImpl.java  |  96 +++++
 .../mapper/custom/SysContractMapper.xml       |  95 +++++
 ruoyi-ui/src/api/custom/contract.js           |  53 +++
 ruoyi-ui/src/permission.js                    |   2 +-
 ruoyi-ui/src/router/index.js                  |   4 +-
 ruoyi-ui/src/views/custom/contract/index.vue  | 398 ++++++++++++++----
 .../src/views/custom/signContract/index.vue   | 106 +++++
 sql/ry_20200920.sql                           |  20 +-
 14 files changed, 1046 insertions(+), 107 deletions(-)
 create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/custom/SysContractController.java
 create mode 100644 ruoyi-custom/src/main/java/com/ruoyi/custom/domain/SysContract.java
 create mode 100644 ruoyi-custom/src/main/java/com/ruoyi/custom/mapper/SysContractMapper.java
 create mode 100644 ruoyi-custom/src/main/java/com/ruoyi/custom/service/ISysContractService.java
 create mode 100644 ruoyi-custom/src/main/java/com/ruoyi/custom/service/impl/SysContractServiceImpl.java
 create mode 100644 ruoyi-custom/src/main/resources/mapper/custom/SysContractMapper.xml
 create mode 100644 ruoyi-ui/src/api/custom/contract.js
 create mode 100644 ruoyi-ui/src/views/custom/signContract/index.vue

diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 5d215da05..2fb3e6223 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -119,6 +119,23 @@
             <scope>provided</scope>
         </dependency>
 
+        <!-- itextpdf-->
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>kernel</artifactId>
+            <version>7.1.12</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>layout</artifactId>
+            <version>7.1.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.7.30</version>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
index 4e6dbd393..0295cba77 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -98,17 +98,5 @@ public class CommonController {
         FileUtils.writeBytes(downloadPath, response.getOutputStream());
     }
 
-    /**
-     * 合同签单
-     */
-    @PostMapping("/common/contract")
-    public AjaxResult signContract(@RequestBody Contract contract) throws Exception {
-        try {
-            AjaxResult ajax = AjaxResult.success();
-            ajax.put("result", "hi");
-            return ajax;
-        } catch (Exception e) {
-            return AjaxResult.error(e.getMessage());
-        }
-    }
+
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/custom/SysContractController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/custom/SysContractController.java
new file mode 100644
index 000000000..71312315a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/custom/SysContractController.java
@@ -0,0 +1,112 @@
+package com.ruoyi.web.controller.custom;
+
+import java.util.List;
+
+import com.ruoyi.common.core.domain.model.Contract;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.custom.domain.SysContract;
+import com.ruoyi.custom.service.ISysContractService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 合同Controller
+ *
+ * @author wonder
+ * @date 2020-10-23
+ */
+@RestController
+@RequestMapping("/custom/contract")
+public class SysContractController extends BaseController {
+    @Autowired
+    private ISysContractService sysContractService;
+
+    /**
+     * 查询合同列表
+     */
+    @PreAuthorize("@ss.hasPermi('custom:contract:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysContract sysContract) {
+        startPage();
+        List<SysContract> list = sysContractService.selectSysContractList(sysContract);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出合同列表
+     */
+    @PreAuthorize("@ss.hasPermi('custom:contract:export')")
+    @Log(title = "合同", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(SysContract sysContract) {
+        List<SysContract> list = sysContractService.selectSysContractList(sysContract);
+        ExcelUtil<SysContract> util = new ExcelUtil<SysContract>(SysContract.class);
+        return util.exportExcel(list, "contract");
+    }
+
+    /**
+     * 获取合同详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('custom:contract:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return AjaxResult.success(sysContractService.selectSysContractById(id));
+    }
+
+    /**
+     * 新增合同
+     */
+    @PreAuthorize("@ss.hasPermi('custom:contract:add')")
+    @Log(title = "合同", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysContract sysContract) {
+        return toAjax(sysContractService.insertSysContract(sysContract));
+    }
+
+    /**
+     * 修改合同
+     */
+    @PreAuthorize("@ss.hasPermi('custom:contract:edit')")
+    @Log(title = "合同", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysContract sysContract) {
+        return toAjax(sysContractService.updateSysContract(sysContract));
+    }
+
+    /**
+     * 删除合同
+     */
+    @PreAuthorize("@ss.hasPermi('custom:contract:remove')")
+    @Log(title = "合同", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(sysContractService.deleteSysContractByIds(ids));
+    }
+
+    /**
+     * 合同签单
+     */
+    @PostMapping("/sign")
+    public AjaxResult signContract(@RequestBody Contract contract) throws Exception {
+        try {
+            AjaxResult ajax = AjaxResult.success();
+            ajax.put("result", "hi");
+            return ajax;
+        } catch (Exception e) {
+            return AjaxResult.error(e.getMessage());
+        }
+    }
+}
diff --git a/ruoyi-custom/src/main/java/com/ruoyi/custom/domain/SysContract.java b/ruoyi-custom/src/main/java/com/ruoyi/custom/domain/SysContract.java
new file mode 100644
index 000000000..feffe6f99
--- /dev/null
+++ b/ruoyi-custom/src/main/java/com/ruoyi/custom/domain/SysContract.java
@@ -0,0 +1,114 @@
+package com.ruoyi.custom.domain;
+
+import java.math.BigDecimal;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 合同对象 sys_contract
+ * 
+ * @author wonder
+ * @date 2020-10-23
+ */
+public class SysContract extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 合同编号 */
+    @Excel(name = "合同编号")
+    private Long id;
+
+    /** 客户姓名 */
+    @Excel(name = "客户姓名")
+    private String name;
+
+    /** 电话 */
+    @Excel(name = "电话")
+    private String phone;
+
+    /** 服务时间 */
+    @Excel(name = "服务时间")
+    private Integer serveTime;
+
+    /** 金额 */
+    @Excel(name = "金额")
+    private BigDecimal amount;
+
+    /** 文件路径 */
+    @Excel(name = "文件路径")
+    private String path;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setName(String name) 
+    {
+        this.name = name;
+    }
+
+    public String getName() 
+    {
+        return name;
+    }
+    public void setPhone(String phone) 
+    {
+        this.phone = phone;
+    }
+
+    public String getPhone() 
+    {
+        return phone;
+    }
+    public void setServeTime(Integer serveTime) 
+    {
+        this.serveTime = serveTime;
+    }
+
+    public Integer getServeTime() 
+    {
+        return serveTime;
+    }
+    public void setAmount(BigDecimal amount) 
+    {
+        this.amount = amount;
+    }
+
+    public BigDecimal getAmount() 
+    {
+        return amount;
+    }
+    public void setPath(String path) 
+    {
+        this.path = path;
+    }
+
+    public String getPath() 
+    {
+        return path;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("name", getName())
+            .append("phone", getPhone())
+            .append("serveTime", getServeTime())
+            .append("amount", getAmount())
+            .append("path", getPath())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/ruoyi-custom/src/main/java/com/ruoyi/custom/mapper/SysContractMapper.java b/ruoyi-custom/src/main/java/com/ruoyi/custom/mapper/SysContractMapper.java
new file mode 100644
index 000000000..7755acd5a
--- /dev/null
+++ b/ruoyi-custom/src/main/java/com/ruoyi/custom/mapper/SysContractMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.custom.mapper;
+
+import java.util.List;
+import com.ruoyi.custom.domain.SysContract;
+
+/**
+ * 合同Mapper接口
+ * 
+ * @author wonder
+ * @date 2020-10-23
+ */
+public interface SysContractMapper 
+{
+    /**
+     * 查询合同
+     * 
+     * @param id 合同ID
+     * @return 合同
+     */
+    public SysContract selectSysContractById(Long id);
+
+    /**
+     * 查询合同列表
+     * 
+     * @param sysContract 合同
+     * @return 合同集合
+     */
+    public List<SysContract> selectSysContractList(SysContract sysContract);
+
+    /**
+     * 新增合同
+     * 
+     * @param sysContract 合同
+     * @return 结果
+     */
+    public int insertSysContract(SysContract sysContract);
+
+    /**
+     * 修改合同
+     * 
+     * @param sysContract 合同
+     * @return 结果
+     */
+    public int updateSysContract(SysContract sysContract);
+
+    /**
+     * 删除合同
+     * 
+     * @param id 合同ID
+     * @return 结果
+     */
+    public int deleteSysContractById(Long id);
+
+    /**
+     * 批量删除合同
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteSysContractByIds(Long[] ids);
+}
diff --git a/ruoyi-custom/src/main/java/com/ruoyi/custom/service/ISysContractService.java b/ruoyi-custom/src/main/java/com/ruoyi/custom/service/ISysContractService.java
new file mode 100644
index 000000000..40bf5d920
--- /dev/null
+++ b/ruoyi-custom/src/main/java/com/ruoyi/custom/service/ISysContractService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.custom.service;
+
+import java.util.List;
+import com.ruoyi.custom.domain.SysContract;
+
+/**
+ * 合同Service接口
+ * 
+ * @author wonder
+ * @date 2020-10-23
+ */
+public interface ISysContractService 
+{
+    /**
+     * 查询合同
+     * 
+     * @param id 合同ID
+     * @return 合同
+     */
+    public SysContract selectSysContractById(Long id);
+
+    /**
+     * 查询合同列表
+     * 
+     * @param sysContract 合同
+     * @return 合同集合
+     */
+    public List<SysContract> selectSysContractList(SysContract sysContract);
+
+    /**
+     * 新增合同
+     * 
+     * @param sysContract 合同
+     * @return 结果
+     */
+    public int insertSysContract(SysContract sysContract);
+
+    /**
+     * 修改合同
+     * 
+     * @param sysContract 合同
+     * @return 结果
+     */
+    public int updateSysContract(SysContract sysContract);
+
+    /**
+     * 批量删除合同
+     * 
+     * @param ids 需要删除的合同ID
+     * @return 结果
+     */
+    public int deleteSysContractByIds(Long[] ids);
+
+    /**
+     * 删除合同信息
+     * 
+     * @param id 合同ID
+     * @return 结果
+     */
+    public int deleteSysContractById(Long id);
+}
diff --git a/ruoyi-custom/src/main/java/com/ruoyi/custom/service/impl/SysContractServiceImpl.java b/ruoyi-custom/src/main/java/com/ruoyi/custom/service/impl/SysContractServiceImpl.java
new file mode 100644
index 000000000..9fbbea799
--- /dev/null
+++ b/ruoyi-custom/src/main/java/com/ruoyi/custom/service/impl/SysContractServiceImpl.java
@@ -0,0 +1,96 @@
+package com.ruoyi.custom.service.impl;
+
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.custom.mapper.SysContractMapper;
+import com.ruoyi.custom.domain.SysContract;
+import com.ruoyi.custom.service.ISysContractService;
+
+/**
+ * 合同Service业务层处理
+ * 
+ * @author wonder
+ * @date 2020-10-23
+ */
+@Service
+public class SysContractServiceImpl implements ISysContractService 
+{
+    @Autowired
+    private SysContractMapper sysContractMapper;
+
+    /**
+     * 查询合同
+     * 
+     * @param id 合同ID
+     * @return 合同
+     */
+    @Override
+    public SysContract selectSysContractById(Long id)
+    {
+        return sysContractMapper.selectSysContractById(id);
+    }
+
+    /**
+     * 查询合同列表
+     * 
+     * @param sysContract 合同
+     * @return 合同
+     */
+    @Override
+    public List<SysContract> selectSysContractList(SysContract sysContract)
+    {
+        return sysContractMapper.selectSysContractList(sysContract);
+    }
+
+    /**
+     * 新增合同
+     * 
+     * @param sysContract 合同
+     * @return 结果
+     */
+    @Override
+    public int insertSysContract(SysContract sysContract)
+    {
+        sysContract.setCreateTime(DateUtils.getNowDate());
+        return sysContractMapper.insertSysContract(sysContract);
+    }
+
+    /**
+     * 修改合同
+     * 
+     * @param sysContract 合同
+     * @return 结果
+     */
+    @Override
+    public int updateSysContract(SysContract sysContract)
+    {
+        sysContract.setUpdateTime(DateUtils.getNowDate());
+        return sysContractMapper.updateSysContract(sysContract);
+    }
+
+    /**
+     * 批量删除合同
+     * 
+     * @param ids 需要删除的合同ID
+     * @return 结果
+     */
+    @Override
+    public int deleteSysContractByIds(Long[] ids)
+    {
+        return sysContractMapper.deleteSysContractByIds(ids);
+    }
+
+    /**
+     * 删除合同信息
+     * 
+     * @param id 合同ID
+     * @return 结果
+     */
+    @Override
+    public int deleteSysContractById(Long id)
+    {
+        return sysContractMapper.deleteSysContractById(id);
+    }
+}
diff --git a/ruoyi-custom/src/main/resources/mapper/custom/SysContractMapper.xml b/ruoyi-custom/src/main/resources/mapper/custom/SysContractMapper.xml
new file mode 100644
index 000000000..c4912fee3
--- /dev/null
+++ b/ruoyi-custom/src/main/resources/mapper/custom/SysContractMapper.xml
@@ -0,0 +1,95 @@
+<?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.ruoyi.custom.mapper.SysContractMapper">
+    
+    <resultMap type="SysContract" id="SysContractResult">
+        <result property="id"    column="id"    />
+        <result property="name"    column="name"    />
+        <result property="phone"    column="phone"    />
+        <result property="serveTime"    column="serve_time"    />
+        <result property="amount"    column="amount"    />
+        <result property="path"    column="path"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+    </resultMap>
+
+    <sql id="selectSysContractVo">
+        select id, name, phone, serve_time, amount, path, create_by, create_time, update_by, update_time, remark from sys_contract
+    </sql>
+
+    <select id="selectSysContractList" parameterType="SysContract" resultMap="SysContractResult">
+        <include refid="selectSysContractVo"/>
+        <where>  
+            <if test="id != null "> and id = #{id}</if>
+            <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
+            <if test="phone != null  and phone != ''"> and phone = #{phone}</if>
+        </where>
+    </select>
+    
+    <select id="selectSysContractById" parameterType="Long" resultMap="SysContractResult">
+        <include refid="selectSysContractVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertSysContract" parameterType="SysContract" useGeneratedKeys="true" keyProperty="id">
+        insert into sys_contract
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="name != null and name != ''">name,</if>
+            <if test="phone != null">phone,</if>
+            <if test="serveTime != null">serve_time,</if>
+            <if test="amount != null">amount,</if>
+            <if test="path != null">path,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="name != null and name != ''">#{name},</if>
+            <if test="phone != null">#{phone},</if>
+            <if test="serveTime != null">#{serveTime},</if>
+            <if test="amount != null">#{amount},</if>
+            <if test="path != null">#{path},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateSysContract" parameterType="SysContract">
+        update sys_contract
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="name != null and name != ''">name = #{name},</if>
+            <if test="phone != null">phone = #{phone},</if>
+            <if test="serveTime != null">serve_time = #{serveTime},</if>
+            <if test="amount != null">amount = #{amount},</if>
+            <if test="path != null">path = #{path},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteSysContractById" parameterType="Long">
+        delete from sys_contract where id = #{id}
+    </delete>
+
+    <delete id="deleteSysContractByIds" parameterType="String">
+        delete from sys_contract where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+    
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-ui/src/api/custom/contract.js b/ruoyi-ui/src/api/custom/contract.js
new file mode 100644
index 000000000..80fa8bec4
--- /dev/null
+++ b/ruoyi-ui/src/api/custom/contract.js
@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询合同列表
+export function listContract(query) {
+  return request({
+    url: '/custom/contract/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询合同详细
+export function getContract(id) {
+  return request({
+    url: '/custom/contract/' + id,
+    method: 'get'
+  })
+}
+
+// 新增合同
+export function addContract(data) {
+  return request({
+    url: '/custom/contract',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改合同
+export function updateContract(data) {
+  return request({
+    url: '/custom/contract',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除合同
+export function delContract(id) {
+  return request({
+    url: '/custom/contract/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出合同
+export function exportContract(query) {
+  return request({
+    url: '/custom/contract/export',
+    method: 'get',
+    params: query
+  })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/permission.js b/ruoyi-ui/src/permission.js
index bdec77067..5b7d18cd1 100644
--- a/ruoyi-ui/src/permission.js
+++ b/ruoyi-ui/src/permission.js
@@ -7,7 +7,7 @@ import { getToken } from '@/utils/auth'
 
 NProgress.configure({ showSpinner: false })
 
-const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/contract']
+const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/sign']
 
 router.beforeEach((to, from, next) => {
   NProgress.start()
diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js
index 1dfaeeeca..59e6ce592 100644
--- a/ruoyi-ui/src/router/index.js
+++ b/ruoyi-ui/src/router/index.js
@@ -125,9 +125,9 @@ export const constantRoutes = [
     ]
   },
   {
-    path: '/contract',
+    path: '/sign',
     hidden: true,
-    component: (resolve) => require(['@/views/custom/contract'], resolve),
+    component: (resolve) => require(['@/views/custom/signContract'], resolve),
   }
 ]
 
diff --git a/ruoyi-ui/src/views/custom/contract/index.vue b/ruoyi-ui/src/views/custom/contract/index.vue
index 3574e181b..2964dbcd1 100644
--- a/ruoyi-ui/src/views/custom/contract/index.vue
+++ b/ruoyi-ui/src/views/custom/contract/index.vue
@@ -1,107 +1,325 @@
 <template>
-  <div class="dashboard-editor-container">
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="合同编号" prop="id">
+        <el-input
+          v-model="queryParams.id"
+          placeholder="请输入合同编号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="客户姓名" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入客户姓名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="电话" prop="phone">
+        <el-input
+          v-model="queryParams.phone"
+          placeholder="请输入电话"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
 
-    <panel-group @handleSetLineChartData="handleSetLineChartData"/>
-
-    <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
-      <line-chart :chart-data="lineChartData"/>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['custom:contract:add']"
+        >新增</el-button>
+      </el-col>
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="success"-->
+<!--          icon="el-icon-edit"-->
+<!--          size="mini"-->
+<!--          :disabled="single"-->
+<!--          @click="handleUpdate"-->
+<!--          v-hasPermi="['custom:contract:edit']"-->
+<!--        >修改</el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="danger"-->
+<!--          icon="el-icon-delete"-->
+<!--          size="mini"-->
+<!--          :disabled="multiple"-->
+<!--          @click="handleDelete"-->
+<!--          v-hasPermi="['custom:contract:remove']"-->
+<!--        >删除</el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="warning"-->
+<!--          icon="el-icon-download"-->
+<!--          size="mini"-->
+<!--          @click="handleExport"-->
+<!--          v-hasPermi="['custom:contract:export']"-->
+<!--        >导出</el-button>-->
+<!--      </el-col>-->
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <!--    <el-row :gutter="32">-->
-    <!--      <el-col :xs="24" :sm="24" :lg="8">-->
-    <!--        <div class="chart-wrapper">-->
-    <!--          <raddar-chart />-->
-    <!--        </div>-->
-    <!--      </el-col>-->
-    <!--      <el-col :xs="24" :sm="24" :lg="8">-->
-    <!--        <div class="chart-wrapper">-->
-    <!--          <pie-chart />-->
-    <!--        </div>-->
-    <!--      </el-col>-->
-    <!--      <el-col :xs="24" :sm="24" :lg="8">-->
-    <!--        <div class="chart-wrapper">-->
-    <!--          <bar-chart />-->
-    <!--        </div>-->
-    <!--      </el-col>-->
-    <!--    </el-row>-->
+    <el-table v-loading="loading" :data="contractList" @selection-change="handleSelectionChange">
+<!--      <el-table-column type="selection" width="55" align="center" />-->
+      <el-table-column label="合同编号" align="center" prop="id" />
+      <el-table-column label="客户姓名" align="center" prop="name" />
+      <el-table-column label="电话" align="center" prop="phone" />
+      <el-table-column label="服务时间" align="center" prop="serveTime" :formatter="serveTimeFormat" />
+      <el-table-column label="金额" align="center" prop="amount" />
+      <el-table-column label="合同地址" align="center" prop="path" />
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-edit"-->
+<!--            @click="handleUpdate(scope.row)"-->
+<!--            v-hasPermi="['custom:contract:edit']"-->
+<!--          >修改</el-button>-->
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['custom:contract:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
 
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
 
+    <!-- 添加或修改合同对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="客户姓名" prop="name">
+          <el-input v-model="form.name" placeholder="请输入客户姓名" />
+        </el-form-item>
+        <el-form-item label="电话" prop="phone">
+          <el-input v-model="form.phone" placeholder="请输入电话" />
+        </el-form-item>
+        <el-form-item label="服务时间" prop="serveTime">
+          <el-select v-model="form.serveTime" placeholder="请选择服务时间">
+            <el-option
+              v-for="dict in serveTimeOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="金额" prop="amount">
+          <el-input v-model="form.amount" placeholder="请输入金额" />
+        </el-form-item>
+<!--        <el-form-item label="文件路径" prop="path">-->
+<!--          <el-input v-model="form.path" placeholder="请输入文件路径" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-  import PanelGroup from '@/views/dashboard/PanelGroup'
-  import LineChart from '@/views/dashboard/LineChart'
-  import RaddarChart from '@/views/dashboard/RaddarChart'
-  import PieChart from '@/views/dashboard/PieChart'
-  import BarChart from '@/views/dashboard/BarChart'
-  import Base64 from 'base-64';
-  import {searchToParams} from "../../../utils/ruoyi";
+import { listContract, getContract, delContract, addContract, updateContract, exportContract } from "@/api/custom/contract";
 
-  const lineChartData = {
-    newVisitis: {
-      expectedData: [100, 120, 161, 134, 105, 160, 165],
-      actualData: [120, 82, 91, 154, 162, 140, 145]
+export default {
+  name: "Contract",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 合同表格数据
+      contractList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 服务时间字典
+      serveTimeOptions: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        id: null,
+        name: null,
+        phone: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        name: [
+          { required: true, message: "客户姓名不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    this.getDicts("cus_serve_time").then(response => {
+      this.serveTimeOptions = response.data;
+    });
+  },
+  methods: {
+    /** 查询合同列表 */
+    getList() {
+      this.loading = true;
+      listContract(this.queryParams).then(response => {
+        this.contractList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
     },
-    messages: {
-      expectedData: [200, 192, 120, 144, 160, 130, 140],
-      actualData: [180, 160, 151, 106, 145, 150, 130]
+    // 服务时间字典翻译
+    serveTimeFormat(row, column) {
+      return this.selectDictLabel(this.serveTimeOptions, row.serveTime);
     },
-    purchases: {
-      expectedData: [80, 100, 121, 104, 105, 90, 100],
-      actualData: [120, 90, 100, 138, 142, 130, 130]
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
     },
-    shoppings: {
-      expectedData: [130, 140, 141, 142, 145, 150, 160],
-      actualData: [120, 82, 91, 154, 162, 140, 130]
-    }
-  }
-
-  let params = window.location.search.substring(1);
-  if(params){
-    params = Base64.decode( window.location.search.substring(1))
-    params = searchToParams((params));
-  }
-  console.log(params)
-
-  export default {
-    name: 'Index',
-    components: {
-      PanelGroup,
-      LineChart,
-      RaddarChart,
-      PieChart,
-      BarChart
-    },
-    data() {
-      return {
-        lineChartData: lineChartData.newVisitis
-      }
-    },
-    methods: {
-      handleSetLineChartData(type) {
-        this.lineChartData = lineChartData[type]
-      }
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        name: null,
+        phone: null,
+        serveTime: null,
+        amount: null,
+        path: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null,
+        remark: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加合同";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getContract(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改合同";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateContract(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addContract(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除合同编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delContract(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有合同数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportContract(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
     }
   }
+};
 </script>
-
-<style lang="scss" scoped>
-  .dashboard-editor-container {
-    padding: 32px;
-    background-color: rgb(240, 242, 245);
-    position: relative;
-
-    .chart-wrapper {
-      background: #fff;
-      padding: 16px 16px 0;
-      margin-bottom: 32px;
-    }
-  }
-
-  @media (max-width: 1024px) {
-    .chart-wrapper {
-      padding: 8px;
-    }
-  }
-</style>
diff --git a/ruoyi-ui/src/views/custom/signContract/index.vue b/ruoyi-ui/src/views/custom/signContract/index.vue
new file mode 100644
index 000000000..0b4f0409d
--- /dev/null
+++ b/ruoyi-ui/src/views/custom/signContract/index.vue
@@ -0,0 +1,106 @@
+<template>
+  <div class="dashboard-editor-container">
+
+    <panel-group @handleSetLineChartData="handleSetLineChartData"/>
+
+    <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
+      <line-chart :chart-data="lineChartData"/>
+    </el-row>
+
+    <!--    <el-row :gutter="32">-->
+    <!--      <el-col :xs="24" :sm="24" :lg="8">-->
+    <!--        <div class="chart-wrapper">-->
+    <!--          <raddar-chart />-->
+    <!--        </div>-->
+    <!--      </el-col>-->
+    <!--      <el-col :xs="24" :sm="24" :lg="8">-->
+    <!--        <div class="chart-wrapper">-->
+    <!--          <pie-chart />-->
+    <!--        </div>-->
+    <!--      </el-col>-->
+    <!--      <el-col :xs="24" :sm="24" :lg="8">-->
+    <!--        <div class="chart-wrapper">-->
+    <!--          <bar-chart />-->
+    <!--        </div>-->
+    <!--      </el-col>-->
+    <!--    </el-row>-->
+
+
+  </div>
+</template>
+
+<script>
+  import PanelGroup from '@/views/dashboard/PanelGroup'
+  import LineChart from '@/views/dashboard/LineChart'
+  import RaddarChart from '@/views/dashboard/RaddarChart'
+  import PieChart from '@/views/dashboard/PieChart'
+  import BarChart from '@/views/dashboard/BarChart'
+  import Base64 from 'base-64';
+
+  const lineChartData = {
+    newVisitis: {
+      expectedData: [100, 120, 161, 134, 105, 160, 165],
+      actualData: [120, 82, 91, 154, 162, 140, 145]
+    },
+    messages: {
+      expectedData: [200, 192, 120, 144, 160, 130, 140],
+      actualData: [180, 160, 151, 106, 145, 150, 130]
+    },
+    purchases: {
+      expectedData: [80, 100, 121, 104, 105, 90, 100],
+      actualData: [120, 90, 100, 138, 142, 130, 130]
+    },
+    shoppings: {
+      expectedData: [130, 140, 141, 142, 145, 150, 160],
+      actualData: [120, 82, 91, 154, 162, 140, 130]
+    }
+  }
+
+  let params = window.location.search.substring(1);
+  if(params){
+    params = Base64.decode( window.location.search.substring(1))
+    params = this.searchToParams((params));
+  }
+  console.log(params)
+
+  export default {
+    name: 'Index',
+    components: {
+      PanelGroup,
+      LineChart,
+      RaddarChart,
+      PieChart,
+      BarChart
+    },
+    data() {
+      return {
+        lineChartData: lineChartData.newVisitis
+      }
+    },
+    methods: {
+      handleSetLineChartData(type) {
+        this.lineChartData = lineChartData[type]
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .dashboard-editor-container {
+    padding: 32px;
+    background-color: rgb(240, 242, 245);
+    position: relative;
+
+    .chart-wrapper {
+      background: #fff;
+      padding: 16px 16px 0;
+      margin-bottom: 32px;
+    }
+  }
+
+  @media (max-width: 1024px) {
+    .chart-wrapper {
+      padding: 8px;
+    }
+  }
+</style>
diff --git a/sql/ry_20200920.sql b/sql/ry_20200920.sql
index 57c1958a8..44e721bee 100644
--- a/sql/ry_20200920.sql
+++ b/sql/ry_20200920.sql
@@ -739,6 +739,24 @@ CREATE VIEW view_user_post AS (
   SELECT up.user_id, u.nick_name AS user_name, p.post_id, p.post_name
   FROM sys_post p, sys_user u, sys_user_post up
   WHERE p.post_id = up.post_id AND u.user_id = up.user_id
-  )
+  );
 
+-- ----------------------------
+-- 21、订单业务表字段
+-- ----------------------------
+drop table if exists sys_contract;
+create table sys_order (
+       id               bigint(20)      not null auto_increment    comment '合同编号',
+       name             varchar(30)     not null                   comment '客户姓名',
+       phone            varchar(30)                                comment '电话',
+       serve_time       tinyint                                    comment '服务时间',
+       amount           decimal(10,2)                              comment '金额',
+       path             varchar(255)                               comment '文件路径',
+       create_by        varchar(64)     default ''                 comment '创建者',
+       create_time      datetime                                   comment '创建时间',
+       update_by        varchar(64)     default ''                 comment '更新者',
+       update_time      datetime                                   comment '更新时间',
+       remark           varchar(500)    default null               comment '备注',
+       primary key (id)
+) engine=innodb auto_increment=1 comment = '合同表';