Bladeren bron

feature:添加续签合同相关功能

sunxinyuan 1 jaar geleden
bovenliggende
commit
688c207309

+ 12 - 0
src/api/contract/index.js

@@ -58,4 +58,16 @@ export default {
   exportMaintenance(query) {
     return micro_request.postRequest(basePath, 'CtrContract', 'CtrContractMaintenanceExport', query)
   },
+  // 续签合同
+  reNewContract(query) {
+    return micro_request.postRequest(basePath, 'CtrContract', 'ReNew', query)
+  },
+  // 查询关联续签合同
+  renewList(query) {
+    return micro_request.postRequest(basePath, 'CtrContract', 'RenewList', query)
+  },
+  // 查询关联续签合同
+  updateReNew(query) {
+    return micro_request.postRequest(basePath, 'CtrContract', 'UpdateReNew', query)
+  },
 }

+ 390 - 0
src/components/select/SelectCtrContract.vue

@@ -0,0 +1,390 @@
+<template>
+  <el-dialog append-to-body :title="title" :visible.sync="innerVisible" @close="close">
+    <el-row v-if="add" style="margin-top: -30px">
+      <el-col :span="24">
+        <div style="float: right">
+          <el-button size="mini" type="primary" @click="handleAdd">新建项目</el-button>
+          <!--          <el-dropdown style="margin-left: 10px" trigger="click">-->
+          <!--            <el-button icon="el-icon-more" size="mini" />-->
+          <!--            <el-dropdown-menu slot="dropdown">-->
+          <!--              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>-->
+          <!--              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>-->
+          <!--            </el-dropdown-menu>-->
+          <!--          </el-dropdown>-->
+        </div>
+      </el-col>
+    </el-row>
+    <el-row>
+      <el-col :span="24">
+        <el-input
+          v-model="queryForm.contractCode"
+          clearable
+          placeholder="合同编号"
+          style="width: 30%; margin-right: 10px"
+          @keyup.enter.native="fetchData" />
+
+        <el-input
+          v-model="queryForm.contractName"
+          clearable
+          placeholder="合同名称"
+          style="width: 30%; margin-right: 10px"
+          @keyup.enter.native="fetchData" />
+        <el-button icon="el-icon-search" type="primary" @click="fetchData">查询</el-button>
+
+        <!--        <span>显示:</span>-->
+        <!--        <el-radio-group v-model="queryForm.type">-->
+        <!--          <el-radio-button label="全部客户" />-->
+        <!--          <el-radio-button label="我负责的客户" />-->
+        <!--        </el-radio-group>-->
+        <table-tool
+          :columns="columns"
+          :show-columns.sync="showColumns"
+          style="float: right"
+          table-type="selectBusinessTable" />
+      </el-col>
+    </el-row>
+    <el-table ref="businessTable" v-loading="listLoading" :data="list" @selection-change="setSelectRows">
+      <el-table-column align="center" type="selection" />
+      <el-table-column
+        v-for="(item, index) in showColumns"
+        :key="index + Math.random()"
+        align="center"
+        :label="item.label"
+        :prop="item.prop"
+        show-overflow-tooltip
+        :sortable="item.sortable"
+        :width="item.width">
+        <template #default="{ row }">
+          <span v-if="item.prop === 'contractAmount'">
+            {{ formatPrice(row.contractAmount) }}
+          </span>
+          <span v-else-if="item.prop === 'approStatus'">
+            {{ approStatusOption[row.approStatus] }}
+          </span>
+          <span v-else-if="item.prop === 'productLine'">
+            {{ productLineOptions[row.productLine] }}
+          </span>
+          <span v-else-if="item.label === '合同有效时间'">
+            {{ parseTime(row.contractStartTime, '{y}-{m}-{d}') }}~{{ parseTime(row.contractEndTime, '{y}-{m}-{d}') }}
+          </span>
+          <span v-else-if="item.label === '合同类型'">
+            {{ contractOptions[row.contractType] }}
+          </span>
+          <span v-else-if="item.label === '签订单位类型'">
+            {{
+              row.signatoryType == '10'
+                ? '终端用户'
+                : row.signatoryType == '20'
+                ? '经销商'
+                : row.signatoryType == '30'
+                ? '代理商'
+                : ''
+            }}
+          </span>
+          <span v-else-if="item.label === '合同签订单位'">
+            {{
+              row.signatoryType == '10'
+                ? row.custName
+                : row.signatoryType == '20'
+                ? row.distributorName
+                : row.signatoryType == '30'
+                ? row.distributorName
+                : ''
+            }}
+          </span>
+          <span v-else-if="item.label === '合同签订时间'">
+            {{ parseTime(row.contractSignTime, '{y}-{m}-{d}') }}
+          </span>
+          <span v-else-if="item.label === '回款金额'">
+            {{ formatPrice(row.collectedAmount) }}
+          </span>
+          <span v-else-if="item.label === '开票金额'">
+            {{ formatPrice(row.invoiceAmount) }}
+          </span>
+          <span v-else-if="item.prop === 'softwareMaintenanceLimit' || item.prop === 'hardwareMaintenanceLimit'">
+            {{ row[item.prop] + '年' }}
+          </span>
+          <span v-else>{{ row[item.prop] }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      background
+      :current-page="queryForm.pageNum"
+      :layout="layout"
+      :page-size="queryForm.pageSize"
+      :total="total"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange" />
+    <span slot="footer">
+      <el-button size="mini" type="primary" @click="save">保存</el-button>
+      <el-button size="mini" @click="innerVisible = false">取消</el-button>
+    </span>
+    <!-- 新建项目弹窗 -->
+    <business-edit ref="businessEdit" @fetch-data="fetchData" />
+  </el-dialog>
+</template>
+
+<script>
+  import TableTool from '@/components/table/TableTool'
+  import BusinessEdit from '@/views/proj/business/components/BusinessEdit'
+  import contractApi from '@/api/contract'
+  import api from '@/api/customer'
+
+  export default {
+    name: 'SelectCtrContract',
+    components: {
+      TableTool,
+      BusinessEdit,
+    },
+    props: {
+      title: {
+        type: String,
+        default: '选择项目',
+      },
+      add: Boolean,
+      multiple: Boolean,
+      queryParams: {
+        type: Object,
+        default() {
+          return {}
+        },
+      },
+    },
+    data() {
+      return {
+        innerVisible: false,
+        queryForm: {
+          type: '全部客户',
+          isNotMaintenanceContract: '10',
+          contractCode: '', // 合同编号
+          contractName: '', //合同名称
+          custName: '', // 客户名称  ()
+          nboName: '', //项目名称
+          approStatus: '30', //审批状态
+          productLine: '', // 产品线
+          inchargeName: '', // 负责人(销售工程师)
+          pageNum: 1,
+          pageSize: 10,
+        },
+        showColumns: [],
+        columns: [
+          {
+            label: '合同编号',
+            width: '160px',
+            prop: 'contractCode',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同类型',
+            width: '100px',
+            prop: 'contractType',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '所在省',
+            width: '200px',
+            prop: 'custProvince',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '所在市',
+            width: '100px',
+            prop: 'custCity',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户名称',
+            width: '280px',
+            prop: 'custName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '产品线',
+            prop: 'productLine',
+            width: '140px',
+          },
+          {
+            label: '签订单位类型',
+            width: '120px',
+            prop: 'signatoryType',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同签订单位',
+            width: '280px',
+            prop: 'distributorName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同签订时间',
+            width: '120px',
+            prop: 'contractSignTime',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同有效时间',
+            width: '200px',
+            prop: 'contractStartTime',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同金额',
+            width: '120px',
+            prop: 'contractAmount',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '回款金额',
+            width: '120px',
+            prop: 'collectedAmount',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '开票金额',
+            width: '120px',
+            prop: 'invoiceAmount',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '销售工程师',
+            width: '120px',
+            prop: 'inchargeName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '审批状态',
+            width: '100px',
+            prop: 'approStatus',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '软件运维期限',
+            width: '120px',
+            prop: 'softwareMaintenanceLimit',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '硬件运维期限',
+            width: '120px',
+            prop: 'hardwareMaintenanceLimit',
+            sortable: false,
+            disableCheck: false,
+          },
+        ],
+        list: [],
+        listLoading: true,
+        layout: 'total, sizes, prev, pager, next, jumper',
+        total: 0,
+        selectRows: [],
+        nboTypeOptions: [],
+        nboPhaseOptions: [],
+        nboStatusOptions: [],
+        approStatusOptions: [],
+        salesModelOptions: [],
+        nboSourceOptions: [],
+        provinceOptions: [],
+        industryOptions: [], //客户行业
+        levelOptions: [], //客户级别
+        contractOptions: {}, //合同类型
+        productLineOptions: {}, //产品线
+        approStatusOption: {
+          10: '待提交审核',
+          20: '待审核',
+          30: '审核已同意',
+          40: '审核已拒绝',
+          50: '审核已撤销',
+        },
+      }
+    },
+    mounted() {
+      this.getOptions()
+    },
+    methods: {
+      getOptions() {
+        Promise.all([api.getProvinceDetail(), this.getDicts('contract_type'), this.getDicts('sys_product_line')])
+          .then(([province, contract, productLine]) => {
+            this.contractOptions = {}
+            contract.data.values.filter((i) => {
+              this.contractOptions[i.key] = i.value
+            })
+            this.productLineOptions = {}
+            productLine.data.values.filter((i) => {
+              this.productLineOptions[i.key] = i.value
+            })
+            this.lines = productLine.data.values
+            this.provinceOptions = province.data.list || []
+          })
+          .catch((err) => console.log(err))
+      },
+      open() {
+        this.innerVisible = true
+        this.fetchData()
+      },
+      close() {
+        this.selectRows = []
+        this.queryForm = this.$options.data().queryForm
+        this.$refs.businessTable.clearSelection()
+      },
+      save() {
+        this.innerVisible = false
+        this.$emit('save', this.selectRows)
+      },
+      handleAdd() {
+        this.$refs.businessEdit.showEdit()
+      },
+      async fetchData() {
+        this.listLoading = true
+        let query = Object.assign(this.queryForm, this.queryParams)
+        const {
+          data: { list, total },
+        } = await contractApi.getList(query)
+        this.list = list
+        this.total = total
+        this.listLoading = false
+      },
+      setSelectRows(val) {
+        if (!this.multiple && val.length === this.list.length && val.length > 1) {
+          // 返回单条数据情况下-控制全选情况下单选第一条数据
+          if (this.selectRows.length === 1) {
+            this.$refs.businessTable.clearSelection()
+            return
+          }
+          this.$refs.businessTable.clearSelection()
+          this.$refs.businessTable.toggleRowSelection(val.shift(), true)
+        } else if (!this.multiple && val.length > 1) {
+          // 返回单条数据情况下-控制选择当前点击数据
+          this.$refs.businessTable.clearSelection()
+          this.$refs.businessTable.toggleRowSelection(val.pop(), true)
+        } else {
+          this.selectRows = val
+        }
+      },
+      handleSizeChange(val) {
+        this.queryForm.pageSize = val
+        this.fetchData()
+      },
+      handleCurrentChange(val) {
+        this.queryForm.pageNum = val
+        this.fetchData()
+      },
+    },
+  }
+</script>
+
+<style scoped></style>

+ 47 - 1
src/views/contract/components/DetailsRecords.vue

@@ -34,6 +34,50 @@
               <p>职务:{{ item.opnContent.postion }}</p>
               <p>手机:{{ item.opnContent.telephone }}</p>
             </template>
+            <template v-else-if="item.opnContent.newHardwareMaintenanceBeginTime">
+              <p>
+                合同名称:
+                <span>{{ item.opnContent.contractName }}</span>
+              </p>
+              <p>
+                原合同软件运维时间:
+                <br />
+                <span>
+                  {{ parseTime(item.opnContent.oldSoftwareMaintenanceBeginTime, '{y}-{m}-{d}') }} ~
+                  {{ parseTime(item.opnContent.oldSoftwareMaintenanceEndTime, '{y}-{m}-{d}') }}
+                </span>
+              </p>
+              <p>
+                原合同硬件运维时间:
+                <br />
+                <span>
+                  {{ parseTime(item.opnContent.oldHardwareMaintenanceBeginTime, '{y}-{m}-{d}') }} ~
+                  {{ parseTime(item.opnContent.oldHardwareMaintenanceEndTime, '{y}-{m}-{d}') }}
+                </span>
+              </p>
+              <p>
+                续签合同软件运维时间:
+                <br />
+                <span>
+                  {{ parseTime(item.opnContent.newSoftwareMaintenanceBeginTime, '{y}-{m}-{d}') }} ~
+                  {{ parseTime(item.opnContent.newSoftwareMaintenanceEndTime, '{y}-{m}-{d}') }}
+                </span>
+              </p>
+              <p>
+                续签合同硬件运维时间:
+                <br />
+                <span>
+                  {{ parseTime(item.opnContent.newHardwareMaintenanceBeginTime, '{y}-{m}-{d}') }} ~
+                  {{ parseTime(item.opnContent.newHardwareMaintenanceEndTime, '{y}-{m}-{d}') }}
+                </span>
+              </p>
+            </template>
+            <template v-else-if="item.opnContent.contractName">
+              <p>
+                合同名称:
+                <span>{{ item.opnContent.contractName }}</span>
+              </p>
+            </template>
           </div>
         </li>
       </ul>
@@ -42,6 +86,8 @@
 </template>
 
 <script>
+  import { parseTime } from '../../../utils'
+
   export default {
     name: 'Records',
     props: {
@@ -57,7 +103,7 @@
 
     mounted() {},
 
-    methods: {},
+    methods: { parseTime },
   }
 </script>
 

+ 205 - 0
src/views/contract/components/DetailsRenew.vue

@@ -0,0 +1,205 @@
+<!--
+ * @Author: liuzl 461480418@qq.com
+ * @Date: 2023-01-09 13:54:40
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-01-10 14:38:22
+ * @Description: file content
+ * @FilePath: \订单全流程管理系统\src\views\contract\components\DetailsProduct.vue
+-->
+<template>
+  <div>
+    <el-table border :data="renewList">
+      <el-table-column
+        v-for="(item, index) in columns"
+        :key="index"
+        align="center"
+        :label="item.label"
+        :min-width="item.width"
+        :prop="item.prop"
+        show-overflow-tooltip>
+        <template #default="{ row }">
+          <span v-if="item.prop === 'contractType'">
+            {{ selectDictLabel(contractTypeOptions, row.contractType) }}
+          </span>
+          <span v-else-if="item.prop === 'signatoryType'">
+            {{ selectDictLabel(signatoryTypeOptions, row.signatoryType) }}
+          </span>
+          <span v-else-if="item.prop === 'contractAmount'">
+            {{ formatPrice(row.contractAmount) }}
+          </span>
+          <span v-else-if="item.prop === 'collectedAmount'">
+            {{ formatPrice(row.collectedAmount) }}
+          </span>
+          <span v-else-if="item.prop === 'contractSignTime'">
+            {{ parseTime(row.contractSignTime, '{y}-{m}-{d}') }}
+          </span>
+          <span v-else-if="item.label === '合同时间'">
+            {{ parseTime(row.contractStartTime, '{y}-{m}-{d}') }}~{{ parseTime(row.contractEndTime, '{y}-{m}-{d}') }}
+          </span>
+          <span v-else>{{ row[item.prop] }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+  import { selectDictLabel } from '../../../utils'
+
+  export default {
+    name: 'DetailsRenew',
+    components: {},
+    props: {
+      details: {
+        type: Object,
+        default: () => {},
+      },
+      renewList: {
+        type: Array,
+        default: () => [],
+      },
+    },
+    data() {
+      return {
+        columns: [
+          {
+            label: '合同编号',
+            width: '160px',
+            prop: 'contractCode',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同类型',
+            width: '100px',
+            prop: 'contractType',
+            sortable: false,
+            disableCheck: false,
+          },
+          // {
+          //   label: '审批状态',
+          //   width: '100px',
+          //   prop: 'approStatus',
+          //   sortable: false,
+          //   disableCheck: false,
+          // },
+          {
+            label: '所在省',
+            width: '100px',
+            prop: 'custProvince',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '所在市',
+            width: '100px',
+            prop: 'custCity',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户名称',
+            width: '280px',
+            prop: 'custName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '签订单位类型',
+            width: '120px',
+            prop: 'signatoryType',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同签订单位',
+            width: '120px',
+            prop: 'distributorName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同签订时间',
+            width: '180px',
+            prop: 'contractSignTime',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同有效时间',
+            width: '180px',
+            prop: 'contractStartTime',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同金额',
+            width: '120px',
+            prop: 'contractAmount',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '回款金额',
+            width: '120px',
+            prop: 'collectedAmount',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '销售工程师',
+            width: '120px',
+            prop: 'inchargeName',
+            sortable: false,
+            disableCheck: false,
+          },
+        ],
+        productLineOptions: [],
+        maintainVisible: false,
+        maintainForm: {
+          id: 0,
+          prodName: '',
+          maintainPeriod: 0,
+          warrantPeriod: 0,
+          maintainStartTime: null,
+          maintainRemark: '',
+          acceptTime: null,
+        },
+        costVisible: false,
+        costForm: {
+          id: 0,
+          prodName: '',
+          purchaseCost: 0,
+          devCost: 0,
+          maintainCost: 0,
+          directCost: 0,
+        },
+        contractTypeOptions: [],
+        signatoryTypeOptions: [],
+      }
+    },
+    computed: {
+      detailsNoMutation() {
+        let obj = Object.assign({}, this.details)
+        return obj
+      },
+    },
+    mounted() {
+      this.getOptions()
+    },
+    methods: {
+      selectDictLabel,
+      getOptions() {
+        Promise.all([this.getDicts('contract_type'), this.getDicts('contract_signatory_type')])
+          .then(([contract, signatory]) => {
+            this.contractTypeOptions = contract.data.values || []
+            this.signatoryTypeOptions = signatory.data.values || []
+            console.log('this.contractTypeOptions', this.contractTypeOptions)
+          })
+          .catch((err) => console.log(err))
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped></style>

+ 755 - 0
src/views/contract/components/RenewEdit.vue

@@ -0,0 +1,755 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-09 15:49:34
+ * @LastEditors: niezch@dashoo.cn
+ * @LastEditTime: 2023-04-04 16:18:50
+ * @Description: file content
+ * @FilePath: \opms_frontend\src\views\contract\components\Edit.vue
+-->
+<template>
+  <el-dialog class="edit-container" :title="title" top="5vh" :visible.sync="editVisible" @close="handleClose">
+    <div class="setp-wrap">
+      <el-steps :active="stepActive" :align-center="true" finish-status="success">
+        <el-step title="基础信息" />
+        <el-step title="产品列表" />
+      </el-steps>
+    </div>
+    <el-form v-show="stepActive == 0" ref="editForm" :model="editForm" :rules="editRules">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="合同编号" prop="contractCode">
+            <el-input v-model="editForm.contractCode" disabled placeholder="根据编号规则自动生产" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="关联合同" prop="renewContractName">
+            <el-input
+              v-model="editForm.renewContractName"
+              :disabled="businessData.length > 0"
+              placeholder="请选择关联合同"
+              readonly
+              suffix-icon="el-icon-search"
+              @focus="openProject" />
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="合同名称" prop="contractName">
+            <el-input v-model="editForm.contractName" placeholder="请输入合同名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="客户签约人" prop="custSignatoryName">
+            <el-input
+              v-model="editForm.custSignatoryName"
+              :disabled="!businessUserQueryParams.busId"
+              placeholder="请选择客户签约人"
+              readonly
+              suffix-icon="el-icon-search"
+              @focus="openContact" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="合同开始时间" prop="contractStartTime">
+            <el-date-picker
+              v-model="editForm.contractStartTime"
+              :picker-options="pickerOptionsStart"
+              placeholder="选择开始日期"
+              style="width: 100%"
+              type="date"
+              value-format="yyyy-MM-dd" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="合同结束时间" prop="contractEndTime">
+            <el-date-picker
+              v-model="editForm.contractEndTime"
+              :picker-options="pickerOptionsEnd"
+              placeholder="选择结束日期"
+              style="width: 100%"
+              type="date"
+              value-format="yyyy-MM-dd" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="合同签订时间" prop="contractSignTime">
+            <el-date-picker
+              v-model="editForm.contractSignTime"
+              :picker-options="pickerOptionsSign"
+              placeholder="选择签订日期"
+              style="width: 100%"
+              type="date"
+              value-format="yyyy-MM-dd" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="销售工程师" prop="inchargeName">
+            <el-input
+              v-model="editForm.inchargeName"
+              :disabled="true"
+              placeholder="请选择销售工程师"
+              readonly
+              suffix-icon="el-icon-search"
+              @focus="openUser(false, 'inchargeId', 'inchargeName')" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="公司签约人" prop="signatoryName">
+            <el-input
+              ref="signatoryName"
+              v-model="editForm.signatoryName"
+              placeholder="请选择公司签约人"
+              readonly
+              suffix-icon="el-icon-search"
+              @focus="openUser(false, 'signatoryId', 'signatoryName')" />
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="经销商/代理商" prop="distributorName">
+            <el-input
+              v-model="editForm.distributorName"
+              placeholder="请选择经销商/代理商"
+              readonly
+              suffix-icon="el-icon-search"
+              @focus="openDistributor" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="合同类型" prop="contractType">
+            <el-select v-model="editForm.contractType" placeholder="合同类型" style="width: 100%">
+              <el-option v-for="item in contractOptions" :key="item.value" :label="item.value" :value="item.key" />
+            </el-select>
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="签订单位类型" prop="signatoryType">
+            <el-select
+              v-model="editForm.signatoryType"
+              placeholder="签订单位类型"
+              style="width: 100%"
+              @change="signatoryTypeChange">
+              <el-option v-for="item in signatoryOptions" :key="item.value" :label="item.value" :value="item.key" />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="合同签订单位" prop="signatoryUnit">
+            <el-input v-model="editForm.signatoryUnit" disabled placeholder="请选择合同签订单位" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="质量/履约保证金(元)" prop="earnestMoney">
+            <el-input v-model.number="editForm.earnestMoney" clearable placeholder="请输入质量/履约保证金" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <!--        <el-col :span="12">-->
+        <!--          <el-form-item label="软件运维期限(年)" prop="softwareMaintenanceLimit">-->
+        <!--            <el-input-number-->
+        <!--              v-model.number="editForm.softwareMaintenanceLimit"-->
+        <!--              controls-position="right"-->
+        <!--              :min="0"-->
+        <!--              placeholder="请输入软件运维期限"-->
+        <!--              :step="1"-->
+        <!--              step-strictly-->
+        <!--              style="width: 100%" />-->
+        <!--          </el-form-item>-->
+        <!--          <el-form-item label="硬件运维期限(年)" prop="hardwareMaintenanceLimit">-->
+        <!--            <el-input-number-->
+        <!--              v-model="editForm.hardwareMaintenanceLimit"-->
+        <!--              controls-position="right"-->
+        <!--              :min="0"-->
+        <!--              placeholder="请输入软件运维期限"-->
+        <!--              :step="1"-->
+        <!--              style="width: 100%" />-->
+        <!--          </el-form-item>-->
+        <!--        </el-col>-->
+        <el-col :span="12">
+          <el-form-item label="软件运维开始时间" prop="softwareMaintenanceBeginTime">
+            <el-date-picker
+              v-model="editForm.softwareMaintenanceBeginTime"
+              :picker-options="softwarePickerOptionsStart"
+              placeholder="选择软件运维开始时间"
+              style="width: 100%"
+              type="date"
+              value-format="yyyy-MM-dd" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="软件运维结束时间" prop="softwareMaintenanceEndTime">
+            <el-date-picker
+              v-model="editForm.softwareMaintenanceEndTime"
+              :picker-options="softwarePickerOptionsEnd"
+              placeholder="选择软件运维结束时间"
+              style="width: 100%"
+              type="date"
+              value-format="yyyy-MM-dd" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="硬件运维开始时间" prop="hardwareMaintenanceBeginTime">
+            <el-date-picker
+              v-model="editForm.hardwareMaintenanceBeginTime"
+              :picker-options="hardwarePickerOptionsStart"
+              placeholder="选择硬件运维开始时间"
+              style="width: 100%"
+              type="date"
+              value-format="yyyy-MM-dd" />
+          </el-form-item>
+
+          <el-form-item label="硬件运维结束时间" prop="hardwareMaintenanceEndTime">
+            <el-date-picker
+              v-model="editForm.hardwareMaintenanceEndTime"
+              :picker-options="hardwarePickerOptionsEnd"
+              placeholder="选择硬件运维结束时间"
+              style="width: 100%"
+              type="date"
+              value-format="yyyy-MM-dd" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="运维服务费约定" prop="serviceFeeAgreement">
+            <el-input
+              v-model="editForm.serviceFeeAgreement"
+              placeholder="请输入运维服务费约定"
+              :rows="5"
+              type="textarea" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="运维条款" prop="maintenanceClause">
+            <el-input v-model="editForm.maintenanceClause" placeholder="请输入运维条款" :rows="5" type="textarea" />
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="备注" prop="remark">
+            <el-input v-model="editForm.remark" placeholder="请输入备注" :rows="5" type="textarea" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+    <!-- 产品分类 -->
+    <el-row v-show="stepActive == 1">
+      <el-row class="mb10" :gutter="20">
+        <el-col :span="12">
+          <p>产品:</p>
+        </el-col>
+        <el-col class="proj-col" :span="12">
+          <el-button type="primary" @click="$refs.product.open()">选择产品</el-button>
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col :span="24">
+          <product-table
+            ref="productTable"
+            :product-data="productData"
+            @changeProductData="changeProductData"
+            @delProductData="delProductData" />
+        </el-col>
+      </el-row>
+    </el-row>
+
+    <span slot="footer">
+      <el-button v-show="stepActive == 0" type="primary" @click="setStep(1)">下一步</el-button>
+      <el-button v-show="stepActive == 1" type="primary" @click="setStep(0)">上一步</el-button>
+      <el-button v-show="!editForm.id && stepActive == 1" type="primary" @click="contractSave">保存</el-button>
+      <el-button v-show="editForm.id && stepActive == 1" type="primary" @click="contractEdit">保存</el-button>
+      <el-button @click="editVisible = false">取消</el-button>
+    </span>
+    <!-- 选择项目 -->
+    <SelectCtrContract ref="project" :multiple="false" @save="getBusinessInfo" />
+    <!-- 选择经销商 -->
+    <select-distributor ref="distributor" :multiple="false" @save="getDistributor" />
+    <!-- 选择用户 -->
+    <select-user ref="user" :label="label" :multiple="multiple" :property="property" @save="getUser" />
+    <!-- 选择产品 -->
+    <select-product ref="product" :multiple="true" @save="getProduct" />
+    <!-- 选择联系人 -->
+    <select-business-contact
+      ref="contact"
+      :multiple="false"
+      :query-params="businessUserQueryParams"
+      @save="getContact" />
+  </el-dialog>
+</template>
+
+<script>
+  import { mapGetters } from 'vuex'
+  import to from 'await-to-js'
+  import contractApi from '@/api/contract'
+  import businessApi from '@/api/proj/business'
+  import ProductTable from './ProductTable'
+  import SelectCtrContract from '@/components/select/SelectCtrContract'
+  import SelectDistributor from '@/components/select/SelectDistributor'
+  import SelectUser from '@/components/select/SelectUser'
+  import SelectProduct from '@/components/select/SelectProduct'
+  import SelectBusinessContact from '@/components/select/SelectBusinessContact'
+  export default {
+    components: {
+      ProductTable,
+      SelectCtrContract,
+      SelectDistributor,
+      SelectUser,
+      SelectProduct,
+      SelectBusinessContact,
+    },
+    props: {
+      businessData: {
+        type: Array,
+        default: () => [],
+      },
+    },
+    data() {
+      return {
+        stepActive: 0, //步骤
+        title: '新增客户信息',
+        editVisible: false,
+        editForm: {
+          contractId: null, //关联合同id
+          renewContractName: '', //关联合同
+          contractCode: '', //合同编号
+          contractName: '', //合同名称
+          contractType: '', //合同类型
+          nboId: null, //项目id
+          nboName: '', //项目名称
+          custName: '', // 客户名称
+          inchargeId: null, //销售工程师
+          inchargeName: '', //销售工程师姓名
+          signatoryType: '',
+          signatoryUnit: '',
+          earnestMoney: 0,
+          contractStartTime: '', //合同开始时间
+          contractEndTime: '', //合同结束时间
+          contractSignTime: '', //合同签订时间
+          signatoryName: '', //公司签约人
+          signatoryId: null, //公司签约人id
+          distributorId: null, //经销商id
+          distributorName: '', //经销商name
+          custSignatoryId: null, //客户签约人id
+          custSignatoryName: '', //客户签约人name
+          remark: '', //备注
+          serviceFeeAgreement: '', // 运维服务费约定
+          softwareMaintenanceBeginTime: '',
+          softwareMaintenanceEndTime: '',
+          hardwareMaintenanceBeginTime: '',
+          hardwareMaintenanceEndTime: '',
+          softwareMaintenanceLimit: 1, // 软件运维期限(年)
+          hardwareMaintenanceLimit: 1, // 硬件运维期限(年)
+          maintenanceClause: '', // 运维条款
+        },
+        editRules: {
+          contractName: [{ required: true, trigger: 'blur', message: '请输入合同名称' }],
+          contractType: [{ required: true, trigger: 'change', message: '请选择合同类型' }],
+          signatoryType: [{ required: true, trigger: 'change', message: '请选择签订单位类型' }],
+          signatoryUnit: [{ required: true, trigger: 'change', message: '请选择合同签订单位' }],
+          nboName: [{ required: true, trigger: 'change', message: '请选择关联项目' }],
+          contractStartTime: [
+            { required: true, trigger: 'change', validator: this.pickerOptionsStart, message: '请选择开始时间' },
+          ],
+          contractEndTime: [{ trigger: 'change', validator: this.pickerOptionsEnd, message: '请选择结束时间' }],
+          contractSignTime: [
+            { required: true, trigger: 'change', validator: this.pickerOptionsSign, message: '请选择签订时间' },
+          ],
+          inchargeId: [{ required: true, trigger: 'change', message: '请选择销售工程师' }],
+          signatoryName: [{ required: true, trigger: 'change', message: '请选择公司签约人' }],
+          distributorName: [{ trigger: 'change', message: '请选择经销商' }],
+          softwareMaintenanceLimit: [{ required: true, trigger: 'change', message: '请输入软件运维期限' }],
+          hardwareMaintenanceLimit: [{ required: true, trigger: 'change', message: '请输入硬件运维期限' }],
+          maintenanceClause: [{ required: true, trigger: 'blur', message: '请输入运维条款' }],
+          softwareMaintenanceBeginTime: [{ required: true, trigger: 'blur', message: '请选择软件运维开始时间' }],
+          softwareMaintenanceEndTime: [{ required: true, trigger: 'blur', message: '请选择软件运维结束时间' }],
+          hardwareMaintenanceBeginTime: [{ required: true, trigger: 'blur', message: '请选择硬件运维开始时间' }],
+          hardwareMaintenanceEndTime: [{ required: true, trigger: 'blur', message: '请选择硬件运维结束时间' }],
+        },
+        pickerOptionsStart: {
+          disabledDate: (time) => {
+            let endDateVal = this.editForm.contractEndTime
+            if (endDateVal) {
+              return time.getTime() > new Date(endDateVal).getTime()
+            }
+          },
+        },
+        pickerOptionsEnd: {
+          disabledDate: (time) => {
+            let beginDateVal = this.editForm.contractStartTime
+            if (beginDateVal) {
+              return time.getTime() < new Date(beginDateVal).getTime() - 1 * 24 * 60 * 60 * 1000
+            }
+          },
+        },
+        softwarePickerOptionsStart: {
+          disabledDate: (time) => {
+            let endDateVal = this.editForm.softwareMaintenanceEndTime
+            if (endDateVal) {
+              return time.getTime() > new Date(endDateVal).getTime()
+            }
+          },
+        },
+        softwarePickerOptionsEnd: {
+          disabledDate: (time) => {
+            let beginDateVal = this.editForm.softwareMaintenanceBeginTime
+            if (beginDateVal) {
+              return time.getTime() < new Date(beginDateVal).getTime() - 1 * 24 * 60 * 60 * 1000
+            }
+          },
+        },
+        hardwarePickerOptionsStart: {
+          disabledDate: (time) => {
+            let endDateVal = this.editForm.hardwareMaintenanceEndTime
+            if (endDateVal) {
+              return time.getTime() > new Date(endDateVal).getTime()
+            }
+          },
+        },
+        hardwarePickerOptionsEnd: {
+          disabledDate: (time) => {
+            let beginDateVal = this.editForm.hardwareMaintenanceBeginTime
+            if (beginDateVal) {
+              return time.getTime() < new Date(beginDateVal).getTime() - 1 * 24 * 60 * 60 * 1000
+            }
+          },
+        },
+        pickerOptionsSign: {
+          disabledDate: (time) => {
+            return time.getTime() > new Date().getTime()
+          },
+        },
+        contractOptions: [], //合同类型
+        signatoryOptions: [
+          {
+            key: '10',
+            value: '终端用户',
+          },
+          {
+            key: '20',
+            value: '经销商',
+          },
+          {
+            key: '30',
+            value: '代理商',
+          },
+        ], //合同类型
+        productData: [],
+        multiple: false,
+        property: '',
+        label: '',
+        businessUserQueryParams: {}, //查询客户签约人参数
+      }
+    },
+    computed: {
+      ...mapGetters({
+        userId: 'user/id',
+        username: 'user/username',
+      }),
+    },
+    mounted() {
+      this.getOptions()
+    },
+    methods: {
+      getOptions() {
+        Promise.all([this.getDicts('contract_type')])
+          .then(([contract]) => {
+            this.contractOptions = contract.data.values || []
+          })
+          .catch((err) => console.log(err))
+      },
+      async init(id) {
+        if (this.businessData[0]) this.getBusinessInfo(this.businessData)
+        if (!id) {
+          this.title = '新增合同信息'
+          // 设置销售工程师默认为当前用户
+          // this.editForm.inchargeId = this.userId
+          // this.editForm.inchargeName = this.nickName
+          this.editForm.signatoryId = this.userId
+          this.editForm.signatoryName = this.nickName
+        } else {
+          this.title = '编辑合同'
+          const [err, res] = await to(contractApi.getDetails({ id }))
+          if (err) return
+          if (res.data) {
+            // eslint-disable-next-line no-unused-vars
+            let { product, ...data } = res.data
+            this.editForm = data
+            this.businessUserQueryParams = { busId: data.nboId, custId: data.custId }
+            this.productData =
+              product.length > 0
+                ? product.map((item) => ({
+                    prodCode: item.prodCode,
+                    id: item.prodId,
+                    prodName: item.prodName,
+                    prodClass: item.prodClass,
+                    guidPrice: item.sugSalesPrice,
+                    price: item.tranPrice,
+                    count: item.prodNum,
+                  }))
+                : []
+
+            const [err, resp] = await to(contractApi.getDetails({ id: data.contractId }))
+            if (err) return
+            if (resp.data) {
+              this.editForm.renewContractName = resp.data.contractName
+            }
+          }
+        }
+        this.editVisible = true
+      },
+      // 修改步骤
+      async setStep(step) {
+        if (step == 1) {
+          const [valid] = await to(this.$refs.editForm.validate())
+          if (valid == false) return
+        }
+        this.stepActive = step
+      },
+      // 打开选择项目
+      openProject() {
+        this.$refs.project.open()
+      },
+      signatoryTypeChange() {
+        // 10: '终端用户'
+        // 20: '经销商'
+        // 30: '代理商'
+        if (this.editForm.signatoryType == '10') {
+          this.editForm.signatoryUnit = this.editForm.custName
+        }
+        if (this.editForm.signatoryType == '20') {
+          this.editForm.signatoryUnit = this.editForm.distributorName
+        }
+        // 现在还没有代理商
+        if (this.editForm.signatoryType == '30') {
+          this.editForm.signatoryUnit = this.editForm.distributorName
+        }
+      },
+      // 获取合同信息
+      async getBusinessInfo(data) {
+        let business = data[0] || null
+        if (!business) return
+        console.log(business, 'business')
+        // 获取合同信息
+        const [err, res] = await to(contractApi.getDetails({ id: business.id }))
+        if (err) return
+        if (res.data) {
+          // eslint-disable-next-line no-unused-vars
+          let { product, ...data } = res.data
+          this.editForm = data
+          this.editForm.renewContractName = data.contractName
+          this.editForm.contractId = business.id
+
+          this.editForm.id = null
+          this.editForm.contractCode = ''
+          this.editForm.contractEndTime = ''
+          this.businessUserQueryParams = { busId: data.nboId, custId: data.custId }
+          this.productData =
+            product.length > 0
+              ? product.map((item) => ({
+                  prodCode: item.prodCode,
+                  id: item.prodId,
+                  prodName: item.prodName,
+                  prodClass: item.prodClass,
+                  guidPrice: item.sugSalesPrice,
+                  price: item.tranPrice,
+                  count: item.prodNum,
+                }))
+              : []
+        }
+        this.signatoryTypeChange()
+      },
+      // 打开选择经销商
+      openDistributor() {
+        this.$refs.distributor.open()
+      },
+      // 关闭经销商获取经销商信息
+      getDistributor(data) {
+        let distributor = data[0] || null
+        if (!distributor) return
+        this.editForm.distributorName = distributor.distName
+        this.editForm.distributorId = distributor.id
+        this.signatoryTypeChange()
+      },
+      // 打开选择公司签约人
+      openUser(multiple, property, label) {
+        this.multiple = multiple
+        this.property = property
+        this.label = label
+        if (this.editForm[property].length) {
+          this.$refs.user.ids = this.editForm[property]
+        } else if (this.editForm[property]) {
+          this.$refs.user.ids = [this.editForm[property]]
+        } else {
+          this.$refs.user.ids = []
+        }
+        this.$refs.user.open()
+      },
+      // 获取签约人信息
+      getUser(userList, property, label) {
+        this.editForm[label] = userList.map((item) => item.nickName).join()
+        if (this.multiple) {
+          this.editForm[property] = userList.map((item) => item.id)
+        } else {
+          this.editForm[property] = userList[0] ? userList[0].id : ''
+        }
+        this.$forceUpdate()
+      },
+      // 打开选择公司签约人
+      openContact() {
+        this.$refs.contact.open()
+      },
+      // 获取签约人信息
+      getContact(data) {
+        let user = data[0] || null
+        if (!user) return
+        this.editForm['custSignatoryName'] = user.cuctName
+        this.editForm['custSignatoryId'] = user.id
+      },
+      // 获取产品信息
+      getProduct(data) {
+        // 重构产品数据结构
+        if (data.length > 0) this.setProductData(data)
+      },
+      // 根据项目id获取产品信息
+      async getProjectInfo(id) {
+        let params = { id }
+        const [err, res] = await to(businessApi.getProductByBusinessId(params))
+        if (err) return
+        if (res.data && res.data.length > 0) this.setProductData(res.data)
+      },
+      setProductData(data) {
+        let projData = data.map((item) => ({
+          id: item.prodId ? item.prodId : item.id,
+          prodName: item.prodName,
+          prodCode: item.prodCode,
+          prodClass: item.prodClass,
+          guidPrice: item.guidPrice,
+          count: item.prodNum,
+          price: item.prodPrice ? item.prodPrice : item.guidPrice,
+        }))
+        this.productData.push(...projData)
+        this.productData = this.removeDuplicateObj(this.productData)
+      },
+      // 数组对象去重
+      removeDuplicateObj(arr) {
+        let obj = {}
+        arr = arr.reduce((newArr, next) => {
+          obj[next.id] ? '' : (obj[next.id] = true && newArr.push(next))
+          return newArr
+        }, [])
+        return arr
+      },
+      // 修改产品列表数据
+      changeProductData(data) {
+        this.productData = this.productData.map((item) => {
+          return item.id === data.id ? data : item
+        })
+      },
+      delProductData(data) {
+        this.productData = this.productData.filter((item) => item.id != data.id)
+      },
+      // 保存合同
+      async contractSave() {
+        let product = this.productData.map((item) => ({
+          prodId: item.id,
+          prodNum: parseInt(item.count),
+          maintTerm: 1,
+          sugSalesPrice: item.guidPrice,
+          tranPrice: item.price,
+          remark: '',
+        }))
+        let params = Object.assign({ ...this.editForm }, { product })
+        if (product.length == 0) return this.$message.warning('请选择产品信息')
+        const [err, res] = await to(contractApi.reNewContract(params))
+        if (err) return
+        if (res.code == 200) this.$message.success(res.msg)
+        else return
+        this.editVisible = false
+        this.$emit('contractSave')
+      },
+      // 编辑合同
+      async contractEdit() {
+        let product = this.productData.map((item) => ({
+          prodId: item.id,
+          prodNum: parseInt(item.count),
+          maintTerm: 1,
+          sugSalesPrice: item.guidPrice,
+          tranPrice: item.price,
+          remark: '',
+        }))
+        let params = Object.assign({ ...this.editForm }, { product })
+        if (product.length == 0) return this.$message.warning('请选择产品信息')
+        const [err, res] = await to(contractApi.updateReNew(params))
+        if (err) return
+        if (res.code == 200) this.$message.success(res.msg)
+        else return
+        this.editVisible = false
+        this.$emit('contractSave')
+      },
+      handleClose() {
+        this.editForm = {
+          contractCode: '', //合同编号
+          contractName: '', //合同名称
+          contractType: '', //合同类型
+          nboId: null, //项目id
+          nboName: '', //项目名称
+          custName: '', // 客户名称
+          inchargeId: null, //销售工程师
+          inchargeName: '', //销售工程师名称
+          signatoryType: '',
+          contractStartTime: '', //合同开始时间
+          contractEndTime: '', //合同结束时间
+          signatoryName: '', //公司签约人
+          signatoryId: null, //公司签约人id
+          distributorId: null, //经销商id
+          distributorName: '', //经销商name
+          remark: '', //备注
+          serviceFeeAgreement: '', //运维服务费约定
+          softwareMaintenanceLimit: 1, // 软件运维期限(年)
+          hardwareMaintenanceLimit: 1, // 硬件运维期限(年)
+          maintenanceClause: '', // 运维条款
+        }
+        this.productData = []
+        this.stepActive = 0
+        this.businessUserQueryParams = {}
+        this.$refs.editForm.resetFields()
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  $base: '.edit-container';
+  #{$base} {
+    .mb10 {
+      margin-bottom: 10px;
+    }
+    .proj-col {
+      text-align: right;
+    }
+    // 进度条样式
+    // ::v-deep .el-steps {
+    //   .el-step__line {
+    //     top: 17px;
+    //   }
+    //   .el-step__icon {
+    //     width: 35px;
+    //     height: 35px;
+    //     font-size: 18px;
+    //   }
+    //   .is-process {
+    //     .el-step__icon {
+    //       background: #2e51ff;
+    //       color: #fff;
+    //       border-color: #2e51ff;
+    //     }
+    //   }
+    // }
+  }
+</style>

+ 28 - 0
src/views/contract/detail.vue

@@ -67,6 +67,13 @@
           <el-tab-pane label="分成信息" name="share">
             <details-share v-if="activeName == 'share'" :details="details" :shares="shares" />
           </el-tab-pane>
+          <el-tab-pane label="续签合同" name="renew">
+            <DetailRenew
+              v-if="activeName == 'renew'"
+              :details="details"
+              :renew-list="renewList"
+              @productUpdate="init" />
+          </el-tab-pane>
         </el-tabs>
       </div>
       <div class="info-side">
@@ -97,6 +104,7 @@
   import contractApi from '@/api/contract'
   import DetailsInfo from './components/DetailsInfo'
   import DetailsProduct from './components/DetailsProduct'
+  import DetailRenew from './components/DetailsRenew.vue'
   import DetailsCollection from './components/DetailsCollection'
   import DetailsRecords from './components/DetailsRecords'
   import DetailsInvoice from './components/DetailsInvoice'
@@ -119,6 +127,7 @@
       DetailsShare,
       Edit,
       Transfer,
+      DetailRenew,
     },
     data() {
       return {
@@ -129,6 +138,7 @@
         activeName: 'details',
         dynamicsList: [],
         shares: [],
+        renewList: [],
       }
     },
     computed: {
@@ -142,6 +152,7 @@
       this.init()
       this.getShares()
       this.getRecord()
+      this.getRenew()
     },
     methods: {
       async init() {
@@ -162,6 +173,15 @@
           this.shares = list
         }
       },
+      // 获取续签合同
+      async getRenew() {
+        const [err, res] = await to(contractApi.renewList({ contractId: this.id }))
+        if (err) return
+        if (res.data) {
+          let list = res.data
+          this.renewList = list
+        }
+      },
       scale(numer1, numer2) {
         if (numer2 == 0) {
           return '-'
@@ -176,10 +196,18 @@
           const keys = Object.keys(obj).reverse()
           let records = {}
           for (const item of keys) {
+            if (obj[item].length > 0) {
+              obj[item].forEach((record) => {
+                if (record.opnContent) {
+                  record.opnContent = JSON.parse(record.opnContent)
+                }
+              })
+            }
             records[item] = obj[item]
           }
 
           this.dynamicsList = records
+          console.log('records========================================================', records)
         }
       },
       async handleEdit() {

+ 30 - 10
src/views/contract/index.vue

@@ -85,36 +85,36 @@
           <el-form-item prop="softwareMaintenanceBeginTime">
             <el-date-picker
               v-model="queryForm.softwareMaintenanceBeginTime"
-              end-placeholder="软件运维时间开始"
+              end-placeholder="软件运维开始时间结束"
               range-separator="至"
-              start-placeholder="软件运维时间开始"
+              start-placeholder="软件运维开始时间开始"
               type="daterange"
               value-format="yyyy-MM-dd" />
           </el-form-item>
           <el-form-item prop="softwareMaintenanceEndTime">
             <el-date-picker
               v-model="queryForm.softwareMaintenanceEndTime"
-              end-placeholder="软件运维时间结束"
+              end-placeholder="软件运维结束时间结束"
               range-separator="至"
-              start-placeholder="软件运维时间结束"
+              start-placeholder="软件运维结束时间开始"
               type="daterange"
               value-format="yyyy-MM-dd" />
           </el-form-item>
           <el-form-item prop="hardwareMaintenanceBeginTime">
             <el-date-picker
               v-model="queryForm.hardwareMaintenanceBeginTime"
-              end-placeholder="硬件运维时间开始"
+              end-placeholder="硬件运维开始时间结束"
               range-separator="至"
-              start-placeholder="硬件运维时间开始"
+              start-placeholder="硬件运维开始时间开始"
               type="daterange"
               value-format="yyyy-MM-dd" />
           </el-form-item>
           <el-form-item prop="hardwareMaintenanceEndTime">
             <el-date-picker
               v-model="queryForm.hardwareMaintenanceEndTime"
-              end-placeholder="硬件运维时间结束"
+              end-placeholder="硬件运维结束时间结束"
               range-separator="至"
-              start-placeholder="硬件运维时间结束"
+              start-placeholder="硬件运维结束时间开始"
               type="daterange"
               value-format="yyyy-MM-dd" />
           </el-form-item>
@@ -130,6 +130,13 @@
         <el-button v-permissions="['contract:manage:add']" icon="el-icon-plus" type="primary" @click="handleEdit()">
           新建
         </el-button>
+        <el-button
+          v-permissions="['contract:manage:add']"
+          icon="el-icon-plus"
+          type="primary"
+          @click="handleRenewEdit()">
+          续签
+        </el-button>
         <el-button
           v-permissions="['contract:manage:transfer']"
           icon="el-icon-refresh"
@@ -259,6 +266,7 @@
       @size-change="handleSizeChange" />
     <!-- 新增编辑客户弹窗 -->
     <Edit ref="edit" @contractSave="contractSave" />
+    <RenewEdit ref="renewEdit" @contractSave="contractSave" />
     <!-- 转移合同 -->
     <Transfer ref="transfer" :contract-id="contractId" @transferSave="contractSave" />
     <ApplyContract ref="applyContract" @refresh="queryData" />
@@ -269,10 +277,12 @@
   import to from 'await-to-js'
   import contractApi from '@/api/contract'
   import Edit from './components/Edit'
+  import RenewEdit from './components/RenewEdit'
   import TableTool from '@/components/table/TableTool'
   import Transfer from './components/Transfer'
   import ApplyContract from './components/ApplyContract'
   import api from '@/api/customer'
+  import downloadFileByByte from '@/utils/base64ToFile'
 
   export default {
     name: 'Contract',
@@ -281,6 +291,7 @@
       TableTool,
       Transfer,
       ApplyContract,
+      RenewEdit,
     },
     data() {
       return {
@@ -543,7 +554,8 @@
         }
         const [err, res] = await to(contractApi.exportMaintenance(params))
         if (err) return (this.listLoading = false)
-        window.open(res.data)
+        downloadFileByByte(res.data, '项目运维信息.xlsx')
+        // window.open(res.data)
       },
       handleApply(row) {
         this.$refs.applyContract.form.id = row.id
@@ -573,7 +585,15 @@
       },
       // 客户编辑
       async handleEdit(row = null) {
-        row ? this.$refs.edit.init(row.id) : this.$refs.edit.init()
+        if (row && row.contractId) {
+          this.$refs.renewEdit.init(row.id)
+        } else {
+          row ? this.$refs.edit.init(row.id) : this.$refs.edit.init()
+        }
+      },
+      // 客户编辑
+      async handleRenewEdit() {
+        this.$refs.renewEdit.init()
       },
       // 合同详情
       handleContractDetail(row) {