Explorar o código

合同管理-合同列表

hbchen hai 1 ano
pai
achega
8e6aa39afc

+ 2 - 0
package.json

@@ -17,11 +17,13 @@
     "element-plus": "2.4.4",
     "froala-editor": "^4.1.4",
     "highcharts": "11.2.0",
+    "html2canvas": "1.1.4",
     "jquery": "^3.7.1",
     "js-md5": "^0.8.3",
     "lodash": "^4.17.21",
     "moment": "^2.30.1",
     "pinia": "^2.1.7",
+    "v-distpicker": "2.1.0",
     "vue": "^3.4.19",
     "vue-froala-wysiwyg": "^4.1.4",
     "vue-router": "^4.3.0",

+ 32 - 0
src/hooks/mixins/index.js

@@ -0,0 +1,32 @@
+// 从原项目的 @/mixins/index.js 提取出来(有用到的)
+
+import http from "@/api/http";
+// 显示时间为 2021.07.22 
+export function formatter(row,column,cellvalue){
+  return cellvalue ? http.dateFormatter(cellvalue) : '';
+}
+
+// 显示时间为 2021.07.22 
+export function formatTime(time){
+  if(time==='0001-01-01 00:00:00'||time==='0000-00-00 00:00:00'){
+    return '--'
+  }else{
+    return time.replace(/-/g,'.')
+  }
+}
+
+//  格式化金额 三位一个逗号
+export function formatPriceHasPoint(e){
+  let str=e.toString()
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  return num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}

+ 5 - 0
src/main.js

@@ -26,11 +26,16 @@ import 'froala-editor/css/froala_style.min.css';
 
 import VueFroala from 'vue-froala-wysiwyg';
 
+import {registerComponents} from "@/utils/registryComponents"
+
 function setupApp() {
   const app = createApp(App)
   initStore(app)
 
   initRouter(app)
+  
+  // 注册全局组件
+  registerComponents(app)
 
   app.use(ElementPlus,{locale: zhCn})
   app.use(vue3TreeOrg)

+ 163 - 0
src/router/modules/contractRoutes.js

@@ -0,0 +1,163 @@
+//合同管理路由模块
+import Home from '@/layouts/index.vue'
+
+export default [
+    {
+		path: '/',
+		component: Home,
+		name: 'contractManage',
+		meta: {
+			title: "合同管理",
+		},
+		icon_path: require('@/assets/img/home/custom_ico.png'),
+		children: [
+			{
+				path: 'contractmanagelist',
+				name: 'contractmanagelist',
+				component: () => import('@/views/contract_manage/contractList.vue'),
+				meta: {
+					title: "合同列表",
+				},
+			},
+			{
+				path: 'addcontract',
+				component: () => import('@/views/contract_manage/addContract.vue'),
+				name: "addcontract",
+				meta: {
+					title: "添加合同",
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+				}
+			},
+			{
+				path: 'contractdetail',
+				component: () => import('@/views/contract_manage/contractDetail.vue'),
+				name: "contractdetail",
+				meta: {
+					title:'合同详情',
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表'
+				}
+			},
+			{
+				path: 'editcontract',
+				component: () => import('@/views/contract_manage/editContract.vue'),
+				name: "editcontract",
+				hidden: false,
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title:'编辑合同'
+				}
+			},
+			{
+				path: 'retrialcontract',
+				component: () => import('@/views/contract_manage/editContract.vue'),
+				name: "retrialcontract",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title:"重审合同"
+				}
+			},
+			{
+				path: 'copycontract',
+				component: () => import('@/views/contract_manage/editContract.vue'),
+				name: "copycontract",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title:'复制模板'
+				}
+			},
+			{
+				path: 'modifyapply',
+				component: () => import('@/views/contract_manage/editContract.vue'),
+				name: "modifyapply",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title:'修改重审'
+				}
+			},
+			{
+				path: 'addcontractdc',
+				component: () => import('@/views/contract_manage/addContractDC.vue'),
+				name: "addcontractdc",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title: '添加代付合同'
+				}
+			},
+			{
+				path: 'contractdetaildc',
+				component: () => import('@/views/contract_manage/contractDetailDC.vue'),
+				name: "contractdetaildc",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title: '代付合同详情'
+				}
+			},
+			{
+				path: 'editcontractdc',
+				component: () => import('@/views/contract_manage/editContractDC.vue'),
+				name: "editcontractdc",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title: '代付合同编辑'
+				}
+			},
+			{
+				path: 'retrialcontractdc',
+				component: () => import('@/views/contract_manage/editContractDC.vue'),
+				name: "retrialcontractdc",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title: '代付合同重审'
+				}
+			},
+			{
+				path: 'copycontractdc',
+				component: () => import('@/views/contract_manage/editContractDC.vue'),
+				name: "copycontractdc",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title: '代付合同复制模板'
+				}
+			},
+			{
+				path: 'modifyapplydc',
+				component: () => import('@/views/contract_manage/editContractDC.vue'),
+				name: "modifyapplydc",
+				meta: {
+					pathFrom: 'contractmanagelist',
+					pathName: '合同列表',
+					title: '代付合同修改重审'
+				}
+			},
+			// {
+			// 	path:"raiAllocationPage",
+			// 	component:()=>import("@/views/contract_manage/raiAllocationPage.vue"),
+			// 	name:"合同派点",
+			// 	hidden:false,
+			// 	meta: {
+			// 		keepAlive: false
+			// 	}
+			// },
+			// {
+			// 	path:"researcherStatistics",
+			// 	component:()=>import("@/views/contract_manage/researcherStatistics.vue"),
+			// 	name:"研究员派点统计",
+			// 	hidden:false,
+			// 	meta: {
+			// 		keepAlive: false
+			// 	}
+			// }
+		]
+	},
+]

+ 35 - 31
src/utils/registryComponents.js

@@ -1,32 +1,36 @@
-import Vue from 'vue';
-
-//地区选择
 import VDistpicker from 'v-distpicker'
-Vue.component('v-distpicker', VDistpicker)
-
-//日期选择
-import DatePicker from 'vue2-datepicker';
-import 'vue2-datepicker/index.css';
-import 'vue2-datepicker/locale/zh-cn';
-Vue.component('date-picker',DatePicker)
-
-//指标搜索浮动显示详情popover
-import edbDetailPopover from '@/components/edbDetailPopover.vue';
-Vue.component('edbDetailPopover',edbDetailPopover)
-
-//指标添加 单位
-import selectUnit from '@/components/selectUnit.vue'
-Vue.component('selectUnit',selectUnit)
-
-//查看指标历史
-import edbHistoryDialog from '@/components/edbHistoryDialog.vue';
-Vue.component('edbHistoryDialog',edbHistoryDialog);
-
-/* 很多图表模块列表页基本类似 慢慢抽离替换 */
-//列表
-import chartListWrap from '@/components/chart/chartListWrap.vue'
-Vue.component('chartListWrap',chartListWrap)
-
-//详情图表操作
-import chartDetailHandlesWrap from '@/components/chart/chartDetailHandlesWrap.vue'
-Vue.component('chartHandlesWrap',chartDetailHandlesWrap)
+
+// import DatePicker from 'vue2-datepicker';
+// import 'vue2-datepicker/index.css';
+// import 'vue2-datepicker/locale/zh-cn';
+
+// import edbDetailPopover from '@/components/edbDetailPopover.vue';
+// import selectUnit from '@/components/selectUnit.vue'
+// import edbHistoryDialog from '@/components/edbHistoryDialog.vue';
+// import chartListWrap from '@/components/chart/chartListWrap.vue'
+// import chartDetailHandlesWrap from '@/components/chart/chartDetailHandlesWrap.vue'
+
+export function registerComponents(app){
+  //地区选择
+  app.component('v-distpicker', VDistpicker)
+
+  //日期选择
+
+  // app.component('date-picker',DatePicker)
+
+  //指标搜索浮动显示详情popover
+  // app.component('edbDetailPopover',edbDetailPopover)
+
+  //指标添加 单位
+  // app.component('selectUnit',selectUnit)
+
+  //查看指标历史
+  // app.component('edbHistoryDialog',edbHistoryDialog);
+
+  /* 很多图表模块列表页基本类似 慢慢抽离替换 */
+  //列表
+  // app.component('chartListWrap',chartListWrap)
+
+  //详情图表操作
+  // app.component('chartHandlesWrap',chartDetailHandlesWrap)
+}

+ 986 - 0
src/views/contract_manage/addContract.vue

@@ -0,0 +1,986 @@
+
+<script setup>
+import { ref,reactive,computed,watch } from "vue";
+import {ElMessage,ElMessageBox} from "element-plus"
+import { useRouter} from 'vue-router';
+import _ from 'lodash'
+import { InfoFilled } from '@element-plus/icons-vue'
+
+import { contractInterface,customInterence } from "@/api/api.js";
+import{province_sorce,city_sorce} from '@/utils/distpicker';
+import ServiceDialog from "./components/ServiceDialog.vue"; //套餐内容弹窗组件
+import QyServiceTable from "./components/QyServiceTable.vue"; //权益服务内容表格组件
+import FiccServiceTable from "./components/FiccServiceTable.vue"; //ficc服务内容表格组件
+import {CalculationDate} from '@/utils/CalculationDate.js'
+
+const $router = useRouter()
+
+const province_sorce_value=province_sorce
+const city_sorce_value=city_sorce
+
+const contractTypeDisable1=ref(false) //能否选择新签合同
+const contractTypeDisable2=ref(false) //能否选择续约合同
+const contractTypeDisable3=ref(false) //能否选择补充协议
+const timeDisable=ref(false)
+const cusLastcontract=ref(null)
+const temContractCode=ref(null)//临时生成的合同编号
+const RoleType=ref(localStorage.getItem("Role") || "")
+const radio=ref('2')//是否有补充内容 1有 2 无
+const formData=reactive({
+  constractType: null, //合同类型
+  time: [],
+  price: "",
+  price2: "",
+  payRemark: "",
+  customeName: "",
+  customeXYM: "",
+  customeCz: "",
+  customeTel: "",
+  postCode: "",
+  province: "",
+  city: "",
+  address: "",
+  remark: "",
+  sellerRemark:'',
+  PayChannel:['无']
+})
+const formRule={
+  constractType: [{ required: true, message: "请选择合同类型", trigger: "change" }],
+  time: [{ required: true, message: "请选择有效期限", trigger: "change" }],
+  price: [
+    { required: true, message: "请填写合同金额", trigger: "blur" },
+    // { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: "请输入正确的格式,可保留两位小数" },
+  ],
+  payRemark: [{ required: true, message: "请填写付款方式说明", trigger: "blur" }],
+  customeName: [{ required: true, message: "请填写名称", trigger: "blur" }],
+  customeXYM: [{ required: true, message: "请填写信用码", trigger: "blur" }],
+  province: [{ required: true, message: "请选择地址", trigger: "change" }],
+  remark: [{ required: false, message: "请填写补充说明", trigger: "blur" }],
+  PayChannel:[{ required: true, message: "请填写付款方", trigger: "change" }],
+  customeTel:[{ required: true, message: "请填写电话", trigger: "change" }],
+  address:[{ required: true, message: "请填写详细地址", trigger: "change" }],
+}
+const ficcServiceData=ref([])//ficc服务内容
+const qyServiceData=ref([])//权益服务内容
+const serviceShow=ref(false)
+const serviceCon=ref({})//选择的服务项 查看报价单/选择品种
+const selectServiceData=ref([])
+const editValue=ref({})//修改小套餐的value
+const PayChannelOptions=ref([])//搜索出付款方列表
+
+const pickerOptions=computed(()=>{
+  let obj={disabledDate() {return false}}
+  if(cusLastcontract.value){
+    if(formData.constractType==='续约合同'&&RoleType.value==='ficc_seller'){
+      // ficc 起始日期为权限中最大的时间
+      formData.time=[]
+      let timearr=cusLastcontract.value.map(item=> item.EndDate)
+      let maxTime=Math.max.apply(null, timearr.map(item => (new Date(item)).getTime()));
+      let endDate=formatDate(new Date(maxTime))
+      console.log(endDate);
+      obj={
+        disabledDate(time) {
+          return time.getTime() < new Date(endDate).getTime();
+        }
+      }
+    }else{
+      obj={
+        disabledDate() {
+            return false
+          }
+      }
+    }
+    if(formData.constractType==='补充协议'){
+      let today=formatDate(new Date())
+      // 找出权限中最晚截止的那个作为截至日期
+      let timearr=cusLastcontract.value.map(item=> item.EndDate)
+      let maxTime=Math.max.apply(null, timearr.map(item => (new Date(item)).getTime()));
+      let endDate=formatDate(new Date(maxTime))
+      formData.time=[today,endDate]
+      timeDisable.value=true
+      obj={disabledDate() {return true}}
+    }else{
+      timeDisable.value=false
+    }
+  }
+  
+  return obj
+})
+
+const formItemRemark=ref(null)
+
+watch(radio,(nval, oval)=>{
+  formItemRemark.value.resetField();
+  if (nval === "1") {
+    formRule.remark[0].required = true;
+  } else {
+    formRule.remark[0].required = false;
+  }
+})
+
+// filters
+// 金额转中文大写
+const digitUppercase=(n)=>{
+  if (n) {
+    n=n.replace(/,/g,'')
+    let fraction = ["角", "分"];
+    let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+    let unit = [
+      ["元", "万", "亿"],
+      ["", "拾", "佰", "仟"],
+    ];
+    let head = n < 0 ? "欠" : "";
+    n = Math.abs(n);
+    let s = "";
+    for (let i = 0; i < fraction.length; i++) {
+      s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, "");
+    }
+    // s = s || "整";
+
+    n = Math.floor(n);
+    for (let i = 0; i < unit[0].length && n > 0; i++) {
+      let p = "";
+      for (let j = 0; j < unit[1].length && n > 0; j++) {
+        p = digit[n % 10] + unit[1][j] + p;
+        n = Math.floor(n / 10);
+      }
+      s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s;
+    }
+    return (
+      "大写:" + (head + s.replace(/(零.)*零元/, "元").replace(/(零.)+/g, "零"))
+      // .replace(/^整$/, "零元整")
+    );
+  }
+}
+
+//计算多少年 X年X个月X天
+const formateYear=(e)=>{
+  if (!e) return;
+  if (e[0]) {
+    return `有效期为${CalculationDate(e[0],e[1])}`
+  }
+}
+
+// 格式化时间
+const formatDate=(date)=>{
+  let year=date.getFullYear()
+  let month=date.getMonth()+1
+  let day=date.getDate()
+  return `${year}-${month<10?'0'+month:month}-${day<10?'0'+day:day}`
+}
+
+// 社会信用码变更
+const getContractByCode=async ()=>{
+  contractTypeDisable1.value=false
+  contractTypeDisable2.value=false
+  contractTypeDisable3.value=false
+  if(!formData.customeXYM) return
+  const res=await contractInterface.getContractTypeByCode({CreditCode:formData.customeXYM})
+  if(res.Ret==200){
+    let customeId=res.Data.Item&&res.Data.Item.CompanyId
+    if(customeId){
+      const res2=await customInterence.applyTurnContractType({CompanyId:customeId}) 
+      formData.constractType=res2.Data.ContractType
+      if(res2.Data.ContractType==='新签合同'){
+        contractTypeDisable1.value=false
+        contractTypeDisable2.value=true
+        contractTypeDisable3.value=true
+      }else{
+        if(RoleType.value==='ficc_seller'){
+          contractTypeDisable1.value=true
+          contractTypeDisable2.value=false
+          contractTypeDisable3.value=false
+        }
+        if(RoleType.value==='rai_seller'){
+          contractTypeDisable1.value=true
+          contractTypeDisable2.value=false
+          contractTypeDisable3.value=true
+        }
+      }
+    }
+  }
+}
+
+
+// 解除搜索选中的客户绑定(需求修改不需要此操作2021-9-16)
+const handleUnbind=()=>{
+  ElMessageBox.confirm('此操作将解除与选择的客户绑定, 是否继续?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    contractTypeDisable1.value=false
+    contractTypeDisable2.value=false
+    contractTypeDisable3.value=false
+    cusLastcontract.value=null
+    timeDisable.value=false
+  }).catch(()=>{
+    console.log('取消解绑');
+  })
+}
+
+// 客户名称搜索框输入变化
+const handleCustomeInputChange=()=>{
+  // 将付款方初始化为客户名称
+  // const flag=this.formData.PayChannel.includes(this.formData.customeName)
+  // if(!flag){
+  //   this.formData.PayChannel.push(this.formData.customeName)
+  // }
+}
+
+// 搜索付款渠道
+// async querySearchAsyncPayChannel(queryString, cb){
+//   cb([])
+//   // if(!queryString) return
+//   let res=await contractInterface.getPayChannel({Keyword:queryString})
+//   if(res.Ret===200){
+//     if(res.Data&&res.Data.length>0){
+//       let arr=res.Data.map(item=>{
+//         return {value:item.PayChannel,...item}
+//       })
+//       cb(arr)
+//     }
+//   }
+// },
+
+// 付款渠道方式修改 多选
+const querySearchAsyncPayChannel=async (query,type)=>{
+  if(!type&&!query) return
+  let res=await contractInterface.getPayChannel({Keyword:query})
+  if(res.Ret===200){
+    PayChannelOptions.value=res.Data||[]
+  }
+}
+
+// 客户搜索
+const querySearchAsyncCustome=async (queryString, cb)=>{
+  cb([])
+  if(!queryString) return
+  let CompanyType=localStorage.getItem('RoleType')
+  let res=await customInterence.customList({KeyWord:queryString,PageSize:10000,CompanyType:CompanyType,IncludeShare:true})
+  // this.contractTypeDisable1=false
+  // this.contractTypeDisable2=false
+  // this.contractTypeDisable3=false
+  // // this.pickerOptions={}
+  // this.cusLastcontract=null
+  // this.timeDisable=false
+  if(res.Ret===200){
+    if(res.Data.List.length>0){
+      let arr=res.Data.List.map(item=>{
+        return {value:item.CompanyName,...item}
+      })
+      cb(arr)
+    }
+  }
+}
+
+//选择客户
+const handleSelectCustome=async (item)=>{
+  // 获取客户详情 更新表单数据
+  let res=await customInterence.customDetail({CompanyId:item.CompanyId})
+  if(res.Ret===200){
+    formData.customeXYM=res.Data.Item.CreditCode
+    formData.province=res.Data.Item.Province
+    formData.city=res.Data.Item.City
+  }
+  // 获取以前的合同自动 填充部分信息
+  let res4=await contractInterface.getHistoryContract({CompanyId:item.CompanyId})
+  if(res4.Ret===200){
+    formData.address=res4.Data.Address||''
+    formData.customeCz=res4.Data.Fax||''
+    formData.customeTel=res4.Data.Phone||''
+    formData.postCode=res4.Data.Postcode||''
+  }
+  // 更新合同类型
+  let res2=await customInterence.applyTurnContractType({CompanyId:item.CompanyId})
+  if(res2.Ret===200){
+    formData.constractType=res2.Data.ContractType
+    if(res2.Data.ContractType==='新签合同'){
+      contractTypeDisable1.value=false
+      contractTypeDisable2.value=true
+      contractTypeDisable3.value=true
+    }else{
+      if(RoleType.value==='ficc_seller'){
+        contractTypeDisable1.value=true
+        contractTypeDisable2.value=false
+        contractTypeDisable3.value=false
+      }
+      if(RoleType.value==='rai_seller'){
+        contractTypeDisable1.value=true
+        contractTypeDisable2.value=false
+        contractTypeDisable3.value=true
+      }
+    }
+  }
+
+  // 获取客户大于今天的最后一份有效合同详情
+  let res3=await customInterence.lastContractInfo({CompanyId:item.CompanyId})
+  if(res3.Ret===200){
+    if(res3.Data&&res3.Data.length>0){
+      cusLastcontract.value=res3.Data
+    }else{
+      cusLastcontract.value=null
+    }
+  }
+}
+
+
+//判断合同期限 不小于一个月
+const validateTime=()=>{
+  if(formData.constractType==='补充协议') return true
+  let start = new Date(formData.time[0]).getTime();
+  let end = new Date(formData.time[1]).getTime();
+  let oneMonth = 1000 * 60 * 60 * 24 * 29;
+  if (end - start >= oneMonth) {
+    return true;
+  } else {
+    ElMessage.warning("合同期限不能小于一个月");
+    return false;
+  }
+}
+
+//判断优惠后金额不能大于合同金额
+const validatePrice=()=>{
+  if (Number(formData.price2) > Number(formData.price)) {
+    ElMessage.warning("优惠后金额不得大于合同金额");
+    return false;
+  } else {
+    return true;
+  }
+}
+
+// 判断小套餐中是否选择品种/新增的行是否有数据
+const validateService=(e,data)=>{
+  if(!e.Value){
+    ElMessage.warning("请保存小套餐");
+    return false
+  }
+  //判断品种列是否有值
+  let arr = [];
+  data.forEach((item) => {
+    item.forEach((item2) => {
+      if (item2.HeadName === "品种") {
+        arr.push(...item2.ValueId);
+      }
+    });
+  });
+  // 判断行是否有值
+  let arr2 = [];
+  data.forEach((item, index) => {
+    let arr = item.filter((item2) => {
+      if (!item2.Value) return item2;
+    });
+    if (arr.length === item.length) {
+      arr2.push(index);
+    }
+  });
+
+  if (!arr.length&&formData.constractType!=='补充协议') {
+    ElMessage.warning("至少选择一个品种");
+    return false;
+  }
+
+  if (arr2.length) {
+    ElMessage.warning("行内至少填一项");
+    return false;
+  }
+
+  return true;
+}
+
+// 生成临时的合同编号
+const createTemContractCode=()=>{
+  let time = new Date();
+  let year = time.getFullYear();
+  let month = time.getMonth() + 1 < 10 ? "0" + (time.getMonth() + 1) : time.getMonth() + 1;
+  let day = time.getDate() < 10 ? "0" + time.getDate() : time.getDate();
+  let timeStr = `${year}${month}${day}`;
+  let random = parseInt(Math.random() * 1000);
+  if (random < 10) {
+    random = `00${random}`;
+  }
+  if (random < 100) {
+    random = `0${random}`;
+  }
+  let typeStr = RoleType.value === "ficc_seller" ? "FICC" : "EQ";
+  temContractCode.value = `HZ${typeStr}${timeStr}${random}`;
+}
+
+//获取服务套餐模板数据
+const getServiceList=()=>{
+  let ProductId = RoleType.value === "ficc_seller" ? 1 : 2;
+  contractInterface.getServiceList({ ProductId }).then((res) => {
+    if (res.Ret === 200) {
+      if (RoleType.value === "ficc_seller") {
+        ficcServiceData.value = res.Data;
+      } else {
+        qyServiceData.value = res.Data;
+      }
+    }
+  });
+}
+
+//显示服务内容弹窗
+const handleShowService=(e)=>{
+  serviceCon.value = e;
+  serviceShow.value = true;
+}
+
+//关闭服务内容弹窗
+const serviceClose=()=>{
+  serviceShow.value = false;
+}
+
+//选地地区时 选则的省份改变重置city为空
+const provinceChange=(e)=>{
+  formData.province =e.value=='省'?'':e.value;
+  // this.formData.city=''
+}
+
+//选择地区
+const selectRegion=(e)=>{
+  formData.province =e.province.value=='省'?'':e.province.value;
+  formData.city = e.city.value=='市'?'':e.city.value;
+}
+
+//小套餐点击保存 更新数据
+const serviceSave=(e)=>{
+  editValue.value = { ServiceTemplateId: e.ServiceTemplateId, Value: e.Value, tableData: e.tableData, tableHeadData: e.tableHeadData };
+
+  // this.ficcServiceData.forEach((item) => {
+  //   if (item.ServiceTemplateId === e.ServiceTemplateId) {
+  //     item.Value = e.Value;
+  //   }
+  // });
+
+  // this.$refs.FiccServiceTable.tableData.forEach(item=>{
+  //   if(item.selected){
+  //     this.selectServiceData.push(item)
+  //   }
+  // })
+  // this.selectServiceData.forEach((item) => {
+  //   if (item.ServiceTemplateId === e.ServiceTemplateId) {
+  //     item.Value = e.Value;
+  //   }
+  // });
+}
+
+const formRef=ref(null)
+const FiccServiceTableRef=ref(null)
+const QyServiceTableRef=ref(null)
+const ServiceDialogRef=ref(null)
+// 预览/存草稿/提交 操作
+const handleSubmit=_.debounce(function(type){
+  formRef.value.validate((valid)=>{
+    if(valid){
+      let temarr = [];
+      if (RoleType.value === "ficc_seller") {
+        console.log(FiccServiceTableRef.value,'FiccServiceTableRef.value',FiccServiceTableRef.value.tableData);
+        FiccServiceTableRef.value.tableData.forEach((item) => {
+          let obj = {
+            ServiceTemplateId: "",
+            Value: "",
+            Detail: [],
+            Title: item.Title,
+            ChartPermissionId:item.ChartPermissionId
+          };
+          obj.ServiceTemplateId = item.ServiceTemplateId;
+          obj.Value = item.Value;
+          if (item.selected) {
+            //小套餐情况
+            if (item.Detail) {
+              obj.Detail = [ServiceDialogRef.value.tableHeadData, ...ServiceDialogRef.value.tableData];
+            }
+            temarr.push(obj);
+          }
+        });
+      } else {
+        // 只要一个分类里面 主观和客观其中一个被勾选 这个分类就要传
+        QyServiceTableRef.value.selectAllArr.map(item =>{
+          if(QyServiceTableRef.value.checkList.find(it => it.indexOf(item.name)!=-1 && it.indexOf("升级")==-1)){
+            temarr.push({
+              ServiceTemplateId: item.ServiceTemplateId,
+              Value: item.value,
+              Detail: null,
+              Title: item.name,
+              ChartPermissionId:item.ChartPermissionId
+            })
+          }
+        })
+        QyServiceTableRef.value.tableData.list.forEach((item) => {
+          let obj = {
+            ServiceTemplateId: "",
+            Value: "",
+            Detail: null,
+            Title: item.Title == item.fatherName ? item.Title:`${item.fatherName}(${item.Title})`,
+            ChartPermissionId:item.ChartPermissionId
+          };
+          obj.ServiceTemplateId = item.ServiceTemplateId;
+          obj.Value = item.Value;
+          let flag = ''
+          if(item.Title == item.fatherName){
+            //没有主客观
+            flag= QyServiceTableRef.value.checkList.indexOf(item.Title);
+          }else{
+            flag= QyServiceTableRef.value.checkList.indexOf(`${item.fatherName}(${item.Title})`);
+          }
+          if (flag !== -1) {
+            temarr.push(obj);
+          }
+        });
+      }
+      // 判断地址
+      if(formData.province!='海外'&&!formData.city){
+        ElMessage.warning('请选择地址')
+        return
+      }
+
+      // 判断合同期限 不小于一个月
+      if (!validateTime()) {
+        return;
+      }
+
+      //判断金额
+      if (!validatePrice()) {
+        return;
+      }
+      //判断是否选择了套餐
+      if (!temarr.length) {
+        ElMessage.warning("请选择套餐");
+        return;
+      }
+
+      //判断小套餐
+      let flag = true;
+      temarr.forEach((item) => {
+        if (item.Detail&&item.Detail.length) {
+          flag = validateService(item,item.Detail.slice(1));
+        }
+      });
+      if (!flag) return;
+
+
+      let params = {
+        ContractType: formData.constractType,
+        ContractBusinessType:"业务合同",
+        StartDate: formData.time[0],
+        EndDate: formData.time[1],
+        OriginalPrice: Number(formData.price.replace(/,/g,'')),
+        Price: Number(formData.price2.replace(/,/g,'')),
+        PayRemark: formData.payRemark,
+        CompanyName: formData.customeName,
+        CreditCode: formData.customeXYM,
+        Province: formData.province,
+        City: formData.city,
+        Address: formData.address,
+        Fax: formData.customeCz,
+        Phone: formData.customeTel,
+        Postcode: formData.postCode,
+        Remark: formData.remark,
+        SellerRemark:formData.sellerRemark,
+        PayChannel:formData.PayChannel.join(','),
+        TemplateId: RoleType.value === "ficc_seller" ? 1 : 2,
+        Service: temarr,
+        IsAudit: type === "提交" ? true : false,
+      };
+
+      // 判断套餐权限
+      if(cusLastcontract.value&&!handleValidate(params)) return
+      
+      if(type==='预览'){
+        handlePreview(params)
+      }else{
+        handleSave(params)
+      }
+    }else{
+      ElMessage.warning('请完善必填项')
+    }
+  })
+},200)
+
+// 判断套餐权限
+const handleValidate=(e)=>{
+  let tag=true
+  let tagsmall=false
+  // ficc 补充协议 不允许有选择过的
+  if(RoleType.value === "ficc_seller"&&e.ContractType==='补充协议'){
+    // 是否选择大套餐 大套餐为全部品种 不能选
+    e.Service.forEach(item=>{
+      // 大套餐
+      if(item.ChartPermissionId===0&&item.ServiceTemplateId===1){
+        tag=false
+        ElMessage.warning('FICC大套餐不可选')
+      }
+      // 小套餐 判断其中ficc周报是否有重复选择的权限
+      if(item.ChartPermissionId===0&&item.ServiceTemplateId===2){
+        let temIdarr=[]
+        item.Detail.forEach(item2=>{
+          item2.forEach(item3=>{
+            if(item3.Value==='FICC周报'){
+              item2.forEach(item4=>{
+                if(item4.HeadName==='品种'){
+                  temIdarr=item4.ValueId
+                }
+              })
+            }
+          })
+        })
+
+        cusLastcontract.value.forEach(item4=>{
+          if(temIdarr.indexOf(item4.ChartPermissionId)!=-1){
+            tag=false
+            tagsmall=true
+          }
+        })
+      }
+
+      // 市场策略
+      if(item.ChartPermissionId!==0){
+        cusLastcontract.value.forEach(item2=>{
+          if(item2.ChartPermissionId===item.ChartPermissionId){
+            ElMessage.warning(`${item.Title}不可选`)
+            tag=false
+          }
+        })
+      }
+    })
+  }
+
+  // 权益 续约合同 
+  if(RoleType.value === "rai_seller"&&e.ContractType==='续约合同'){
+    const time1=new Date(formData.time[0]).getTime()//选择的开始时间
+    const time2=new Date(formData.time[1]).getTime()//选择的结束时间
+    cusLastcontract.value.forEach(item=>{
+      const time3=new Date(item.StartDate).getTime()
+      const time4=new Date(item.EndDate).getTime()
+      if(time1>time4||time2<time3){
+        console.log('选择时间和上一份无重叠');
+      }else{
+        console.log('时间重叠');
+        e.Service.forEach(item2=>{
+          console.log(item2.ChartPermissionId,item.ChartPermissionId);
+          if(item2.ChartPermissionId===item.ChartPermissionId){
+            ElMessage.warning('同行业有重叠的合同期限,请核实后再提交')
+            tag=false
+          }
+        })
+
+      }
+    })
+    
+  }
+
+  // 小套餐统一一个提示
+  if(tagsmall){
+    ElMessage.warning('小套餐中权限重复')
+  }
+  return tag
+}
+
+//前去预览
+const handlePreview=(params)=>{
+  contractInterface.previewContract(params).then((res) => {
+    if (res.Ret === 200) {
+      sessionStorage.setItem("contractdtl", res.Data.Html);
+      let { href } = $router.resolve({ path: "/contractdtl" });
+      window.open(href, "_blank");
+    }
+  });
+}
+
+//保存
+const handleSave=(params)=>{
+  contractInterface.addContract(params).then((res) => {
+    if (res.Ret === 200) {
+      $router.go(-1);
+    }
+  });
+}
+
+// 金额输入框获取焦点
+const handlePriceBoxFocus=(key)=>{
+  let val=formData[key]
+  val=val.replace(/,/g,'')
+  formData[key]=val
+}
+// 金额输入框获失去焦点
+const handlePriceBoxBlur=(key)=>{
+  let str=formData[key]
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  formData[key]=num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+
+createTemContractCode()
+getServiceList()
+// 初始化一次 搜索付款方选择列表
+querySearchAsyncPayChannel('','init')
+</script>
+
+<template>
+  <div class="addconstract-container">
+    <el-form ref="formRef" :model="formData" label-position="left" :rules="formRule" 
+    label-width="110px" size="large">
+      <section class="section">
+        <h2 class="section-title">客户信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="甲方名称" prop="customeName" style="width: 50%">
+              <!-- <el-input v-model="formData.customeName" placeholder="请输入名称" style="width: 350px"></el-input> -->
+              <el-autocomplete
+                v-model="formData.customeName"
+                :fetch-suggestions="querySearchAsyncCustome"
+                placeholder="请输入或者搜索客户名称"
+                @select="handleSelectCustome"
+                @blur="handleCustomeInputChange"
+                style="width: 50%"
+              ></el-autocomplete>
+            </el-form-item>
+            <el-form-item label="社会信用码" prop="customeXYM" style="width: 50%">
+              <el-input v-model="formData.customeXYM" placeholder="请输入社会信用码" style="width: 350px" :disabled="cusLastcontract" @input="getContractByCode"></el-input>
+              <!-- <span style="font-size:14px;color:#4099ef;cursor: pointer;" v-if="cusLastcontract" @click="handleUnbind">解除绑定</span> -->
+            </el-form-item>
+          </div>
+
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item 
+              label="公司地址" 
+              prop="province" 
+              style="width: 50%">
+              <v-distpicker :province="formData.province" :city="formData.city" 
+                :province-source="province_sorce_value"
+                :city-source="city_sorce_value"
+                hide-area @province="provinceChange" @selected="selectRegion"></v-distpicker>
+            </el-form-item>
+            <el-form-item label="详细地址" prop="address" style="width: 50%">
+              <el-input v-model="formData.address" placeholder="请输入详细地址" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="传真" prop="customeCz" style="width: 50%">
+              <el-input v-model="formData.customeCz" placeholder="请输入传真" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="电话" prop="customeTel" style="width: 50%">
+              <el-input v-model="formData.customeTel" placeholder="请输入电话" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+
+          <el-form-item label="邮编" prop="postCode" class="border-top">
+            <el-input v-model="formData.postCode" placeholder="请输入邮编" style="width: 350px"></el-input>
+          </el-form-item>
+        </div>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">合同信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="合同编号" style="width: 50%">
+              <span>{{ temContractCode }}</span>
+            </el-form-item>
+            <el-form-item label="合同归属" style="width: 50%">
+              <span>{{ RoleType === "ficc_seller" ? "FICC" : "权益" }}</span>
+            </el-form-item>
+          </div>
+          <el-form-item label="合同类型" prop="constractType" class="border-top">
+            <el-radio-group v-model="formData.constractType">
+              <div style="display:flex">
+                <div style="margin-right:10px;">
+                  <el-radio label="新签合同" :disabled="contractTypeDisable1">新签合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>没有正式转试用记录的客户,在申请转正时提交的合同</template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right:10px">
+                  <el-radio label="续约合同" :disabled="contractTypeDisable2">续约合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>
+                      1、有正式转试用记录的客户,在申请转正时提交的合同<br>
+										  2、所有客户在续约申请时提交的合同
+                    </template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right:10px" v-if="RoleType!=='rai_seller'">
+                  <el-radio label="补充协议" :disabled="contractTypeDisable3">补充协议</el-radio>
+                </div>
+              </div>
+            </el-radio-group>
+          </el-form-item>
+          <div class="flex border-top">
+            <el-form-item label="合同期限" prop="time" style="width: 50%">
+              <el-date-picker 
+                style="max-width: 350px"
+                v-model="formData.time" 
+                type="daterange" 
+                value-format="YYYY-MM-DD" 
+                range-separator="至" 
+                start-placeholder="开始日期" 
+                end-placeholder="结束日期"
+                :picker-options="pickerOptions"
+                :disabled="timeDisable"> 
+              </el-date-picker>
+            </el-form-item>
+            <span style="line-height: 40px">{{ formateYear(formData.time) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="合同金额" prop="price" style="width: 50%">
+              <el-input v-model="formData.price" @focus="handlePriceBoxFocus('price')" @blur="handlePriceBoxBlur('price')" placeholder="请输入合同金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(formData.price) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="优惠后金额" prop="price2" style="width: 50%">
+              <el-input v-model="formData.price2" @focus="handlePriceBoxFocus('price2')" @blur="handlePriceBoxBlur('price2')" placeholder="请输入优惠后金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(formData.price2) }}</span>
+          </div>
+
+          <el-form-item label="付款方式说明" prop="payRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.payRemark" placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)" style="width: 80%"></el-input>
+            <p>说明模板:甲方自合同生效日起的十日之内一次性支付一年服务费,乙方收款后为甲方开具合法有效的增值税发票。</p>
+          </el-form-item>
+          <el-form-item label="付款方" prop="PayChannel" class="border-top">
+            <!-- <el-input type="textarea" v-model="formData.PayChannel" placeholder="填写代支付的券商名称/期货公司名称,若非代付填写无" style="width: 80%"></el-input> -->
+            <!-- <el-autocomplete
+                v-model="formData.PayChannel"
+                :fetch-suggestions="querySearchAsyncPayChannel"
+                placeholder="请输入"
+                style="width: 80%"
+              ></el-autocomplete> -->
+              <el-select
+                v-model="formData.PayChannel"
+                multiple
+                filterable
+                remote
+                allow-create
+                placeholder="请输入关键词"
+                :remote-method="querySearchAsyncPayChannel"
+                style="width: 80%">
+                <el-option
+                  v-for="item in PayChannelOptions"
+                  :key="item.PayChannel"
+                  :label="item.PayChannel"
+                  :value="item.PayChannel">
+                </el-option>
+              </el-select>
+              <p>如果为代付,则需要填写代付方名称(期货公司或者证券公司),请勿填写现金/转账</p>
+          </el-form-item>
+          <!-- <el-form-item label="备注" prop="sellerRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.sellerRemark" placeholder="审批人查看,不在生成合同中展示" style="width: 80%"></el-input>
+          </el-form-item> -->
+        </div>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">服务内容</h2>
+        <div class="section-container">
+          <!-- ficc 服务内容表格 -->
+          <FiccServiceTable
+            ref="FiccServiceTableRef"
+            :canEdit="true"
+            :serviceData="ficcServiceData"
+            :hasSercive="selectServiceData"
+            :editValue="editValue"
+            :contractType="formData.constractType"
+            @handleShowService="handleShowService"
+            v-if="RoleType === 'ficc_seller'"
+          ></FiccServiceTable>
+          <!-- 权益 服务内容表格 -->
+          <QyServiceTable ref="QyServiceTableRef" :canEdit="true" :serviceData="qyServiceData" :hasSercive="selectServiceData" @handleShowService="handleShowService" v-else></QyServiceTable>
+        </div>
+
+        <p style="margin-top: 30px; margin-bottom: 20px;font-size:14px">补充内容(eg额外赠送、路演次数规定)</p>
+        <el-radio v-model="radio" label="2">无</el-radio>
+        <el-radio v-model="radio" label="1">有</el-radio>
+        <el-form-item prop="remark" label-width="0" ref="formItemRemark">
+          <el-input v-if="radio === '1'" type="textarea" v-model="formData.remark" rows="5" placeholder="请输入内容" style="margin: 20px 0; display: block; box-sizing: border-box"></el-input>
+        </el-form-item>
+        <!-- <div style="text-align: center; margin-top: 40px; margin-bottom: 20px">
+          <el-button type="primary" plain style="width: 145px" @click="handleSubmit('预览')">预览</el-button>
+          <el-button type="primary" @click="handleSubmit('存草稿')" style="width: 145px">存草稿</el-button>
+          <el-button type="primary" @click="handleSubmit('提交')" style="width: 145px">提交</el-button>
+        </div> -->
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">审批备注</h2>
+        <div class="section-container">
+          <el-form-item label="备注" prop="sellerRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.sellerRemark" placeholder="请输入备注(仅供审批人查看,不在生成合同中展示)" style="width: 80%"></el-input>
+          </el-form-item>
+        </div>
+        <div style="text-align: center; margin-top: 40px; margin-bottom: 20px">
+          <el-button type="primary" plain style="width: 145px" @click="handleSubmit('预览')">预览</el-button>
+          <el-button type="primary" @click="handleSubmit('存草稿')" style="width: 145px">存草稿</el-button>
+          <el-button type="primary" @click="handleSubmit('提交')" style="width: 145px">提交</el-button>
+        </div>
+      </section>
+    </el-form>
+
+    <!-- 套餐 -->
+    <ServiceDialog ref="ServiceDialogRef" :contractType="formData.constractType" :serviceShow="serviceShow" @serviceClose="serviceClose" @serviceSave="serviceSave" :serviceCon="serviceCon"></ServiceDialog>
+  </div>
+</template>
+
+
+<style>
+.el-radio__input.is-checked .el-radio__inner {
+  background-color: transparent;
+}
+.el-radio__inner::after {
+  width: 6px;
+  height: 6px;
+  background-color: #409eff;
+}
+.addconstract-container .el-checkbox__label {
+  font-size: 14px !important;
+}
+.el-form-item {
+  margin-bottom: 30px;
+}
+.addconstract-container .section-container .el-textarea__inner::placeholder{
+  color: #999;
+}
+.addconstract-container .section-container .el-input__inner::placeholder{
+  color: #999;
+}
+</style>
+
+<style lang="scss" scoped>
+.addconstract-container {
+  min-height: calc(100vh - 250px);
+  position: relative;
+  font-size: 16px;
+  color: #000;
+}
+.flex {
+  display: flex;
+}
+.section {
+  background-color: #fff;
+  border: 1px solid #aab4cc;
+  border-radius: 4px;
+  padding: 20px 30px;
+  margin-bottom: 20px;
+  .section-title {
+    margin-bottom: 30px;
+  }
+  .border-top {
+    padding-top: 30px;
+    border-top: 1px solid #dcdfe6;
+  }
+}
+</style>

+ 545 - 0
src/views/contract_manage/addContractDC.vue

@@ -0,0 +1,545 @@
+<script setup>
+import { ref,reactive,nextTick } from "vue";
+import {ElMessage,ElMessageBox} from "element-plus"
+import { useRouter} from 'vue-router';
+import _ from 'lodash'
+import { InfoFilled } from '@element-plus/icons-vue'
+
+import { contractInterface } from "@/api/api.js";
+import{province_sorce,city_sorce} from '@/utils/distpicker';
+import QyServiceTable from "./components/QyServiceTable.vue"; //权益服务内容表格组件
+import FiccServiceTable from "./components/FiccServiceTable.vue"; //ficc服务内容表格组件
+import { CalculationDate } from "@/utils/CalculationDate";
+import {formatTime} from '@/hooks/mixins/index.js'
+
+const $router = useRouter()
+
+const province_sorce_value=province_sorce
+const city_sorce_value=city_sorce
+
+const RoleType=ref(localStorage.getItem("Role") || "")
+const formData=reactive({
+  CompanyName: "",
+  CreditCode: "",
+  Province: "",
+  City: "",
+  Address: "",
+  Fax: "",
+  Phone: "",
+  Postcode: "",
+  OriginalPrice: "",
+  trueUseName: "",
+  sellerRemark: "",
+  PayRemark: "",
+  RelationContractId: null,
+})
+
+const formRule={
+  CompanyName: [{ required: true, message: "请填写名称", trigger: "blur" }],
+  CreditCode: [{ required: true, message: "请填写信用码", trigger: "blur" }],
+  Province: [{ required: true, message: "请选择地址", trigger: "change" }],
+  OriginalPrice: [
+    { required: true, message: "请填写代付金额", trigger: "blur" },
+    // { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: "请输入正确的格式,可保留两位小数" },
+  ],
+  trueUseName: [{ required: true, message: "请输入关键字", trigger: "change" }],
+  PayRemark: [{ required: true, message: "请填写付款方式说明", trigger: "blur" }],
+  Address: [{ required: true, message: "请填写详细地址", trigger: "blur" }],
+  Phone: [{ required: true, message: "请填写电话", trigger: "blur" }],
+}
+
+const searchList=ref([])
+const contractList=ref([])
+const showContractList=ref(false)
+const relationContractData=ref(null) //选择的关联合同数据
+const ficcServiceData=ref(null) //ficc 底部表格数据
+const qyServiceData=ref(null) //权益底部表格数据
+const serviceShow=ref(false) //是否显示查看报价单
+const serviceCon=ref({}) //选择的服务项 查看报价单/选择品种
+// filters
+
+const formatPrice=(str)=>{
+  if(!str) return ''
+  str=str.toString()
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  return num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+// 金额转中文大写
+const digitUppercase=(n)=>{
+  if(!n) return ''
+  n=n.toString().replace(/,/g,'')
+  let fraction = ["角", "分"];
+  let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+  let unit = [
+    ["元", "万", "亿"],
+    ["", "拾", "佰", "仟"],
+  ];
+  let head = n < 0 ? "欠" : "";
+  n = Math.abs(n);
+  let s = "";
+  for (let i = 0; i < fraction.length; i++) {
+    s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, "");
+  }
+  // s = s || "整";
+
+  n = Math.floor(n);
+  for (let i = 0; i < unit[0].length && n > 0; i++) {
+    let p = "";
+    for (let j = 0; j < unit[1].length && n > 0; j++) {
+      p = digit[n % 10] + unit[1][j] + p;
+      n = Math.floor(n / 10);
+    }
+    s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s;
+  }
+  return (
+    "大写:" + (head + s.replace(/(零.)*零元/, "元").replace(/(零.)+/g, "零"))
+    // .replace(/^整$/, "零元整")
+  );
+}
+//计算多少年
+const formateYear=(e)=>{
+  if (e[0]) {
+    return `有效期为${CalculationDate(e[0], e[1])}`;
+  } else {
+    return "";
+  }
+}
+
+// 搜索出客户
+const customeSearch=async(query)=>{
+  if (!query) return;
+  const res = await contractInterface.getBusinessContractCompanyNameList({ Keyword: query });
+  if (res.Ret === 200) {
+    searchList.value = res.Data;
+  }
+}
+// 选择客户并搜索出其下已签回合同
+const handleSelectTrueUseName=(e)=>{
+  nextTick(async()=>{
+    if(isBlurManual.value){
+      isBlurManual.value=false
+      return 
+    }
+    if (e||!formData.trueUseName) return;
+
+    const res = await contractInterface.getBusinessContractList({ CompanyName: formData.trueUseName });
+    if (res.Ret === 200) {
+      showContractList.value = true;
+      nextTick(() => {
+        contractList.value = res.Data.List;
+      });
+    }
+  })
+
+}
+
+// 确认关联
+const handleRelation=async()=>{
+  if (!formData.RelationContractId) {
+    ElMessage.warning("请选择一份合同进行关联");
+    return;
+  }
+  const res = await contractInterface.getContractDetail({ ContractId: formData.RelationContractId });
+  if (res.Ret === 200) {
+    relationContractData.value = res.Data;
+    getServiceList();
+    showContractList.value = false;
+  }
+}
+
+const trueUseNameRef=ref(null)
+const isBlurManual=ref(false)
+const closeTrueUseNameDia=()=>{
+  // element-plus 会在弹窗关闭后,返回焦点给el-select组件……
+  console.log('失去焦点');
+  isBlurManual.value=true
+  trueUseNameRef.value.blur()
+}
+
+//获取服务套餐模板数据
+const getServiceList=()=>{
+  contractInterface.getServiceList({ ProductId: relationContractData.value.ProductId }).then((res) => {
+    if (res.Ret === 200) {
+      if (relationContractData.value.ProductId === 1) {
+        ficcServiceData.value = res.Data;
+      } else {
+        qyServiceData.value = res.Data;
+      }
+    }
+  });
+}
+
+//显示查看报价单弹窗
+const handleShowService=(e)=>{
+  // 小套餐情况处理表格数据
+  if (e.Detail) {
+    let temarr = e.Detail.map((rowItem) => {
+      let rowArr = [];
+      for (let key in rowItem) {
+        if (key.substring(0, 3) === "Col" && rowItem[key] !== "") {
+          rowArr.push(JSON.parse(rowItem[key]));
+        }
+      }
+      return rowArr;
+    });
+    serviceCon.value = { ...e, tableHeadData: temarr[0], tableData: temarr.slice(1) };
+  } else {
+    serviceCon.value = e;
+  }
+  serviceShow.value = true;
+}
+
+//选地地区时 选则的省份改变重置city为空
+const provinceChange=(e)=>{
+  formData.Province =e.value=='省'?'':e.value;
+  formData.City=''
+}
+
+//选择地区
+const selectRegion=(e)=>{
+  formData.Province =e.province.value=='省'?'':e.province.value;
+  formData.City = e.city.value=='市'?'':e.city.value;
+}
+
+const formRef=ref(null)
+// 提交
+const handleSubmit=(type)=>{
+  formRef.value.validate(async (valid) => {
+    if (valid) {
+      let params = {
+        ContractType:"新签合同",
+        ContractBusinessType:"代付合同",
+        Address: formData.Address,
+        City: formData.City,
+        CompanyName: formData.CompanyName,
+        CreditCode: formData.CreditCode,
+        Province: formData.Province,
+        Fax: formData.Fax,
+        Phone: formData.Phone,
+        Postcode: formData.Postcode,
+        OriginalPrice: Number(formData.OriginalPrice.replace(/,/g,'')),
+        sellerRemark: formData.sellerRemark,
+        PayRemark: formData.PayRemark,
+        TemplateId: RoleType.value === "ficc_seller" ? 1 : 2,
+        RelationContractId: formData.RelationContractId,
+      };
+      if(!params.City){
+        ElMessage.warning("请选择城市")
+        return
+      }
+      if(!params.RelationContractId){
+        ElMessage.warning('请选择关联合同')
+        return
+      }
+      if (type === "预览") {
+        params = { ...params, IsAudit: false };
+        handlePreview(params);
+        return;
+      } else if (type === "存草稿") {
+        params = { ...params, IsAudit: false };
+      } else {
+        params = { ...params, IsAudit: true };
+      }
+      const res = await contractInterface.addContract(params);
+      if (res.Ret === 200) {
+        $router.go(-1);
+      }
+    }else{
+      ElMessage.warning('请完善必填项')
+    }
+  });
+}
+//前去预览
+const handlePreview=(params)=>{
+  contractInterface.previewContract(params).then((res) => {
+    if (res.Ret === 200) {
+      sessionStorage.setItem("contractdtl", res.Data.Html);
+      let { href } = $router.resolve({ path: "/contractdtl" });
+      window.open(href, "_blank");
+    }
+  });
+}
+
+// 金额输入框获取焦点
+const handlePriceBoxFocus=(key)=>{
+  let val=formData[key]
+  val=val.replace(/,/g,'')
+  formData[key]=val
+}
+// 金额输入框获失去焦点
+const handlePriceBoxBlur=(key)=>{
+  let str=formData[key]
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  formData[key]=num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+
+</script>
+
+<template>
+  <div class="addcontractdc-container">
+    <el-form ref="formRef" :model="formData" label-position="left" :rules="formRule" label-width="110px" size="large">
+      <section class="section">
+        <h2 class="section-title">客户信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="代付方" prop="CompanyName" style="width: 50%">
+              <el-input v-model="formData.CompanyName" placeholder="请输入名称" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="社会信用码" prop="CreditCode" style="width: 50%">
+              <el-input v-model="formData.CreditCode" placeholder="请输入社会信用码" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="公司地址" prop="Province" style="width: 50%">
+              <v-distpicker :province-source="province_sorce_value"
+                :city-source="city_sorce_value"  :province="formData.Province" :city="formData.City" hide-area @province="provinceChange" @selected="selectRegion"></v-distpicker>
+            </el-form-item>
+            <el-form-item label="详细地址" prop="Address" style="width: 50%">
+              <el-input v-model="formData.Address" placeholder="请输入详细地址" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="传真" prop="Fax" style="width: 50%">
+              <el-input v-model="formData.Fax" placeholder="请输入传真" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="电话" prop="Phone" style="width: 50%">
+              <el-input v-model="formData.Phone" placeholder="请输入电话" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="邮编" prop="Postcode" style="width: 50%">
+              <el-input v-model="formData.Postcode" placeholder="请输入邮编" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="代付金额" prop="OriginalPrice" style="width: 50%">
+              <el-input v-model="formData.OriginalPrice" @focus="handlePriceBoxFocus('OriginalPrice')" @blur="handlePriceBoxBlur('OriginalPrice')" placeholder="请输入金额" style="width: 350px"></el-input>
+              <span style="line-height: 40px;margin-left:20px">{{ digitUppercase(formData.OriginalPrice)  }}</span>
+            </el-form-item>
+          </div>
+        </div>
+      </section>
+      <section class="section">
+        <el-form-item label="付款方式说明" prop="PayRemark">
+          <el-input type="textarea" v-model="formData.PayRemark" placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)" style="width: 80%"></el-input>
+          <p>说明模板:甲方自合同生效日起的十日之内一次性支付一年服务费,乙方收款后为甲方开具合法有效的增值税发票。</p>
+        </el-form-item>
+        <el-form-item label="实际使用方" prop="trueUseName" class="border-top">
+          <el-select v-model="formData.trueUseName" filterable remote placeholder="关键词搜索" ref="trueUseNameRef"
+          :remote-method="customeSearch" @visible-change="handleSelectTrueUseName" style="width: 500px">
+            <el-option v-for="item in searchList" :key="item" :label="item" :value="item"> </el-option>
+          </el-select>
+        </el-form-item>
+      </section>
+
+      <section class="section" v-if="relationContractData">
+        <h2 class="section-title">合同信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="合同编号" style="width: 50%">
+              <span>{{ relationContractData.ContractCode }}</span>
+            </el-form-item>
+            <el-form-item label="合同归属" style="width: 50%">
+              <span>{{ relationContractData.ProductId === 1 ? "ficc" : "权益" }}</span>
+            </el-form-item>
+          </div>
+          <el-form-item label="合同类型" class="border-top">
+            <el-radio-group v-model="relationContractData.ContractType">
+              <div style="display: flex">
+                <div style="margin-right: 10px">
+                  <el-radio label="新签合同" disabled>新签合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>没有正式转试用记录的客户,在申请转正时提交的合同</template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right: 10px">
+                  <el-radio label="续约合同" disabled>续约合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>
+                      1、有正式转试用记录的客户,在申请转正时提交的合同<br>
+										  2、所有客户在续约申请时提交的合同
+                    </template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right: 10px" v-if="RoleType !== 'rai_seller'">
+                  <el-radio label="补充协议" disabled>补充协议</el-radio>
+                </div>
+              </div>
+            </el-radio-group>
+          </el-form-item>
+          <div class="flex border-top" v-if="relationContractData.timeRange">
+            <el-form-item label="合同期限" style="width: 50%">
+              <el-date-picker disabled v-model="relationContractData.timeRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
+            </el-form-item>
+            <span style="line-height: 40px">{{ formateYear(relationContractData.timeRange) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="合同金额" style="width: 50%">
+              <el-input disabled :value="formatPrice(relationContractData.OriginalPrice)" placeholder="请输入合同金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(relationContractData.OriginalPrice)  }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="优惠后金额" style="width: 50%">
+              <el-input disabled :value="formatPrice(relationContractData.Price)" placeholder="请输入优惠后金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(relationContractData.Price)  }}</span>
+          </div>
+
+          <el-form-item label="付款方式说明" class="border-top">
+            <el-input
+              type="textarea"
+              disabled
+              v-model="relationContractData.PayRemark"
+              placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)"
+              style="width: 80%"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="付款方" class="border-top">
+            <el-input
+              type="textarea"
+              disabled
+              v-model="relationContractData.PayChannel"
+              placeholder="代付,请填写代付的券商名称或期货公司名称;非代付,请填写无。(请勿填写现金/转账等支付形式)"
+              style="width: 80%"
+            ></el-input>
+          </el-form-item>
+        </div>
+      </section>
+
+      <section class="section" v-if="relationContractData">
+        <h2 class="section-title">服务内容</h2>
+          <div class="section-container">
+            <!-- ficc 服务内容表格 -->
+            <FiccServiceTable
+              :canEdit="false"
+              :serviceData="ficcServiceData"
+              :hasSercive="relationContractData.Service"
+              @handleShowService="handleShowService"
+              v-if="relationContractData.ProductId === 1 && ficcServiceData"
+            ></FiccServiceTable>
+
+            <!-- 权益 服务内容表格 -->
+            <QyServiceTable
+              :canEdit="false"
+              :serviceData="qyServiceData"
+              :hasSercive="relationContractData.Service"
+              @handleShowService="handleShowService"
+              v-if="relationContractData.ProductId === 2 && qyServiceData"
+            ></QyServiceTable>
+          </div>
+          <p style="margin-top: 30px; margin-bottom: 20px">补充内容(eg额外赠送、路演次数规定)</p>
+          <el-radio :model-value="relationContractData.Remark?'1':'2'" label="2" disabled>无</el-radio>
+          <el-radio :model-value="relationContractData.Remark?'1':'2'" label="1" disabled>有</el-radio>
+          <el-input v-if="relationContractData.Remark" disabled type="textarea" v-model="relationContractData.Remark" rows="5" placeholder="请输入内容" style="margin: 20px 0; display: block; box-sizing: border-box"></el-input>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">审批备注</h2>
+        <div class="section-container">
+          <el-form-item label="备注" prop="sellerRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.sellerRemark" placeholder="请输入备注(仅供审批人查看,不在生成合同中展示)" style="width: 80%"></el-input>
+          </el-form-item>
+        </div>
+        <div style="text-align: center; margin-top: 40px; margin-bottom: 20px">
+          <el-button type="primary" plain style="width: 145px" @click="handleSubmit('预览')" size="large">预览</el-button>
+          <el-button type="primary" @click="handleSubmit('存草稿')" style="width: 145px" size="large">存草稿</el-button>
+          <el-button type="primary" @click="handleSubmit('提交')" style="width: 145px" size="large">提交</el-button>
+        </div>
+      </section>
+    </el-form>
+
+    <!-- 选择合同弹窗 -->
+    <el-dialog v-dialogDrag :title="`搜索到${formData.trueUseName}下合同`" :append-to-body="true" 
+    v-model="showContractList" width="50%" center @close="closeTrueUseNameDia" draggable>
+      <el-table :data="contractList" border height="60vh">
+        <el-table-column align="center" width="50">
+          <template #default="scope">
+            <el-radio v-model="formData.RelationContractId" :label="scope.row.ContractId"><span></span></el-radio>
+          </template>
+        </el-table-column>
+        <el-table-column label="合同编号" prop="ContractCode" align="center"></el-table-column>
+        <el-table-column label="销售" prop="SellerName" align="center" width="80"></el-table-column>
+        <el-table-column label="合同类型" prop="ContractType" align="center" width="80"></el-table-column>
+        <el-table-column label="合同有效期" prop="ContractType" align="center" width="180">
+          <template #default="scope">{{ formatTime(scope.row.StartDateStr)  }}~{{ formatTime(scope.row.EndDateStr) }}</template>
+        </el-table-column>
+        <el-table-column key="合同金额" align="center" prop="Price" label="合同金额" width="100"></el-table-column>
+        <el-table-column key="合同状态" align="center" prop="Status" label="合同状态" width="80"></el-table-column>
+        <el-table-column key="签回时间" align="center" prop="Status" label="签回时间" width="160">
+          <template #default="scope">{{ formatTime(scope.row.CheckBackFileTimeStr) }}</template>
+        </el-table-column>
+      </el-table>
+      <div style="text-align: center; margin: 30px 0">
+        <el-button type="primary" @click="handleRelation" size="large">确定关联</el-button>
+        <el-button type="primary" plain @click="showContractList = false" size="large">取消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 查看报价单弹窗 -->
+    <el-dialog v-dialogDrag v-model="serviceShow" width="60%" class="self-dialog-c" :modal-append-to-body="false" @close="serviceShow=false" :show-close="false">
+      <h2 class="title" style="text-align: center; color: #000">{{RoleType == 'ficc_seller'? serviceCon.Title : serviceCon.showTitle}}</h2>
+      <img class="img" style="width: 100%; display: block; margin: 20px auto" 
+      :src="RoleType == 'ficc_seller'? serviceCon.Value : serviceCon.showValue" />
+      <div style="text-align: center; margin-bottom: 30px">
+        <el-button type="primary" @click="serviceShow=false" size="large">知道了</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<style>
+.addcontractdc-container .self-dialog-c .el-dialog__header {
+  background-color: #fff;
+  padding: 0;
+}
+.addcontractdc-container .self-dialog-c {
+  width: auto;
+  max-width: 60%;
+}
+</style>
+<style lang="scss" scoped>
+.addcontractdc-container {
+  min-height: calc(100vh - 250px);
+  position: relative;
+  font-size: 16px;
+  color: #000;
+}
+.flex {
+  display: flex;
+}
+.section {
+  background-color: #fff;
+  border: 1px solid #aab4cc;
+  border-radius: 4px;
+  padding: 20px 30px;
+  margin-bottom: 20px;
+  .section-title {
+    margin-bottom: 30px;
+  }
+  .border-top {
+    padding-top: 30px;
+    border-top: 1px solid #dcdfe6;
+  }
+}
+</style>

+ 260 - 0
src/views/contract_manage/components/FiccServiceTable.vue

@@ -0,0 +1,260 @@
+<script setup>
+import { ref,watch } from "vue";
+const props = defineProps({
+  serviceData: {
+    type:Array,
+    default:()=>[]
+  },
+  hasSercive: {
+    type:Array,
+    default:()=>[]
+  },
+  canEdit: false,
+  editValue: {},
+  contractType:null,
+  isEdit:false // 是新增合同还是修改合同
+});
+const emits=defineEmits(['handleShowService'])
+
+const tableData=ref([])
+
+watch(()=>props.editValue,(nval, oval)=>{
+  if (nval.ServiceTemplateId) {
+    tableData.value.forEach((item) => {
+      if (item.ServiceTemplateId === nval.ServiceTemplateId) {
+        item.Value = nval.Value;
+        // item 表格数据 nval 更新的数据
+        // 更新表头 item.Detail[0]
+        console.log([nval.tableHeadData,...nval.tableData]);
+        let arr=[nval.tableHeadData,...nval.tableData].map((item2,index2)=>{
+          
+          let obj={}
+          item2.forEach((item3,index3)=>{
+            let key=`Col${index3+1}`
+            obj={...obj,[key]:JSON.stringify(item3)}
+          })
+          return obj
+        })
+        console.log(arr);
+        item.Detail=arr
+
+
+        
+      }
+    });
+  }
+})
+
+// 初始化数据
+const initTableData=()=>{
+  if (props.serviceData.length === 0) return;
+  let arr = props.serviceData.map((item, index) => {
+    return {
+      ...item,
+      selected: false,
+      disable: false,
+      text1: item.Detail ? "选择品种" : "查看报价单",
+      text2: "下载报价单",
+    };
+  });
+  // 合同详情或者是需要编辑情况下
+  if (props.hasSercive.length !== 0) {
+  arr.forEach((item) => {
+    props.hasSercive.forEach((e) => {
+      if (e.ServiceTemplateId === item.ServiceTemplateId) {
+        item.Value = e.Value;
+        item.Detail = e.DetailList || e.Detail;
+        item.selected = true;
+        item.disable = false;
+      }
+
+      if (item.SelectType === "radio" && e.ServiceTemplateId !== item.ServiceTemplateId) {
+        if (!item.selected) {
+          item.disable = false;
+        }
+      }
+    });
+  });
+
+  // 合同详情 全部禁用
+  if (!props.canEdit) {
+    arr.forEach((item) => {
+      item.disable = true;
+      // 如果是小套餐类型 即存在Detail 则将选择品种改为查看报价单
+      if (item.Detail) {
+        item.text1 = "查看报价单";
+      }
+    });
+  }
+  // this.tableData = arr;
+  } else {
+    // 新增 默认选择第一个
+    // arr.forEach((item, index) => {
+    //   if (index === 0) {
+    //     item.selected = true;
+    //   }
+    // });
+    //如果第一个是单选的 则将其他的禁用
+    // if (arr[0] && arr[0].SelectType === "radio") {
+    //   arr.forEach((item) => {
+    //     if (item.ServiceTemplateId !== arr[0].ServiceTemplateId && item.SelectName === arr[0].SelectName) {
+    //       item.disable = true;
+    //       item.selected = false;
+    //     }
+    //   });
+    // }
+  }
+
+  if(props.contractType==='补充协议'){
+    arr.forEach(item=>{
+      //大套餐 禁用
+      if(item.ServiceTemplateId===1){
+        item.disable=true
+        item.selected=false
+      }else{
+        item.disable=false
+      }
+    })
+  }
+
+  tableData.value = arr;
+}
+
+// 一开始进来 serviceData数据为空数组
+watch(()=>props.serviceData,()=>{
+  initTableData();
+},
+{immediate:true,deep:true})
+
+watch(()=>props.contractType,(nval)=>{
+  initTableData();
+  if(nval==='补充协议'){
+    tableData.value.forEach(item=>{
+      //大套餐 禁用
+      if(item.ServiceTemplateId===1){
+        item.disable=true
+        item.selected=false
+      }else{
+        item.disable=false
+      }
+      // 需求更改,新增合同类型为"补充协议的时候",不默认勾选宏观经济
+      // 将默认的勾选的宏观经济去除
+      if(item.ServiceTemplateId===2 && !props.isEdit){
+        for (let i = 0; i < item.Detail.slice(3,6).length; i++) {
+          let temp = JSON.parse(item.Detail.slice(3,6)[i].Col2)
+          temp.ValueId.length=0
+          temp.Value=""
+          item.Detail.slice(3,6)[i].Col2 = JSON.stringify(temp)
+        }
+      }
+    })
+  }else{
+    // 如果一个都没选中过 则重置都为非禁用
+    let flag=0
+    tableData.value.forEach(item=>{
+      if(item.selected){
+        flag++
+      }
+    // "补充协议"切换会其他合同类型时,恢复默认,即勾选宏观经济的状态
+      if(item.ServiceTemplateId===2 && !props.isEdit){
+        for (let i = 0; i < item.Detail.slice(3,6).length; i++) {
+          let temp = JSON.parse(item.Detail.slice(3,6)[i].Col2)
+          if(temp.ValueId.length===0){
+            temp.ValueId[0]=1
+            temp.Value="宏观经济"
+            item.Detail.slice(3,6)[i].Col2 = JSON.stringify(temp) 
+          }
+        }
+      }
+    })
+    if(flag==0){
+      tableData.value.forEach(item=>{
+        item.disable=false
+      })
+    }
+  }
+})
+
+// 选项切换
+const handleChange=(e)=>{
+  if (e.SelectType === "radio") {
+    if (e.selected) {
+      tableData.value.forEach((item) => {
+        if (item.ServiceTemplateId !== e.ServiceTemplateId && item.SelectName === e.SelectName) {
+          item.disable = true;
+          item.selected = false;
+        }
+      });
+      // 如果是小套餐则 主动展示弹窗
+      if(e.Detail&&e.Detail.length){
+        handleShow(e)
+      }
+    } else {
+      tableData.value.forEach((item) => {
+        if (item.ServiceTemplateId !== e.ServiceTemplateId && item.SelectName === e.SelectName) {
+          // 如果选择了补充协议 则大套餐仍然不可选
+          if(props.contractType==='补充协议'&&item.ServiceTemplateId===1){
+            item.disable=true
+            item.selected=false
+          }else{
+            item.disable = false;
+            item.selected = false;
+          }
+        }
+      });
+    }
+  }
+}
+
+//下载报价单
+const handleDownloadImg=(e)=>{
+  let link = document.createElement("a");
+
+  //判断e.Value是否以 http开头
+  if (e.Value.startsWith("http")) {
+    link.href = e.Value + "?response-content-type=application/octet-stream"; //下载链接
+  } else {
+    link.href = e.Value;
+  }
+  link.setAttribute("download", e.Title);
+  link.style.display = "none"; //a标签隐藏
+  document.body.appendChild(link);
+  link.click();
+}
+
+const handleShow=(e)=>{
+  emits("handleShowService", e);
+}
+defineExpose({
+  tableData
+})
+
+</script>
+
+<template>
+  <el-table border :data="tableData" style="width: 601px">
+    <el-table-column label="套餐类型" width="200" align="center">
+      <template #default="scope">
+        <el-checkbox
+          @change="handleChange(scope.row)"
+          :label="scope.row.Title"
+          v-model="scope.row.selected"
+          :disabled="scope.row.disable"
+          style="width: 100%; text-align: left; padding-left: 50px"
+        ></el-checkbox>
+      </template>
+    </el-table-column>
+    <el-table-column width="200">
+      <template #default="scope">
+        <span style="cursor: pointer; color: #409eff; padding-left: 50px" v-if="scope.row.selected" @click="handleShow(scope.row)">{{ scope.row.text1 }}</span>
+      </template>
+    </el-table-column>
+    <el-table-column width="200" align="center">
+      <template #default="scope">
+        <span style="cursor: pointer; color: #409eff" v-if="scope.row.selected && scope.row.Value" @click="handleDownloadImg(scope.row)">{{ scope.row.text2 }}</span>
+      </template>
+    </el-table-column>
+  </el-table>
+</template>
+
+<style></style>

+ 4 - 1
src/views/contract_manage/components/PreviewService.vue

@@ -3,7 +3,10 @@ import { reactive, watch } from 'vue'
 
 const props = defineProps({
   showPreview: false,
-  serviceCon: [],
+  serviceCon: {
+    type:Array,
+    default:()=>[]
+  },
 })
 
 const emits = defineEmits(['closePreviewService'])

+ 439 - 0
src/views/contract_manage/components/QyServiceTable.vue

@@ -0,0 +1,439 @@
+
+<script setup>
+
+import { ref,reactive,watch } from "vue";
+
+const props = defineProps({
+  serviceData: {
+    type:Array,
+    default:()=>[]
+  },
+  hasSercive: {
+    type:Array,
+    default:()=>[]
+  },
+  canEdit: false,
+});
+const emits=defineEmits(['handleShowService','serviceClose'])
+
+
+const tableData=reactive({
+  radio: "",
+  list: [],
+  spanMergeCount:[]
+})
+const checkList=ref([])
+// 有主客观的套餐列表
+const selectAllArr=ref([])
+// 有主客观的套餐名称列表
+const haveChildList=ref([])
+// 升级的套餐列表 医药、消费、科技、智造
+const upgradeServes=ref([])
+const templateData=ref([])
+
+  // watch: {
+    // checkList(nval, oval) {
+    //   let tag = "";
+    //   let temtitle = "";
+
+    //   this.tableData.list.forEach((item) => {
+    //     if (item.SelectType === "radio") {
+    //       let flag = nval.indexOf(item.Title);
+    //       if (flag !== -1) {
+    //         tag = item.SelectName;
+    //         temtitle = item.Title;
+    //       }
+    //     }
+    //   });
+
+    //   this.tableData.list.forEach((item) => {
+    //     if (item.fatherName === this.tableData.radio) {
+    //       if (item.SelectName === tag && item.Title !== temtitle) {
+    //         item.disable = true;
+    //         item.selected = false;
+    //       } else {
+    //         item.disable = false;
+    //       }
+    //     }
+    //   });
+    // },
+  // }
+
+//切换radio
+const handleRadioChange=(e)=>{
+  checkList.value = [];
+  for (const it of selectAllArr.value) {
+    it.checkAll = false
+    it.isIndeterminate = false
+  }
+  tableData.list.forEach((item) => {
+    if (item.grandFatherName !== e) {
+      item.disable = true;
+      item.selected = false;
+    } else {
+      item.disable = false;
+    }
+  });
+}
+// 全选
+const handleCheckAllChange=(row)=>{
+  // console.log(row,'row');
+  // console.log(checkList.value,'this.checkList');
+  let arr = checkList.value.filter(item => item.indexOf(row.fatherName) != -1)
+  let rowFather = selectAllArr.value.find((item) => item.name == row.fatherName)
+  rowFather.isIndeterminate = false
+  if(arr.length<2){
+    rowFather.checkAll=true
+    checkList.value = [...new Set([...checkList.value,...[`${row.fatherName}(主观)`,`${row.fatherName}(客观)`]])]
+  }else{
+    checkList.value = checkList.value.filter(item => item.indexOf(row.fatherName) == -1)
+    rowFather.checkAll=false
+  }
+  handleChange(checkList.value,row)
+}
+
+//点击选项
+const handleChange=(nval,row)=>{
+  let rowFather = selectAllArr.value.find((item) => item.name == row.fatherName)
+  if(rowFather){
+    let arr = nval.filter(item => item.indexOf(row.fatherName) !=-1)
+    rowFather.checkAll=arr.length==2
+    rowFather.isIndeterminate=arr.length==1
+  }
+  //一个都没选
+  if(!nval.length){
+    tableData.radio=""
+    tableData.list.forEach(item=>{
+      item.disable=false
+      item.selected=false
+    })
+    return
+  }
+
+  // 当this.tableData.radio 为空时 
+  if(!tableData.radio){
+    tableData.list.forEach(item=>{
+      if(item.Title===nval[0] || nval[0].indexOf(item.Title)!=-1){
+        tableData.radio=item.grandFatherName
+        tableData.list.forEach(item2=>{
+          if(item2.grandFatherName!==item.grandFatherName){
+            item2.selected=false 
+            item2.disable=true
+          }
+        })
+      }
+    })
+  }
+
+  let tag = "";
+  let temtitle = "";
+  
+  tableData.list.forEach((item) => {
+    if (item.SelectType === "radio") {
+      let flag = nval.indexOf(item.Title);
+      if (flag !== -1) {
+        tag = item.SelectName;
+        temtitle = item.Title;
+      }
+    }
+  });
+  tableData.list.forEach((item) => {
+    if (item.grandFatherName === tableData.radio) {
+      if (item.SelectName === tag && item.Title !== temtitle) {
+        item.disable = true;
+        item.selected = false;
+      } else {
+        item.disable = false;
+      }
+    }
+  });
+  // 升级套餐与基础套餐 禁用
+  // console.log(upgradeServes.value,'this.upgradeServes',tableData.list);
+  upgradeServes.value.map(item =>{
+    // 取出原始套餐标题
+    let serveTitle = item.fatherName.split("(")[0]
+    let hasBasicServe=nval.some(item => item.indexOf(serveTitle)!=-1 && item.indexOf('升级')==-1)
+    let hasUpgradeServe=nval.some(item => item.indexOf(serveTitle)!=-1 && item.indexOf('升级')!=-1)
+    if(hasBasicServe){
+      item.disable=true
+    }else if(hasUpgradeServe){
+      tableData.list.map(it => {
+        if(it.fatherName.indexOf(serveTitle)!=-1 && it.fatherName.indexOf('升级')==-1){
+          it.disable=true
+        }
+      })
+    }
+  })
+}
+
+//显示报价单
+const handleShow=(e)=>{
+  emits("handleShowService", e);
+}
+
+//显示后面的文字
+const showText=(e)=>{
+  let text=''
+  if(e.fatherName == e.Title){
+    // 没有主客观的
+    text=e.Title
+    let flag = checkList.value.indexOf(text);
+    if (flag !== -1) {
+      return true;
+    } else {
+      return false;
+    }
+  }else{
+    // 有主客观的 合并了单元格,只会传主观的进来
+    text = e.fatherName
+    let arr = checkList.value.filter(item => item.indexOf(text)!=-1 && item.indexOf("升级")==-1)
+    if(arr.length>0){
+      // 主观或者客观
+      if(arr.length==1){
+        if(arr.find(item => item.indexOf("主观")!=-1)){
+          // 主观
+          e.showValue = e.Value
+          e.showTitle = `${text}(${e.Title})`
+        }else{
+          //客观
+          e.showValue = tableData.list.find(item => item.fatherName ==text && item.Title == '客观').Value
+          e.showTitle = tableData.list.find(item => item.fatherName ==text && item.Title == '客观').showTitle
+        }
+      }else{
+        // 主客观都选 呈现的报价单为总共的那一份
+        e.showValue = selectAllArr.value.find(item => item.name == text).value
+        e.showTitle = selectAllArr.value.find(item => item.name == text).showTitle
+      }
+      return true;
+    }else{
+      return false;
+    }
+  }
+
+}
+//初始化表格数据
+const initTableData=()=>{
+  // console.log(props.serviceData,props.hasSercive,'this.serviceData,this.hasSercive');
+  let arr = [];
+  tableData.spanMergeCount=[]
+  props.serviceData.forEach((item, num) => {
+    let temarr = []
+    if (item.Children) {
+      // 第二层
+      tableData.spanMergeCount.push(item.Children.length)
+      item.Children.map((e, index) => {
+        if(e.Children){
+          // 第三层
+          tableData.spanMergeCount[num]=tableData.spanMergeCount[num]-1+e.Children.length
+          // 有分主客观的项
+          selectAllArr.value.push({
+            name:e.Title,
+            isIndeterminate:false,
+            checkAll:false,
+            ServiceTemplateId:e.ServiceTemplateId,
+            value:e.Value,
+            ChartPermissionId:e.ChartPermissionId,
+            showTitle:e.Title
+          })
+          haveChildList.value.push(e.Title)
+          e.Children.map((it,i)=>{
+            temarr.push({
+              ...it,
+              fatherName: e.Title,
+              grandFatherName:item.Title,
+              text2: "下载报价单",
+              text1: e.Detail ? "选择品种" : "查看报价单",
+              selected: false,
+              disable: false,
+              // 预览时的值 选择主观、客观 和主客观都选时展示的不一样
+              // 用于预览和展示报价单
+              showValue:e.Value,
+              showTitle:`${e.Title}(${it.Title})`
+            });
+          })
+        }else{
+          temarr.push({
+            ...e,
+            fatherName: e.Title,
+            grandFatherName:item.Title,
+            text2: "下载报价单",
+            text1: e.Detail ? "选择品种" : "查看报价单",
+            selected: false,
+            disable: false,
+            showValue:e.Value,
+            showTitle:e.Title
+          });
+        }
+      });
+      arr = [...arr, ...temarr];
+    } else {
+      arr.push({ 
+        ...item, 
+        selected: false, 
+        disable: false, 
+        fatherName: item.Title, 
+        grandFatherName: item.Title, 
+        text2: "下载报价单", 
+        text1: item.Detail ? "选择品种" : "查看报价单" });
+    }
+  });
+  // console.log(arr,'arr');
+  
+  tableData.list = arr;
+  // 升级套餐
+  upgradeServes.value = tableData.list.filter(item => item.fatherName.indexOf('升级')!=-1)
+  // console.log(selectAllArr.value,'this.selectAllArr',haveChildList.value);
+  // 回显(合同详情或者是需要编辑的,如果是合同详情则canEdit=false 则全部禁用)
+  // console.log(props.hasSercive,'this.hasSercive');
+  // 目前 医药、消费、科技、智造 分为了主客观
+  if (props.hasSercive&&props.hasSercive.length !== 0) {
+    props.hasSercive.forEach((item) => {
+      // 区分主客观的 主客观都有勾选时,只会返回一个基本套餐名称
+      let basicItem = selectAllArr.value.find(it => it.ServiceTemplateId==item.ServiceTemplateId)
+      if(basicItem){
+        checkList.value.push(`${basicItem.name}(主观)`,`${basicItem.name}(客观)`)
+        // e.fatherName == item.Title
+        arr.filter(e => [item.ServiceTemplateId*2-1,item.ServiceTemplateId*2].includes(e.ServiceTemplateId))
+        .map(it => {
+          handleChange(checkList.value,it)
+        })
+        return 
+      }
+
+      let serviceRow = arr.find(e => e.ServiceTemplateId==item.ServiceTemplateId)
+      if(!serviceRow) return
+      if(item.Title.indexOf("主观")!==-1 || item.Title.indexOf("客观")!==-1){
+        // 兼容之前合同数据的回显
+        checkList.value.push(`${serviceRow.fatherName}(${serviceRow.Title})`)
+      }else{
+        checkList.value.push(item.Title)
+      }
+      handleChange(checkList.value,serviceRow)
+    });
+
+    arr.forEach((item) => {
+      if (item.grandFatherName !== tableData.radio) {
+        item.disable = true;
+      }
+    });
+
+    // 如果是详情即 canEdit=false 则全部禁用
+    if (!props.canEdit) {
+      arr.forEach((item) => {
+        item.disable = true;
+      });
+    }
+    
+    
+  } else {
+    //不需要回显则是新添合同 则初始化将其全部禁用
+    // arr.forEach((item) => {
+    //   item.disable = true;
+    // });
+    //不需要回显则是新添合同 则初始化选择第一个
+    // arr.forEach((item, index) => {
+    //   if (index === 0) {
+    //     item.selected = true;
+    //     item.disable = false;
+    //     this.checkList.push(item.Title);
+    //     this.tableData.radio = item.fatherName;
+    //   }
+    // });
+  }
+}
+
+//合并单元格
+const objectSpanMethod=({ row, column, rowIndex, columnIndex  })=>{
+  if(columnIndex === 0){
+    if(rowIndex == 0){
+      // 权益大套餐
+      return [tableData.spanMergeCount[0],1]
+    }else if(rowIndex == tableData.spanMergeCount[0]){
+      // 行业套餐
+      return [tableData.spanMergeCount[1],1]
+    }else{
+      return [0,0]
+    }
+  }
+  // 45万 70万 医药、消费、科技、智造的升级
+  if([5,6,23,24,25,26,12].includes(row.ServiceTemplateId)){
+    if(columnIndex==1){
+      return [1,2]
+    }else if(columnIndex==2){
+      return [0,0]
+    }
+  }
+  if([1,3,4].includes(columnIndex)){
+    if([15,17,19,21].includes(row.ServiceTemplateId)){
+      // 医药、消费、科技、智造的主观
+      return [2,1]
+    }else if([16,18,20,22].includes(row.ServiceTemplateId)){
+      // 医药、消费、科技、智造的客观
+      return [0,0]
+    }
+  }
+}
+
+defineExpose({
+  selectAllArr,
+  checkList,
+  tableData
+})
+
+//   初始化数据
+watch(()=>props.serviceData,()=>{
+  initTableData();
+},
+{immediate:true})
+
+</script>
+
+<template>
+  <el-table border :data="tableData.list" style="width: 1000px" :span-method="objectSpanMethod">
+    <el-table-column label="套餐类型" width="200" align="center">
+      <template #default="scope">
+        <el-radio :disabled="!canEdit" v-model="tableData.radio" :label="scope.row.grandFatherName" @change="handleRadioChange" style="width: 100%; text-align: left; padding-left: 50px">{{
+          scope.row.grandFatherName
+        }}</el-radio>
+      </template>
+    </el-table-column>
+
+    <el-table-column>
+      <template #default="scope">
+        <el-checkbox :disabled="scope.row.disable" style="width: 100%; text-align: left; padding-left: 50px" 
+        v-model="selectAllArr.find(item => item.name == scope.row.fatherName).checkAll" 
+        :indeterminate="selectAllArr.find(item => item.name == scope.row.fatherName).isIndeterminate"
+          v-if="haveChildList.includes(scope.row.fatherName)"  @change="handleCheckAllChange(scope.row)">
+          {{scope.row.fatherName}}
+        </el-checkbox>
+        <el-checkbox-group v-model="checkList" @change="handleChange($event,scope.row)"  v-else>
+          <el-checkbox :label="scope.row.fatherName" :disabled="scope.row.disable" style="width: 100%; text-align: left; padding-left: 50px"></el-checkbox>
+        </el-checkbox-group>
+      </template>
+    </el-table-column>
+    <el-table-column>
+      <template #default="scope">
+        <el-checkbox-group v-model="checkList" @change="handleChange($event,scope.row)">
+          <el-checkbox :label="scope.row.fatherName+'('+scope.row.Title+')'" 
+           :disabled="scope.row.disable" style="width: 100%; text-align: left; padding-left: 50px">
+            {{scope.row.Title}}
+          </el-checkbox>
+        </el-checkbox-group>
+      </template>
+    </el-table-column>
+    <el-table-column width="200">
+      <template #default="scope">
+        <span style="cursor: pointer; color: #409eff; padding-left: 50px" v-if="showText(scope.row)" @click="handleShow(scope.row)">{{ scope.row.text1 }}</span>
+      </template>
+    </el-table-column>
+    <el-table-column width="200" align="center">
+      <template #default="scope">
+        <a :href="scope.row.showValue + '?response-content-type=application/octet-stream'" download style="cursor: pointer; color: #409eff" v-if="showText(scope.row)">{{
+          scope.row.text2
+        }}</a>
+      </template>
+    </el-table-column>
+  </el-table>
+</template>
+
+<style lang="scss" scoped></style>

+ 831 - 0
src/views/contract_manage/components/ServiceDialog.vue

@@ -0,0 +1,831 @@
+<script setup>
+import html2canvas from "html2canvas";
+import { contractInterface } from "@/api/api.js";
+import { ref,reactive,watch } from "vue";
+import { ElMessage } from "element-plus";
+
+const props = defineProps({
+  serviceCon: null,
+  serviceShow: {
+    type: Boolean,
+    default: false,
+  },
+  contractType:''
+});
+
+const emits=defineEmits(['serviceSave','serviceClose'])
+
+const showOpt=ref(false)//选择权限弹窗
+const optionLists=ref([]) //权限列表数据
+const tableHeadData=ref([]) //表头数据
+const tableData=ref([]) //表格数据
+const roleType=ref(localStorage.getItem("Role"))
+const tableSelectList=reactive({
+  商品复盘: [
+    { id: 2, name: "能化专栏《化里化外》", select: false },
+    { id: 4, name: "黑色专栏《知白守黑》", select: false },
+    { id: 5, name: "有色专栏《有声有色》", select: false },
+    // { id: 1, name: "《每日宏观商品复盘》", select: false },
+    { id: 3, name: "《股债日评》", select: false },
+  ],
+  深度月报:[
+    { id: 6, name: "宏观经济", select: false },
+    { id: 7, name: "草根调研", select: false },
+    // { id: 8, name: "PVC月报", select: false },
+  ]
+}) //表格中自带选择的数据
+const tableSelectCheck=reactive({
+  商品复盘: [],
+}) //表格中自带选择的数据选中项
+
+const position=reactive({
+  top: 0,
+  left: 0,
+}) //鼠标右击时的位置
+const showRightClickMenu=ref(false) //显示右键菜单
+const rightClickCon=ref([
+  { type: "selectRow", name: "选择该行" },
+  { type: "insertColumn", name: "插入一列" },
+  { type: "insertRow", name: "插入一行" },
+  { type: "deleteColumn", name: "删除该列" },
+  { type: "deleteRow", name: "删除该行" },
+]) //右键菜单内容
+
+const showInputHead=ref(false) //显示填写表头
+const form=reactive({
+  title: "",
+}) //插入一列填写的表头数据
+
+const formRule=reactive({
+  title: [{ required: true, message: "请填写名称", trigger: "blur" }],
+})
+
+const selectIndex=reactive({
+  rindex: 0, //行序号
+  cindex: 0, //列序号
+})
+const selectRowIndex=ref(null) //选择该行的序列
+
+// 初始化表格数据
+watch(()=>props.serviceCon,()=>{
+  initData();
+},{
+  // 开启深度监听,监听到‘补充协议’与其他合同类型切换时,对象里面客观经济的选中变化
+  deep:true
+})
+
+//选择上面选项更新表格数据
+// optionLists: {
+//   handler(nval, oval) {
+//     if (this.selectRowIndex === null) return;
+//     let arr = [];
+//     let arrId = [];
+
+//     let count = 0;
+//     nval.forEach((item) => {
+//       if (item.CheckAll) {
+//         count++;
+//       }
+//     });
+//     //全选
+//     if (count === nval.length) {
+//       arr = ["全品种"];
+//       nval.forEach((item) => {
+//         arrId = [...arrId, ...item.CheckList];
+//       });
+//     } else {
+//       nval.forEach((item) => {
+//         item.Items.forEach((item2) => {
+//           let flag = item.CheckList.indexOf(item2.ChartPermissionId);
+//           if (flag != -1) {
+//             arr.push(item2.PermissionName);
+//             arrId.push(item2.ChartPermissionId);
+//           }
+//         });
+//       });
+//     }
+
+//     // console.log(arr);
+//     this.tableData[this.selectRowIndex].forEach((item) => {
+//       if (item.HeadName === "品种") {
+//         item.Value = arr.join("、");
+//         item.ValueId = arrId;
+//       }
+//     });
+//   },
+//   deep: true,
+// },
+
+// 如果没有选择任何行则重置顶部选项数据
+watch(selectRowIndex,(nval, oval)=>{
+  if (nval === null) {
+    optionLists.value.forEach((item) => {
+      item.CheckList = [];
+    });
+  }
+})
+
+const initData=()=>{
+  console.log("初始化");
+  if (!props.serviceCon.Detail) return;
+  let temarr = props.serviceCon.Detail.map((rowItem) => {
+    let rowArr = [];
+    for (let key in rowItem) {
+      if (key.substr(0, 3) === "Col" && rowItem[key] !== "") {
+        rowArr.push(JSON.parse(rowItem[key]));
+      }
+    }
+    return rowArr;
+  });
+
+  tableHeadData.value = temarr[0];
+  tableData.value = temarr.slice(1);
+  // 回显表格内部选择的
+  tableData.value.forEach((item) => {
+    item.forEach((e) => {
+      if (e.Type === "select") {
+        let key = e.Value;
+        item.forEach((e2) => {
+          if (e2.HeadName === "品种") {
+            if(e2.Value){
+              tableSelectCheck[key] = e2.ValueId;
+            }else{
+              tableSelectCheck[key] = [];
+            }
+          }
+        });
+      }
+    });
+  });
+}
+
+//点击保存选择的权限数据
+const handleSaveOpt=()=>{
+  if (selectRowIndex.value === null) return;
+  let arr=[]
+  let arrId=[]
+  let count = 0
+  optionLists.value.forEach((item) => {
+    if (item.CheckAll) {
+      count++;
+    }
+  });
+  // 全选
+  if(count===optionLists.value.length){
+    arr = ["全品种"];
+    optionLists.value.forEach((item) => {
+      arrId = [...arrId, ...item.CheckList];
+    });
+  }else{
+    optionLists.value.forEach((item) => {
+      item.Items.forEach((item2) => {
+        let flag = item.CheckList.indexOf(item2.ChartPermissionId);
+        if (flag != -1) {
+          arr.push(item2.PermissionName);
+          arrId.push(item2.ChartPermissionId);
+        }
+      });
+    });
+  }
+
+  // 找出和该行关联的行 同时修改品种栏数据
+  let rowIndexarr=[]
+  if(!tableData.value[selectRowIndex.value][0].RowName){
+    rowIndexarr.push(selectRowIndex.value)
+  }else{
+    tableData.value.forEach((item,index)=>{
+      if(item[0].RowName==tableData.value[selectRowIndex.value][0].RowName){
+        rowIndexarr.push(index)
+      }
+    })
+  }
+  
+  console.log(rowIndexarr);
+
+  rowIndexarr.forEach(index=>{
+    tableData.value[index].forEach((item) => {
+      if (item.HeadName === "品种") {
+        item.Value = arr.join("、");
+        item.ValueId = arrId;
+      }
+    });
+  })
+
+  // this.tableData[this.selectRowIndex].forEach((item) => {
+  //   if (item.HeadName === "品种") {
+  //     item.Value = arr.join("、");
+  //     item.ValueId = arrId;
+  //   }
+  // });
+  showOpt.value=false
+}
+
+// 点击关闭选择权限弹窗
+const closeOpt=()=>{
+  showOpt.value=false
+  selectRowIndex.value=null
+}
+
+// 左键选择行
+const handleSelectRow=(rindex,data)=>{
+  // 如果选择的行存在 选项数据则不允许选择 或者 该行不可选择 即RowDisable=true
+  if(data.HeadName!='品种') return
+  let tag = false;
+  tableData.value[rindex].forEach((item) => {
+    if (item.Type === "select"||item.RowDisable) {
+      tag = true;
+    }
+  });
+  if (tag) return;
+  selectRowIndex.value = rindex;
+  formatOptionList();
+  showOpt.value=true
+}
+
+//获取顶部权限选项
+const getPermissionOpt=()=>{
+  let CompanyType = localStorage.getItem("Role") === "ficc_seller" ? "ficc" : "权益";
+  contractInterface.getPermissionList({ CompanyType }).then((res) => {
+    if (res.Ret === 200) {
+      let arr = res.Data.List;
+      arr.forEach((item) => {
+        item.CheckList = [];
+        item.CheckAll = false;
+        item.indeterminate = false;
+      });
+      optionLists.value = arr;
+    }
+  });
+}
+
+//每次选中一行时格式化顶部选择数据
+const formatOptionList=()=> {
+  let valueId = [];
+  tableData.value[selectRowIndex.value].forEach((item) => {
+    if (item.HeadName === "品种") {
+      valueId = item.ValueId;
+    }
+  });
+
+  optionLists.value.forEach((item) => {
+    item.CheckList = [];
+    item.Items.forEach((e) => {
+      let flag = valueId.indexOf(e.ChartPermissionId);
+      if (flag != -1) {
+        item.CheckList.push(e.ChartPermissionId);
+      }
+    });
+    if (item.CheckList.length === item.Items.length) {
+      item.CheckAll = true;
+    } else {
+      item.CheckAll = false;
+    }
+  });
+}
+
+//全选
+const handleCheckAllChange=(e)=>{
+  let arr = e.Items.map((item) => {
+    return item.ChartPermissionId;
+  });
+  e.CheckList = e.CheckAll ? arr : [];
+  e.indeterminate = false;
+  // 需求更改,合同类型为补充协议时不默认勾选宏观经济
+  if(e.ClassifyName==='宏观经济'&&props.contractType!=='补充协议'){
+    e.CheckList.push(1)
+  }
+}
+
+//选择单个
+const handleCheckChange=(e)=>{
+  e.CheckAll = e.CheckList.length === e.Items.length;
+  e.indeterminate = e.CheckList.length > 0 && e.CheckList.length < e.Items.length;
+}
+
+//点击表格中选项数据
+const handleTableSelectChange=(title, rindex)=>{
+  let arr = tableSelectCheck[title];
+  let arr2 = [];
+  tableSelectList[title].forEach((item) => {
+    arr.forEach((e) => {
+      if (e == item.id) {
+        arr2.push(item.name);
+      }
+    });
+  });
+  tableData.value[rindex].forEach((item) => {
+    if (item.HeadName === "品种") {
+      item.Value = arr2.join("、");
+      item.ValueId = arr;
+    }
+  });
+}
+
+//鼠标右键
+const rightClick=(rindex, cindex, event)=>{
+  selectIndex.rindex = Number(rindex);
+  selectIndex.cindex = Number(cindex);
+  formatRightClickCon(rindex, cindex);
+  showRightClickMenu.value = true;
+  position.top = event.clientY + "px";
+  position.left = event.clientX + "px";
+}
+
+//格式化鼠标右击显示内容
+const formatRightClickCon=(rindex, cindex)=>{
+  let arr = [
+    { type: "insertColumn", name: "向后插入一列", show: true },
+    { type: "insertRow", name: "向后插入一行", show: true },
+    { type: "deleteColumn", name: "删除该列", show: true },
+    { type: "deleteRow", name: "删除该行", show: true },
+  ];
+
+  // 品种一列不允许删除
+  if (tableHeadData.value[cindex].Tag === "品种"||tableHeadData.value[cindex].Tag === "FICC小套餐服务内容") {
+    arr[2].show = false;
+  }
+  //删除列 不能少于两列
+  if (tableHeadData.value.length <= 2) {
+    arr[2].show = false;
+  }
+
+  //删除行 不能少于两行 并且商品复盘、周报、双周报、数据点评、月报必须有一个存在
+  if (tableData.value.length <= 2) {
+    arr[3].show = false;
+  }
+
+  let temarr=[]
+  tableData.value.forEach(item=>{
+    item.forEach(item2=>{
+      if(item2.HeadName==='FICC小套餐服务内容'){
+        if(item2.Value==='数据点评'||
+        item2.Value==='FICC周报'||
+        item2.Value==='商品双周报+线上电话会讨论会<br/>(由弘则的研究员主持线上讨论)'){
+          temarr.push(item2.Value)
+        }
+      }
+    })
+  })
+  if(temarr.length<2){
+    tableData.value[selectIndex.rindex].forEach(item=>{
+      if(item.Value==='数据点评'||
+        item.Value==='FICC周报'||
+        item.Value==='商品双周报+线上电话会讨论会<br/>(由弘则的研究员主持线上讨论)'){
+          arr[3].show = false;
+      }
+    })
+  }
+
+  //新增列 不能超过6列
+  if (tableHeadData.value.length >= 6) {
+    arr[0].show = false;
+  }
+
+  rightClickCon.value = arr.filter((item) => {
+    return item.show;
+  });
+}
+
+// 点击 新增/删除 行/列  选择该行
+const handleUpdateTable=(type)=>{
+  //删除行
+  if (type === "deleteRow") {
+    selectRowIndex.value = null;
+    tableData.value.splice(selectIndex.rindex, 1);
+  }
+
+  //新增行
+  if (type === "insertRow") {
+    selectRowIndex.value = null;
+    let arr = tableHeadData.value.map((item) => {
+      let obj = { CanEdit: true, Type: "text", Value: "", ValueId: [], HeadName: item.Tag,RowDisable:false,RowName:''};
+      if (item.Tag === "品种") {
+        obj.CanEdit = false;
+      }
+      return obj;
+    });
+
+    tableData.value.splice(selectIndex.rindex + 1, 0, arr);
+  }
+
+  //删除列
+  if (type === "deleteColumn") {
+    selectRowIndex.value = null;
+    tableHeadData.value.splice(selectIndex.cindex, 1);
+    tableData.value = tableData.value.map((item) => {
+      item.splice(selectIndex.cindex, 1);
+      return item;
+    });
+  }
+
+  //新增列
+  if (type === "insertColumn") {
+    selectRowIndex.value = null;
+    showInputHead.value = true;
+  }
+
+  showRightClickMenu.value = false;
+}
+
+const headTitleForm=ref(null)
+
+//点击确定新增表头内容
+const handleConfirmHead=()=>{
+  headTitleForm.value.validate((valid) => {
+    if (!valid) return;
+    tableHeadData.value.splice(selectIndex.cindex + 1, 0, { CanEdit: false, Type: "text", Value: form.title, Tag: form.title });
+    tableData.value = tableData.value.map((item) => {
+      item.splice(selectIndex.cindex + 1, 0, { CanEdit: true, Type: "text", Value: "", HeadName: form.title,RowDisable:false,RowName:'' });
+      return item;
+    });
+    showInputHead.value = false;
+    form.title = "";
+  });
+}
+
+
+//点击取消填写新增列头弹窗
+const handleCancelHead=()=>{
+  headTitleForm.value.resetFields();
+  showInputHead.value = false;
+}
+
+//点击保存
+const handleSave=()=>{
+  let flag = validateData();
+  if (!flag) return;
+
+  // 生成表格图片
+  html2canvas(document.getElementById("table-png"), {
+    backgroundColor: "#ffffff",
+    useCORS: true, // 允许图片跨域
+    allowTaint: true, // 在渲染前测试图片
+    imageTimeout: 0, // 加载延时
+    scale:3,
+  }).then((res) => {
+    let img = res.toDataURL("image/png");
+    emits("serviceSave", {
+      Value: img,
+      ServiceTemplateId: props.serviceCon.ServiceTemplateId,
+      tableData: tableData.value,
+      tableHeadData: tableHeadData.value,
+    });
+    handleServiceClose();
+  });
+}
+
+//点击取消
+const handleCancel=()=>{
+  initData()
+  handleServiceClose();
+}
+
+//校验数据
+const validateData=()=>{
+  //判断品种列是否有值
+  let arr = [];
+  tableData.value.forEach((item) => {
+    item.forEach((item2) => {
+      if (item2.HeadName === "品种") {
+        arr.push(...item2.ValueId);
+      }
+    });
+  });
+  // 判断行是否有值
+  let arr2 = [];
+  tableData.value.forEach((item, index) => {
+    let arr = item.filter((item2) => {
+      if (!item2.Value) return item2;
+    });
+    if (arr.length === tableHeadData.value.length) {
+      arr2.push(index);
+    }
+  });
+
+  // 商品复盘、周报、双周报、数据点评、月报 品种必须有一个选择了
+  let arr3=[]
+  tableData.value.forEach(item=>{
+    item.forEach(item2=>{
+      if(item2.Value==='数据点评'||
+        item2.Value==='FICC周报'||
+        item2.Value==='商品双周报+线上电话会讨论会<br/>(由弘则的研究员主持线上讨论)'){
+          item.forEach(item3=>{
+            if (item3.HeadName === "品种") {
+              arr3.push(...item3.ValueId);
+            }
+          })
+      }
+    })
+  })
+
+  let constractType=props.contractType
+  console.log(constractType);
+  if (!arr.length&&constractType!=='补充协议') {
+    ElMessage.warning("至少选择一个品种");
+    return false;
+  }
+
+  if (arr2.length) {
+    ElMessage.warning("行内至少填一项");
+    return false;
+  }
+
+  if(!arr3.length&&constractType!=='补充协议'){
+    ElMessage.warning("周报、双周报、数据点评至少选择一个品种");
+    return false;
+  }
+
+  return true;
+}
+
+//关闭弹窗
+const handleServiceClose=()=>{
+  showRightClickMenu.value = false;
+  selectRowIndex.value = null;
+  emits("serviceClose");
+}
+
+defineExpose({
+  tableHeadData,tableData
+})
+
+getPermissionOpt();
+</script>
+
+<template>
+  <div class="service-content-wrap">
+    <!-- 大套餐或其他等直接查看图片类型的 -->
+    <el-dialog v-dialogDrag top="5vh" :model-value="props.serviceShow" class="self-dialog-c" :modal-append-to-body="false" @close="handleServiceClose" :show-close="false" v-if="!serviceCon.Detail">
+      <!-- <h2 class="title">{{ serviceCon.Title }}</h2> -->
+      <template #header>
+        <!-- 权益合同和ficc合同有别 -->
+        {{roleType}}
+        <h2 class="title">{{roleType == 'ficc_seller'?serviceCon.Title:serviceCon.showTitle }}</h2>
+      </template>
+      <img class="img" style="width: 100%; display: block; margin: 0 auto 20px auto" 
+      :src="roleType == 'ficc_seller'?serviceCon.Value:serviceCon.showValue" />
+      <div style="text-align: center; margin-bottom: 30px">
+        <el-button type="primary" @click="handleServiceClose">知道了</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 小套餐 -->
+    <el-dialog v-dialogDrag title="提示" width="65%" top="5vh"  :model-value="props.serviceShow" :modal-append-to-body="false" @close="handleCancel"  v-else>
+      <template #header>
+        <img width="20" src="../../../assets/img/constract/select.png"  style="vertical-align: middle;margin-right: 4px" />
+        <span style="vertical-align: middle">选择品种</span>
+      </template>
+
+      <!-- 选择种类部分  -->
+      <!-- <div class="type-select-wrap">
+        <h2>权限设置</h2>
+        <div class="type-select-box">
+          <div class="item flex" v-for="item in optionLists" :key="item.ClassifyName" style="margin-bottom: 20px">
+            <el-checkbox
+              :disabled="selectRowIndex === null"
+              :indeterminate="item.CheckList.length > 0 && item.CheckList.length < item.Items.length"
+              v-model="item.CheckAll"
+              @change="handleCheckAllChange(item)"
+              >{{ item.ClassifyName }}:</el-checkbox
+            >
+            <el-checkbox-group :disabled="selectRowIndex === null" v-model="item.CheckList" @change="handleCheckChange(item)">
+              <el-checkbox :label="tag.ChartPermissionId" v-for="tag in item.Items" :key="tag.ChartPermissionId">{{ tag.PermissionName }}</el-checkbox>
+            </el-checkbox-group>
+          </div>
+        </div>
+      </div> -->
+
+      <!-- 表格部分 -->
+      <div style="max-height: 70vh; overflow-y: auto; padding: 10px 0">
+        <table id="table" ref="table" class="table-wrap" @click="showRightClickMenu = false">
+          <thead>
+            <tr style="background: #f0f2f5">
+              <th class="table-item" v-for="item in tableHeadData" :key="item.Value">{{ item.Value }}</th>
+            </tr>
+          </thead>
+
+          <tbody>
+            <tr v-for="(row, rindex) in tableData" :key="rindex" :class="rindex === selectRowIndex ? 'row-dark' : null" >
+              <td 
+                class="table-item" 
+                v-for="(item, cindex) in row" 
+                :key="item" 
+                @click="handleSelectRow(rindex,item)" 
+                @contextmenu.prevent="rightClick(rindex, cindex, $event)" 
+                :data-rindex="rindex" 
+                :data-cindex="cindex"
+              >
+                <div v-if="item.Type === 'text'">
+                  <img 
+                    class="choose-icon" 
+                    width="14" 
+                    src="../../../assets/img/constract/icon-1.png" 
+                    alt="" 
+                    v-if="item.HeadName=='品种'&&!item.RowDisable"
+                  />
+                  <span 
+                    v-if="!item.CanEdit" 
+                    v-html="item.Value" 
+                    :style="{paddingLeft:item.HeadName=='品种'&&!item.RowDisable?'15px':null,display:'inline-block'}"
+                  ></span>
+                  <el-input v-else type="textarea" placeholder="请输入" v-model="item.Value"></el-input>
+                </div>
+                <div v-if="item.Type === 'select'">
+                  <div style="margin-bottom: 10px;font-size:15px">{{ item.Value }}</div>
+                  <div style="text-align: left">
+                    <el-checkbox-group v-model="tableSelectCheck[item.Value]">
+                      <el-checkbox style="font-size:14px;height: 19px" :label="opt.id" 
+                      v-for="opt in tableSelectList[item.Value]" :key="opt.id" @change="handleTableSelectChange(item.Value, rindex, cindex)">{{ opt.name }}</el-checkbox>
+                    </el-checkbox-group>
+                  </div>
+                </div>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <div style="margin: 40px 0; text-align: center">
+        <el-button type="primary" style="margin-right: 44px" @click="handleSave" size="large">保存</el-button>
+        <el-button type="primary" plain @click="handleCancel" size="large">取消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 权限选择弹窗 -->
+    <el-dialog v-model="showOpt" :modal-append-to-body="false" @close="closeOpt" v-dialogDrag>
+      <template #header>
+        <img style="vertical-align: middle;margin-right: 4px;" width="20" src="../../../assets/img/icons/add_icon.png" alt="" />
+        <span style="vertical-align: middle">选择品种</span>
+      </template>
+      <div class="type-select-wrap">
+        <div class="type-select-box">
+          <div class="item flex" v-for="item in optionLists" :key="item.ClassifyName" style="margin-bottom: 30px">
+            <el-checkbox
+              :disabled="selectRowIndex === null"
+              :indeterminate="item.CheckList.length > 0 && item.CheckList.length < item.Items.length"
+              v-model="item.CheckAll"
+              @change="handleCheckAllChange(item)"
+              >{{ item.ClassifyName }}:</el-checkbox
+            >
+            <el-checkbox-group :disabled="selectRowIndex === null" v-model="item.CheckList" @change="handleCheckChange(item)">
+              <el-checkbox :disabled="contractType!=='补充协议'&&tag.PermissionName==='宏观经济'" :label="tag.ChartPermissionId" v-for="tag in item.Items" :key="tag.ChartPermissionId">{{ tag.PermissionName }}</el-checkbox>
+            </el-checkbox-group>
+          </div>
+        </div>
+        <div style="text-align:center">
+          <el-button type="primary" @click="handleSaveOpt" size="large">保存</el-button>
+          <el-button type="primary" plain @click="closeOpt" size="large">取消</el-button>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 新增列填写表头弹窗 -->
+    <el-dialog v-model="showInputHead" :modal-append-to-body="false" width="560px" top="20vh" v-dialogDrag>
+      <template #header>
+        <img style="vertical-align: middle" width="20" src="../../../assets/img/icons/add_icon.png" alt="" />
+        <span style="vertical-align: middle">添加列</span>
+      </template>
+      <el-form :model="form" ref="headTitleForm" :rules="formRule" label-width="100px" @submit.native.prevent>
+        <el-form-item label="表格名称" prop="title">
+          <el-input v-model="form.title"></el-input>
+        </el-form-item>
+        <div style="text-align: center; margin-top: 70px; margin-bottom: 30px">
+          <el-button type="primary" @click="handleConfirmHead" size="large">保存</el-button>
+          <el-button type="primary" plain @click="handleCancelHead" size="large">取消</el-button>
+        </div>
+      </el-form>
+    </el-dialog>
+
+    <!-- 右键选项弹框 -->
+    <div class="right-click-wrap" :style="position" v-show="showRightClickMenu">
+      <div @click="handleUpdateTable(item.type)" v-for="item in rightClickCon" :key="item.type">{{ item.name }}</div>
+    </div>
+
+    <!-- 生成表格图片dom -->
+    <table id="table-png" class="table-wrap">
+      <thead>
+        <tr style="background: #f0f2f5">
+          <th class="table-item" v-for="item in tableHeadData" :key="item.Value" style="color: #333;font-size:15px">{{ item.Value }}</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr v-for="(row, rindex) in tableData" :key="rindex">
+          <td class="table-item" v-for="item in row" :key="item" style="max-width: 300px">
+            <div v-html="item.Value" style="color: #333;font-size:14px"></div>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</template>
+
+<style>
+.self-dialog-c .el-dialog__header {
+  background-color: #fff;
+  padding: 15px 20px 0 20px !important;
+}
+.self-dialog-c{
+  width: 60%;
+}
+
+/* .el-checkbox{
+  margin-bottom: 20px;
+} */
+.table-item .el-checkbox__label {
+  font-size: 14px !important;
+}
+.type-select-wrap .el-checkbox{
+  margin-bottom: 10px;
+}
+.type-select-wrap .el-checkbox__label {
+  font-size: 14px !important;
+}
+</style>
+
+<style lang="scss" scoped>
+.img{
+  image-rendering: -moz-crisp-edges; 
+  image-rendering: -o-crisp-edges; 
+  image-rendering: -webkit-optimize-contrast; 
+  image-rendering: crisp-edges; 
+  -ms-interpolation-mode: nearest-neighbor;
+}
+
+
+.self-dialog-c .title {
+  text-align: center;
+  font-size: 18px;
+  color: #333;
+}
+.flex {
+  display: flex;
+}
+.table-wrap {
+  position: relative;
+  width: 100%;
+  text-align: center;
+  border-top: 1px solid #ebeef5;
+  border-left: 1px solid #ebeef5;
+  .row-dark {
+    background-color: #deedff;
+  }
+  .table-item {
+    padding: 20px 10px;
+    border-right: 1px solid #ebeef5;
+    border-bottom: 1px solid #ebeef5;
+    min-width: 160px;
+    position: relative;
+    .table-item-mask {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background-color: rgba(0, 0, 0, 0);
+      z-index: 1000;
+    }
+    .choose-icon{
+      position: absolute;
+      top: 50%;
+      left: 10px;
+      transform:translateY(-50%);
+    }
+  }
+}
+.right-click-wrap {
+  border-radius: 4px;
+  background-color: #fff;
+  padding: 10px 0;
+  position: fixed;
+  z-index: 5000;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  line-height: 2;
+  div {
+    cursor: pointer;
+    padding: 0 20px;
+    &:hover {
+      background-color: #ebeef5;
+    }
+  }
+}
+
+.type-select-wrap {
+  margin-bottom: 30px;
+  .type-select-box {
+    // margin-top: 20px;
+    padding: 20px 30px 0 30px;
+    border: 1px dashed #aab4cc;
+    border-radius: 4px;
+    margin-bottom: 20px;
+  }
+}
+
+
+#table-png {
+  position: absolute;
+  z-index: -10;
+  top: -100%;
+  left: 0;
+  width: 1000px;
+}
+</style>

+ 480 - 3
src/views/contract_manage/contractDetail.vue

@@ -1,9 +1,486 @@
+
 <script setup>
+import { ref,reactive,computed,watch } from "vue";
+import { InfoFilled } from '@element-plus/icons-vue'
+
+import QyServiceTable from "./components/QyServiceTable.vue"; //权益服务内容表格组件
+import FiccServiceTable from "./components/FiccServiceTable.vue"; //ficc服务内容表格组件
+import { contractInterface } from "@/api/api.js";
+import {CalculationDate} from '@/utils/CalculationDate'
+import { useRouter,useRoute} from 'vue-router';
+const $router = useRouter()
+const $route = useRoute()
+  // beforeRouteLeave(to, from, next)  {
+  //   from.matched[0].name='合同管理'
+  //   next()
+  // },
+
+const RoleType=ref(localStorage.getItem("Role") || "")
+const contractId=ref($route.query.contractId)
+const operationList=ref([])//操作记录
+const formData=ref({}) //合同详情数据
+const radio=ref("1") //用于显示底部是否有备注内容
+const ficcServiceData=ref(null) //ficc 底部表格数据
+const qyServiceData=ref(null) //权益底部表格数据
+
+const serviceShow=ref(false) //是否显示查看报价单
+const serviceCon=ref({}) //选择的服务项 查看报价单/选择品种
+
+const showEdit=ref(false)//是否显示编辑按钮
+
+
+// filters
+const formatPrice=(str)=>{
+  if(!str) return ''
+  str=str.toString()
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  return num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+// 金额转中文大写
+const digitUppercase=(n)=>{
+  let fraction = ["角", "分"];
+  let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+  let unit = [
+    ["元", "万", "亿"],
+    ["", "拾", "佰", "仟"],
+  ];
+  let head = n < 0 ? "欠" : "";
+  n = Math.abs(n);
+  let s = "";
+  for (let i = 0; i < fraction.length; i++) {
+    s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, "");
+  }
+  // s = s || "整";
+
+  n = Math.floor(n);
+  for (let i = 0; i < unit[0].length && n > 0; i++) {
+    let p = "";
+    for (let j = 0; j < unit[1].length && n > 0; j++) {
+      p = digit[n % 10] + unit[1][j] + p;
+      n = Math.floor(n / 10);
+    }
+    s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s;
+  }
+  return (
+    head + s.replace(/(零.)*零元/, "元").replace(/(零.)+/g, "零")
+    // .replace(/^整$/, "零元整")
+  );
+}
+
+//计算多少年
+const formateYear=(e)=>{
+  if (e[0]) {
+    return `有效期为${CalculationDate(e[0],e[1])}`
+  } else {
+    return "";
+  }
+}
+
+//前往预览合同
+const handleGoPreview=()=>{
+  let {href} = $router.resolve({path:"/contractdtl",query:{contractid:contractId.value}});
+  window.open(href,'_blank');
+}
+
+//获取合同操作记录
+const getContractOperationList=()=>{
+  contractInterface.getContractOperationList({ContractId:contractId.value}).then(res=>{
+    if(res.Ret===200){
+      operationList.value=res.Data.List&&res.Data.List.map(item=>{
+        return {...item,CreateTimeStr:item.CreateTimeStr.replace(/-/g,'.')}
+      })||[]
+    }
+  })
+}
+
+//点击编辑 跳转编辑页
+const handleGoEdit=()=> {
+  $router.push({
+    path: "/editcontract",
+    query: {
+      contractId: contractId.value,
+      type: "edit",
+    },
+  });
+}
+
+//显示查看报价单弹窗
+const handleShowService=(e)=>{
+  console.log(e);
+  // 小套餐情况处理表格数据
+  if (e.Detail) {
+    let temarr = e.Detail.map((rowItem) => {
+      let rowArr = [];
+      for (let key in rowItem) {
+        if (key.substr(0, 3) === "Col" && rowItem[key] !== "") {
+          rowArr.push(JSON.parse(rowItem[key]));
+        }
+      }
+      return rowArr;
+    });
+    serviceCon.value = { ...e, tableHeadData: temarr[0], tableData: temarr.slice(1) };
+  } else {
+    serviceCon.value = e;
+  }
+  serviceShow.value = true;
+}
+
+//关闭查看报价单弹窗
+const serviceClose=()=>{
+  serviceShow.value = false;
+}
+
+//获取服务套餐模板数据
+const getServiceList=()=>{
+  contractInterface.getServiceList({ ProductId: formData.value.ProductId }).then((res) => {
+    if (res.Ret === 200) {
+      if (formData.value.ProductId === 1) {
+        ficcServiceData.value = res.Data;
+      } else {
+        qyServiceData.value = res.Data;
+      }
+    }
+  });
+}
+
+// 获取合同详情
+const getDetail=()=>{
+  contractInterface.getContractDetail({ ContractId: Number(contractId.value) }).then((res) => {
+    if (res.Ret === 200) {
+      formData.value = { ...res.Data, timeRange: [res.Data.StartDate, res.Data.EndDate] };
+      if(res.Data.RelationContractDetailList.length>0){
+        let arr=[]
+        res.Data.RelationContractDetailList.forEach(item=>{
+          arr.push(item.CompanyName)
+        })
+        formData.value.PayChannel=arr.join('、')
+      }
+      if (res.Data.Remark) {
+        radio.value = "1";
+      } else {
+        radio.value = "2";
+      }
+      // 本人的合同并且合同状态不为 已审批、待审批、已作废、已签回、已解约 则显示编辑
+      let userid=localStorage.getItem('AdminId')
+      if(userid==res.Data.SellerId
+        &&res.Data.Status!=='待审批'
+        &&res.Data.Status!=='已审批'
+        &&res.Data.Status!=='已作废'
+        &&res.Data.Status!=='已签回'
+        &&res.Data.Status!=='已解约'){
+        showEdit.value=true
+      }else{
+        showEdit.value=false
+      }
+      getServiceList();
+    }
+  });
+}
+
+getDetail();
+getContractOperationList()
 
 </script>
 
 <template>
-    <div>
-        
+  <div class="flex addconstract-container">
+    <el-form ref="form" :model="formData" label-position="left" label-width="110px" style="width: 80%" size="large">
+      <section class="section">
+        <h2 class="section-title">客户信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="甲方名称" prop="customeName" style="width: 50%">
+              <el-input v-model="formData.CompanyName" placeholder="请输入或者搜索客户名称" style="width: 350px" disabled></el-input>
+            </el-form-item>
+            <el-form-item label="社会信用码" prop="customeXYM" style="width: 50%">
+              <el-input v-model="formData.CreditCode" placeholder="请输入社会信用码" style="width: 350px" disabled></el-input>
+            </el-form-item>
+          </div>
+
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="公司地址" prop="province" style="width: 50%">
+              <el-input :value="formData.Province + formData.City" disabled style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="详细地址" prop="address" style="width: 50%">
+              <el-input :value="formData.Address" disabled placeholder="请输入详细地址" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="传真" prop="customeCz" style="width: 50%">
+              <el-input v-model="formData.Fax" disabled placeholder="请输入传真" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="电话" prop="customeTel" style="width: 50%">
+              <el-input v-model="formData.Phone" disabled placeholder="请输入电话" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <el-form-item label="邮编" prop="postCode" class="border-top">
+            <el-input v-model="formData.Postcode" disabled placeholder="请输入邮编" style="width: 350px"></el-input>
+          </el-form-item>
+        </div>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">合同信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="合同编号" style="width: 50%">
+              <span>{{ formData.ContractCode }}</span>
+            </el-form-item>
+            <el-form-item label="合同归属" style="width: 50%">
+              <span>{{ formData.ProductId === 1 ? "ficc" : "权益" }}</span>
+            </el-form-item>
+          </div>
+          <el-form-item label="合同类型" prop="constractType" class="border-top">
+            <el-radio-group v-model="formData.ContractType">
+              <div style="display:flex">
+                <div style="margin-right:10px;">
+                  <el-radio label="新签合同" disabled>新签合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>没有正式转试用记录的客户,在申请转正时提交的合同</template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right:10px">
+                  <el-radio label="续约合同" disabled>续约合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>
+                      1、有正式转试用记录的客户,在申请转正时提交的合同<br>
+										  2、所有客户在续约申请时提交的合同
+                    </template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right:10px" v-if="RoleType!=='rai_seller'">
+                  <el-radio label="补充协议" disabled>补充协议</el-radio>
+                </div>
+              </div>
+            </el-radio-group>
+          </el-form-item>
+          <div class="flex border-top" v-if="formData.timeRange">
+            <el-form-item label="合同期限" prop="time" style="width: 50%">
+              <el-date-picker disabled v-model="formData.timeRange" type="daterange" range-separator="至" 
+              start-placeholder="开始日期" end-placeholder="结束日期" style="max-width:350px"> </el-date-picker>
+            </el-form-item>
+            <span style="line-height: 40px">{{ formateYear(formData.timeRange) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="合同金额" prop="price" style="width: 50%">
+              <el-input disabled :value="formatPrice(formData.OriginalPrice)" placeholder="请输入合同金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">大写:{{ digitUppercase(formData.OriginalPrice)  }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="优惠后金额" prop="price2" style="width: 50%">
+              <el-input disabled :value="formatPrice(formData.Price)" placeholder="请输入优惠后金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">大写:{{ digitUppercase(formData.Price) }}</span>
+          </div>
+
+          <el-form-item label="付款方式说明" prop="remark" class="border-top">
+            <el-input type="textarea" disabled v-model="formData.PayRemark" placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)" style="width: 80%"></el-input>
+          </el-form-item>
+          <el-form-item label="付款方" prop="PayChannel" class="border-top">
+            <el-input type="textarea" disabled v-model="formData.PayChannel" placeholder="代付,请填写代付的券商名称或期货公司名称;非代付,请填写无。(请勿填写现金/转账等支付形式)" style="width: 80%"></el-input>
+          </el-form-item>
+          <!-- <el-form-item label="备注" class="border-top">
+            <el-input type="textarea" disabled v-model="formData.SellerRemark" placeholder="审批人查看,不在生成合同中展示" style="width: 80%"></el-input>
+          </el-form-item> -->
+        </div>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">服务内容</h2>
+        <div class="section-container">
+          <!-- ficc 服务内容表格 -->
+          <FiccServiceTable
+            :canEdit="false"
+            :serviceData="ficcServiceData"
+            :hasSercive="formData.Service"
+            @handleShowService="handleShowService"
+            v-if="formData.ProductId === 1 && ficcServiceData"
+          ></FiccServiceTable>
+
+          <!-- 权益 服务内容表格 -->
+          <QyServiceTable
+            :canEdit="false"
+            :serviceData="qyServiceData"
+            :hasSercive="formData.Service"
+            @handleShowService="handleShowService"
+            v-if="formData.ProductId === 2 && qyServiceData"
+          ></QyServiceTable>
+        </div>
+
+        <p style="margin-top: 30px; margin-bottom: 20px">补充内容(eg额外赠送、路演次数规定)</p>
+        <el-radio v-model="radio" label="2" disabled>无</el-radio>
+        <el-radio v-model="radio" label="1" disabled>有</el-radio>
+        <el-input v-if="radio === '1'" disabled type="textarea" v-model="formData.Remark" rows="5" placeholder="请输入内容" style="margin: 20px 0; display: block; box-sizing: border-box"></el-input>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">审批备注</h2>
+        <div class="section-container">
+          <el-form-item label="备注" class="border-top">
+            <el-input type="textarea" disabled v-model="formData.SellerRemark" placeholder="请输入备注(仅供审批人查看,不在生成合同中展示)" style="width: 80%"></el-input>
+          </el-form-item>
+        </div>
+      </section>
+    </el-form>
+    <div class="right-wrap">
+      <div style="display: flex; justify-content: space-between">
+        <el-button type="primary" style="width: 45%" @click="handleGoEdit" v-if="showEdit" size="large">编辑</el-button>
+        <el-button type="primary" plain :style="{width: showEdit?'45%':'100%'}" @click="handleGoPreview" size="large">预览</el-button>
+      </div>
+      <div class="timeline-wrap">
+        <el-timeline>
+          <el-timeline-item color="#409EFF" v-for="item in operationList" :key="item.Id" placement="top" :timestamp="item.CreateTimeStr">
+            {{item.OpUserName}}{{ item.Remark }}
+          </el-timeline-item>
+        </el-timeline>
+      </div>
     </div>
-</template>
+
+    <!-- 查看报价单弹窗 -->
+    <el-dialog v-dialogDrag v-model="serviceShow" width="60%" class="self-dialog-c" :modal-append-to-body="false" @close="serviceClose" :show-close="false">
+      <h2 class="title" style="text-align: center; color: #000">{{ serviceCon.ProductId == '1'? serviceCon.Title : serviceCon.showTitle }}</h2>
+      <img class="img" style="width: 100%; display: block; margin: 20px auto" 
+      :src="serviceCon.ProductId == '1'? serviceCon.Value : serviceCon.showValue" />
+      <!-- <table v-else class="table-wrap">
+        <thead>
+          <tr style="background: #f0f2f5">
+            <th class="table-item" v-for="item in serviceCon.tableHeadData" :key="item.Value">{{ item.Value }}</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr v-for="(row, rindex) in serviceCon.tableData" :key="rindex" :class="rindex === selectRowIndex ? 'row-dark' : null">
+            <td class="table-item" v-for="item in row" :key="item">
+              <div>{{ item.Value }}</div>
+            </td>
+          </tr>
+        </tbody>
+      </table> -->
+      <div style="text-align: center; margin-bottom: 30px">
+        <el-button type="primary" @click="serviceShow =false">知道了</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<style>
+.el-radio__input.is-checked .el-radio__inner {
+  background-color: transparent;
+}
+.el-radio__inner::after {
+  width: 6px;
+  height: 6px;
+  background-color: #409eff;
+}
+.el-checkbox__label {
+  font-size: 16px !important;
+}
+.el-form-item {
+  margin-bottom: 30px;
+}
+.el-input.is-disabled .el-input__inner {
+  color: #606266;
+}
+.el-radio__input.is-disabled + span.el-radio__label {
+  color: #606266;
+}
+.el-range-editor.is-disabled input {
+  color: #606266;
+}
+.el-textarea.is-disabled .el-textarea__inner {
+  color: #606266;
+}
+.el-timeline-item__tail {
+  border-left: 2px solid #409eff;
+}
+.self-dialog-c .el-dialog__header {
+  background-color: #fff;
+  padding: 0;
+}
+.self-dialog-c{
+  width: auto;
+  max-width: 60%;
+}
+</style>
+
+<style lang="scss" scoped>
+.img{
+  image-rendering: -moz-crisp-edges; 
+  image-rendering: -o-crisp-edges; 
+  image-rendering: -webkit-optimize-contrast; 
+  image-rendering: crisp-edges; 
+  -ms-interpolation-mode: nearest-neighbor;
+}
+.addconstract-container {
+  min-height: calc(100vh - 250px);
+  position: relative;
+  font-size: 16px;
+  color: #000;
+}
+.flex {
+  display: flex;
+}
+.section {
+  background-color: #fff;
+  border: 1px solid #aab4cc;
+  border-radius: 4px;
+  padding: 20px;
+  margin-bottom: 20px;
+  .section-title {
+    margin-bottom: 30px;
+  }
+  .border-top {
+    padding-top: 30px;
+    border-top: 1px solid #dcdfe6;
+  }
+}
+
+.right-wrap {
+  margin-left: 20px;
+  flex: 1;
+  .timeline-wrap {
+    margin-top: 20px;
+    background-color: #fff;
+    border: 1px solid #aab4cc;
+    padding: 20px;
+    border-radius: 4px;
+    text-align: left;
+    height: calc(100% - 120px);
+    max-height: 1130px;
+    overflow-y: auto;
+  }
+}
+
+.table-wrap {
+  margin: 20px 0;
+  position: relative;
+  width: 100%;
+  text-align: center;
+  border-top: 1px solid #ebeef5;
+  border-left: 1px solid #ebeef5;
+  .row-dark {
+    background-color: #deedff;
+  }
+  .table-item {
+    padding: 12px 10px;
+    border-right: 1px solid #ebeef5;
+    border-bottom: 1px solid #ebeef5;
+    min-width: 200px;
+    position: relative;
+  }
+}
+</style>

+ 454 - 2
src/views/contract_manage/contractDetailDC.vue

@@ -1,7 +1,459 @@
 <script setup>
+import { ref,nextTick } from "vue";
+import {ElMessage,ElMessageBox} from "element-plus"
+import { useRouter,useRoute} from 'vue-router';
+import _ from 'lodash'
+import { InfoFilled } from '@element-plus/icons-vue'
+
+const $route = useRoute()
+const $router = useRouter()
+
+import { contractInterface } from "@/api/api.js";
+import QyServiceTable from "./components/QyServiceTable.vue"; //权益服务内容表格组件
+import FiccServiceTable from "./components/FiccServiceTable.vue"; //ficc服务内容表格组件
+import { CalculationDate } from "@/utils/CalculationDate";
+
+
+const RoleType=ref(localStorage.getItem("Role") || "")
+const formData=ref({})
+const formRule={
+CompanyName: [{ required: true, message: "请填写名称", trigger: "blur" }],
+CreditCode: [{ required: true, message: "请填写信用码", trigger: "blur" }],
+Province: [{ required: true, message: "请选择地址", trigger: "change" }],
+OriginalPrice: [
+    { required: true, message: "请填写代付金额", trigger: "blur" },
+    { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: "请输入正确的格式,可保留两位小数" },
+],
+trueUseName: [{ required: true, message: "请输入关键字", trigger: "change" }],
+PayRemark: [{ required: true, message: "请填写付款方式说明", trigger: "blur" }],
+}
+
+const relationContractData=ref(null) //选择的关联合同数据
+const ficcServiceData=ref(null) //ficc 底部表格数据
+const qyServiceData=ref(null) //权益底部表格数据
+const serviceShow=ref(false) //是否显示查看报价单
+const serviceCon=ref({}) //选择的服务项 查看报价单/选择品种
+const operationList=ref([])
+ 
+const showEdit=ref(false)//是否显示编辑按钮
+
+// filters
+const formatPrice=(str)=>{
+    if(!str) return ''
+    str=str.toString()
+    let num1='',num2=''
+    if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+        num2=''
+    }
+    }else{
+        num1=str
+    }
+    return num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+
+// 金额转中文大写
+const digitUppercase=(n)=>{
+    if(!n) return ''
+    let fraction = ["角", "分"];
+    let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+    let unit = [
+        ["元", "万", "亿"],
+        ["", "拾", "佰", "仟"],
+    ];
+    let head = n < 0 ? "欠" : "";
+    n = Math.abs(n);
+    let s = "";
+    for (let i = 0; i < fraction.length; i++) {
+        s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, "");
+    }
+    // s = s || "整";
+
+    n = Math.floor(n);
+    for (let i = 0; i < unit[0].length && n > 0; i++) {
+        let p = "";
+        for (let j = 0; j < unit[1].length && n > 0; j++) {
+            p = digit[n % 10] + unit[1][j] + p;
+            n = Math.floor(n / 10);
+        }
+        s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s;
+    }
+    return (
+    "大写:" + (head + s.replace(/(零.)*零元/, "元").replace(/(零.)+/g, "零"))
+    // .replace(/^整$/, "零元整")
+    );
+}
+//计算多少年
+const formateYear=(e)=>{
+    if (e[0]) {
+        return `有效期为${CalculationDate(e[0], e[1])}`;
+    } else {
+        return "";
+    }
+}
+
+// 获取合同详情
+const getDetail=async()=>{
+    const res=await contractInterface.getContractDetail({
+        ContractId:$route.query.contractId
+    })
+    if(res.Ret===200){
+    formData.value=res.Data
+    relationContractData.value=res.Data.RelationContractDetailList[0]
+    getServiceList()
+    // 本人的合同并且合同状态不为 已审批、待审批、已作废、已签回、已解约 则显示编辑
+        let userid=localStorage.getItem('AdminId')
+        if(userid==res.Data.SellerId
+        &&res.Data.Status!=='待审批'
+        &&res.Data.Status!=='已审批'
+        &&res.Data.Status!=='已作废'
+        &&res.Data.Status!=='已签回'
+        &&res.Data.Status!=='已解约'){
+            showEdit.value=true
+        }else{
+            showEdit.value=false
+        }
+    }
+}
+
+//获取合同操作记录
+const getContractOperationList=()=>{
+    contractInterface.getContractOperationList({ContractId:$route.query.contractId}).then(res=>{
+    if(res.Ret===200){
+        operationList.value=res.Data.List&&res.Data.List.map(item=>{
+        return {...item,CreateTimeStr:item.CreateTimeStr.replace(/-/g,'.')}
+        })||[]
+    }
+    })
+}
+
+//获取服务套餐模板数据
+const getServiceList=()=>{
+    contractInterface.getServiceList({ ProductId: relationContractData.value.ProductId }).then((res) => {
+    if (res.Ret === 200) {
+        if (relationContractData.value.ProductId === 1) {
+        ficcServiceData.value = res.Data;
+        } else {
+        qyServiceData.value = res.Data;
+        }
+    }
+    });
+}
+
+//显示查看报价单弹窗
+const handleShowService=(e)=>{
+    // 小套餐情况处理表格数据
+    if (e.Detail) {
+    let temarr = e.Detail.map((rowItem) => {
+        let rowArr = [];
+        for (let key in rowItem) {
+        if (key.substr(0, 3) === "Col" && rowItem[key] !== "") {
+            rowArr.push(JSON.parse(rowItem[key]));
+        }
+        }
+        return rowArr;
+    });
+    serviceCon.value = { ...e, tableHeadData: temarr[0], tableData: temarr.slice(1) };
+    } else {
+    serviceCon.value = e;
+    }
+    serviceShow.value = true;
+}
+
+//前往预览合同
+const handleGoPreview=()=>{
+        let {href} = $router.resolve({
+    path:"/contractdtl",
+    query:{contractid:$route.query.contractId}
+    });
+        window.open(href,'_blank');
+}
+
+//点击编辑 跳转编辑页
+const handleGoEdit=()=>{
+    $router.push({
+    path: "/editcontractdc",
+    query: {
+        contractId: $route.query.contractId,
+        type: "edit",
+    },
+    });
+}
+
+getDetail()
+getContractOperationList()
 
 </script>
 
 <template>
-    <div></div>
-</template>
+    <div class="contractdetail-dc flex">
+      <el-form :model="formData" label-position="left" :rules="formRule" label-width="110px" disabled style="width: 80%"
+      size="large">
+        <section class="section">
+          <h2 class="section-title">客户信息</h2>
+          <div class="section-container">
+            <div class="flex border-top" style="padding-top: 30px">
+              <el-form-item label="代付方" prop="CompanyName" style="width: 50%">
+                <el-input v-model="formData.CompanyName" placeholder="请输入名称" style="width: 350px"></el-input>
+              </el-form-item>
+              <el-form-item label="社会信用码" prop="CreditCode" style="width: 50%">
+                <el-input v-model="formData.CreditCode" placeholder="请输入社会信用码" style="width: 350px"></el-input>
+              </el-form-item>
+            </div>
+            <div class="flex border-top" style="padding-top: 30px">
+              <el-form-item label="公司地址" prop="Province" style="width: 50%">
+                <el-input :value="formData.Province + formData.City" disabled style="width: 350px"></el-input>
+              </el-form-item>
+              <el-form-item label="详细地址" prop="Address" style="width: 50%">
+                <el-input v-model="formData.Address" placeholder="请输入详细地址" style="width: 350px"></el-input>
+              </el-form-item>
+            </div>
+            <div class="flex border-top" style="padding-top: 30px">
+              <el-form-item label="传真" prop="Fax" style="width: 50%">
+                <el-input v-model="formData.Fax" placeholder="请输入传真" style="width: 350px"></el-input>
+              </el-form-item>
+              <el-form-item label="电话" prop="Phone" style="width: 50%">
+                <el-input v-model="formData.Phone" placeholder="请输入电话" style="width: 350px"></el-input>
+              </el-form-item>
+            </div>
+            <div class="flex border-top" style="padding-top: 30px">
+              <el-form-item label="邮编" prop="Postcode" style="width: 50%">
+                <el-input v-model="formData.Postcode" placeholder="请输入邮编" style="width: 350px"></el-input>
+              </el-form-item>
+              <el-form-item label="代付金额" prop="OriginalPrice" style="width: 50%">
+                <el-input :value="formatPrice(formData.OriginalPrice)" placeholder="请输入金额" style="width: 350px"></el-input>
+                <span style="line-height: 40px;margin-left:20px">{{ digitUppercase(formData.OriginalPrice) }}</span>
+              </el-form-item>
+            </div>
+            <div class="border-top">
+              <el-form-item label="付款方式说明" prop="PayRemark">
+                <el-input type="textarea" v-model="formData.PayRemark" placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)" style="width: 80%"></el-input>
+              </el-form-item>
+            </div>
+          </div>
+        </section>
+  
+        <section class="section" v-if="relationContractData">
+          <h2 class="section-title">合同信息</h2>
+          <div class="section-container">
+            <div class="flex border-top" style="padding-top: 30px">
+              <el-form-item label="合同编号" style="width: 50%">
+                <span>{{ relationContractData.ContractCode }}</span>
+              </el-form-item>
+              <el-form-item label="合同归属" style="width: 50%">
+                <span>{{ relationContractData.ProductId === 1 ? "ficc" : "权益" }}</span>
+              </el-form-item>
+            </div>
+            <el-form-item label="合同类型" class="border-top">
+              <el-radio-group v-model="relationContractData.ContractType">
+                <div style="display: flex">
+                  <div style="margin-right: 10px">
+                    <el-radio label="新签合同" disabled>新签合同</el-radio>
+                    <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                        <template #content>没有正式转试用记录的客户,在申请转正时提交的合同</template>
+                        <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </div>
+                  <div style="margin-right: 10px">
+                    <el-radio label="续约合同" disabled>续约合同</el-radio>
+                    <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                        <template #content>
+                        1、有正式转试用记录的客户,在申请转正时提交的合同<br>
+                        2、所有客户在续约申请时提交的合同
+                        </template>
+                        <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </div>
+                  <div style="margin-right: 10px" v-if="RoleType !== 'rai_seller'">
+                    <el-radio label="补充协议" disabled>补充协议</el-radio>
+                  </div>
+                </div>
+              </el-radio-group>
+            </el-form-item>
+            <div class="flex border-top" v-if="relationContractData.timeRange">
+              <el-form-item label="合同期限" style="width: 50%">
+                <el-date-picker disabled v-model="relationContractData.timeRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
+              </el-form-item>
+              <span style="line-height: 40px">{{ formateYear(relationContractData.timeRange)  }}</span>
+            </div>
+  
+            <div class="flex border-top">
+              <el-form-item label="合同金额" style="width: 50%">
+                <el-input disabled :value="formatPrice(relationContractData.OriginalPrice)" placeholder="请输入合同金额" style="width: 220px"></el-input>
+              </el-form-item>
+              <span style="line-height: 40px">{{ digitUppercase(relationContractData.OriginalPrice) }}</span>
+            </div>
+  
+            <div class="flex border-top">
+              <el-form-item label="优惠后金额" style="width: 50%">
+                <el-input disabled :value="formatPrice(relationContractData.Price)" placeholder="请输入优惠后金额" style="width: 220px"></el-input>
+              </el-form-item>
+              <span style="line-height: 40px">{{ digitUppercase(relationContractData.Price)  }}</span>
+            </div>
+  
+            <el-form-item label="付款方式说明" class="border-top">
+              <el-input
+                type="textarea"
+                disabled
+                v-model="relationContractData.PayRemark"
+                placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)"
+                style="width: 80%"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="付款方" class="border-top">
+              <el-input
+                type="textarea"
+                disabled
+                v-model="relationContractData.PayChannel"
+                placeholder="代付,请填写代付的券商名称或期货公司名称;非代付,请填写无。(请勿填写现金/转账等支付形式)"
+                style="width: 80%"
+              ></el-input>
+            </el-form-item>
+          </div>
+        </section>
+  
+        <section class="section" v-if="relationContractData">
+          <h2 class="section-title">服务内容</h2>
+            <div class="section-container">
+              <!-- ficc 服务内容表格 -->
+              <FiccServiceTable
+                :canEdit="false"
+                :serviceData="ficcServiceData"
+                :hasSercive="relationContractData.Service"
+                @handleShowService="handleShowService"
+                v-if="relationContractData.ProductId === 1 && ficcServiceData"
+              ></FiccServiceTable>
+  
+              <!-- 权益 服务内容表格 -->
+              <QyServiceTable
+                :canEdit="false"
+                :serviceData="qyServiceData"
+                :hasSercive="relationContractData.Service"
+                @handleShowService="handleShowService"
+                v-if="relationContractData.ProductId === 2 && qyServiceData"
+              ></QyServiceTable>
+            </div>
+            <p style="margin-top: 30px; margin-bottom: 20px">补充内容(eg额外赠送、路演次数规定)</p>
+            <el-radio :model-value="relationContractData.Remark?'1':'2'" label="2" disabled>无</el-radio>
+            <el-radio :model-value="relationContractData.Remark?'1':'2'" label="1" disabled>有</el-radio>
+            <el-input v-if="relationContractData.Remark" disabled type="textarea" v-model="relationContractData.Remark" rows="5" placeholder="请输入内容" style="margin: 20px 0; display: block; box-sizing: border-box"></el-input>
+        </section>
+  
+        <section class="section">
+          <h2 class="section-title">审批备注</h2>
+          <div class="section-container">
+            <el-form-item label="备注" prop="sellerRemark" class="border-top">
+              <el-input type="textarea" v-model="formData.sellerRemark" placeholder="请输入备注(仅供审批人查看,不在生成合同中展示)" style="width: 80%"></el-input>
+            </el-form-item>
+          </div>
+        </section>
+      </el-form>
+      <div class="right-wrap">
+        <div style="display: flex; justify-content: space-between">
+          <el-button type="primary" style="width: 45%" @click="handleGoEdit" v-if="showEdit" size="large">编辑</el-button>
+          <el-button type="primary" plain :style="{width: showEdit?'45%':'100%'}" @click="handleGoPreview" size="large">预览</el-button>
+        </div>
+        <div class="timeline-wrap">
+          <el-timeline>
+            <el-timeline-item color="#409EFF" v-for="item in operationList" :key="item.Id" placement="top" :timestamp="item.CreateTimeStr">
+              {{item.OpUserName}}{{ item.Remark }}
+            </el-timeline-item>
+          </el-timeline>
+        </div>
+      </div>
+      <!-- 查看报价单弹窗 -->
+      <el-dialog v-dialogDrag v-model="serviceShow" width="60%" class="self-dialog-c" :modal-append-to-body="false" @close="serviceShow=false" :show-close="false">
+        <h2 class="title" style="text-align: center; color: #000">{{ RoleType == 'ficc_seller'? serviceCon.Title : serviceCon.showTitle }}</h2>
+        <img class="img" style="width: 100%; display: block; margin: 20px auto" 
+        :src="RoleType == 'ficc_seller'? serviceCon.Value : serviceCon.showValue"/>
+        <div style="text-align: center; margin-bottom: 30px">
+          <el-button type="primary" @click="serviceShow=false" size="large">知道了</el-button>
+        </div>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <style>
+  .contractdetail-dc .self-dialog-c .el-dialog__header {
+    background-color: #fff;
+    padding: 0;
+  }
+  .contractdetail-dc .self-dialog-c {
+    width: auto;
+    max-width: 60%;
+  }
+  .contractdetail-dc .el-timeline-item__tail {
+    border-left: 2px solid #409eff;
+  }
+  .el-radio__input.is-checked .el-radio__inner {
+    background-color: transparent;
+  }
+  .el-radio__inner::after {
+    width: 6px;
+    height: 6px;
+    background-color: #409eff;
+  }
+  .el-checkbox__label {
+    font-size: 16px !important;
+  }
+  .el-form-item {
+    margin-bottom: 30px;
+  }
+  .el-input.is-disabled .el-input__inner {
+    color: #606266;
+  }
+   .el-radio__input.is-disabled + span.el-radio__label {
+     color: #606266;
+   }
+   .el-range-editor.is-disabled input {
+     color: #606266;
+   }
+   .el-textarea.is-disabled .el-textarea__inner {
+     color: #606266;
+   }
+   .el-timeline-item__tail {
+     border-left: 2px solid #409eff;
+   }
+  </style>
+  <style lang="scss" scoped>
+  .contractdetail-dc{
+      min-height: calc(100vh - 250px);
+      position: relative;
+      font-size: 16px;
+      color: #000;
+  }
+  .flex {
+    display: flex;
+  }
+  .right-wrap {
+    margin-left: 20px;
+    flex: 1;
+    .timeline-wrap {
+      margin-top: 20px;
+      background-color: #fff;
+      border: 1px solid #aab4cc;
+      padding: 20px;
+      border-radius: 4px;
+      text-align: left;
+      height: calc(100% - 120px);
+      max-height: 1130px;
+      overflow-y: auto;
+    }
+  }
+  .section {
+    background-color: #fff;
+    border: 1px solid #aab4cc;
+    border-radius: 4px;
+    padding: 20px 30px;
+    margin-bottom: 20px;
+    .section-title {
+      margin-bottom: 30px;
+    }
+    .border-top {
+      padding-top: 30px;
+      border-top: 1px solid #dcdfe6;
+    }
+  }
+  </style>

+ 1094 - 0
src/views/contract_manage/contractList.vue

@@ -0,0 +1,1094 @@
+
+<script>
+import { defineComponent } from 'vue'
+export default defineComponent({
+  // 进入前是否清除参数
+  beforeRouteEnter(to, from, next) {
+    if(from.path!='/contractdetail'&&from.path!='/contractdetaildc'&&from.path!='/addcontractdc'){
+      sessionStorage.removeItem('contractListBack')
+      sessionStorage.removeItem('contractListTabs')
+    }
+    next()
+  }
+})
+
+</script>
+
+<script setup>
+import { ref,reactive,computed } from "vue";
+import { onBeforeRouteLeave ,useRouter} from 'vue-router';
+import {ElMessage,ElMessageBox} from "element-plus"
+import _ from 'lodash'
+import PreviewService from "./components/PreviewService.vue";
+import { contractInterface,customInterence } from "@/api/api.js";
+import ExplainDlg from './components/ExplainDlg.vue';
+import {formatter,formatPriceHasPoint} from "@/hooks/mixins/index"
+
+
+const $router = useRouter()
+
+// 离开前缓存页面状态
+onBeforeRouteLeave((to, from, next)=>{
+  let obj={
+    page:page.value,
+    searchVal:searchVal.value,
+    searchType:searchType.value,
+    timeRange:timeRange.value,
+    constractTypeVal:constractTypeVal.value,
+    constractStatusVal:constractStatusVal.value,
+    constractBelongVal:constractBelongVal.value,
+    constractSellerVal:constractSellerVal.value,
+  }
+  sessionStorage.setItem('contractListBack',JSON.stringify(obj))
+  sessionStorage.setItem('contractListTabs',tabsActive.value)
+  next()
+})
+
+const tabs=[{name:'业务合同'},{name:"代付合同"}]
+//合同类型选项
+const constractTypeOptions=[
+        {value: "新签合同",label: "新签合同"},
+        {value: "续约合同",label: "续约合同"},
+        {value: "补充协议",label: "补充协议"}] 
+//合同状态选项
+const constractStatusOptions=ref([
+        {value: "待提交",lable: "待提交"},
+        {value: "待审批",lable: "待审批"},
+        {value: "已撤回",lable: "已撤回"},
+        {value: "已审批",lable: "已审批"},
+        {value: "已驳回",lable: "已驳回"},
+        {value: "已作废",lable: "已作废"},
+        {value: "已签回",lable: "已签回"},
+        {value: "已解约",lable: "已解约"}
+      ])
+//合同归属选项
+const constractBelongOptions=[
+        {value: "1",label: "FICC"},
+        {value: "2",label: "权益"}] 
+//销售级联配置
+const defaultSalesProps={
+  multiple: true,
+  label:'RealName',
+  children:'ChildrenList',
+  value:'AdminId'
+}
+const tabsActive=ref(sessionStorage.getItem('contractListTabs')||'业务合同')
+const searchType=ref('使用方')
+const showPreContractList=ref(false)
+const preContractList=ref([])
+const showAddTypeDia=ref(false)//新增合同类型弹窗
+const RoleType=ref(localStorage.getItem("Role") || "")
+const contractTemList=ref([])//合同模板列表
+const serviceCon=ref([])//套餐数据
+const showPreview=ref(false)//查看套餐弹窗
+const showDownload=ref(false)//下载合同模板弹窗
+const page=ref(1)
+const pageSize=ref(10)
+const total=ref(0)
+const searchVal=ref("")//搜索值
+const timeRange=ref(["", ""])//选择时间段
+const constractTypeVal=ref("")//选择的合同类型值
+const constractStatusVal=ref("")//选择的合同状态值
+const constractBelongVal=ref("")//合同归属值
+const constractSellerOptions=ref([])//申请销售列表
+const constractSellerVal=ref("")//申请销售值
+const tableList=ref([])//合同列表数据(表格)
+const uploadFileData=reactive({
+  name:"",//文件名
+  CompanyName:"",//客户名
+  url:'',
+  contractId:0,
+  file:null,
+})//销售更新合同文件数据
+const showUploadAttachment=ref(false)//销售更新合同文件弹窗
+const explainShowDownload=ref(false)//操作详情
+const showlc=ref(false)
+
+
+const exportExcel=computed(()=>{
+  let baseUrl = import.meta.env.VITE_APP_API_ROOT + "/contract/list";
+  let token = localStorage.getItem("auth") || "";
+  let paramStr = "";
+  let obj = {
+    ContractType: constractTypeVal.value,
+    ContractStatus: constractStatusVal.value,
+    ProductId: constractBelongVal.value || 0,
+    ModifyStartTime: !timeRange.value?'':timeRange.value[0] ? `${timeRange.value[0]} 00:00:00` : "",
+    ModifyEndTime: !timeRange.value?'':timeRange.value[1] ? `${timeRange.value[1]} 23:59:59` : "",
+    SellerId: '',
+    Keyword: searchVal.value,
+    KeywordType:searchType.value,
+    IsExport:true,
+    ContractBusinessType:tabsActive.value,
+  };
+  if(constractSellerVal.value.length){
+    obj.SellerId=constractSellerVal.value.map(item=>{
+      return item[item.length-1]
+    }).join(',')
+  }
+  for (let key in obj) {
+    paramStr = `${paramStr}&${key}=${obj[key]}`;
+  }
+  return `${baseUrl}?${token}${paramStr}`;
+})
+
+// 业务合同、代付合同切换
+const handleChangeTabs=(e)=>{
+  tabsActive.value=e
+  handleRefreshPage()
+}
+
+// 业务合同查看代付合同、代付合同查看
+const handlePreviewContract=(e)=>{
+  console.log(preContractList.value,'preContractList.value');
+  // 只有一个直接跳转
+  if(e.length===1){
+    let contractId=0
+    if(tabsActive.value==='业务合同'){
+      contractId=e[0].PaymentOnBehalfContractId
+    }else if(tabsActive.value==='代付合同'){
+      contractId=e[0].ContractId
+    }
+    handleGoContractdtl(contractId)
+  }else if(e.length>1){
+    preContractList.value=e
+    showPreContractList.value=true
+  }
+}
+
+// 跳转合同预览
+const handleGoContractdtl=(id)=>{
+  let {href} = $router.resolve({path:"/contractdtl",query:{contractid:id}});
+  window.open(href,'_blank');
+}
+
+const checkFileBeforeUpload=(file)=>{
+  let hostfile = file;
+  let size = Math.floor(hostfile.size / 1024 / 1024);
+  if (size > 200) {
+    ElMessage.error("上传文件大小不能大于200M!");
+    hostfile = {};
+    return false;
+  }
+  if (hostfile.name.toLowerCase().includes(".pdf")||hostfile.name.toLowerCase().includes(".doc")||hostfile.name.toLowerCase().includes(".docx")) {
+      uploadFileData.name=hostfile.name.toLowerCase()
+      uploadFileData.file=hostfile
+    } else {
+      ElMessage.error("请上传PDF/word文件!");
+    }
+  return false
+}
+
+// 销售更新合同附件
+const handleUploadAttachment=()=>{
+  $("#fileCard").click();
+}
+
+// 获取列表数据
+const getContractList=()=>{
+  // 处理销售筛选
+  let salesArr=[]
+  if(constractSellerVal.value.length){
+    salesArr=constractSellerVal.value.map(item=>{
+      return item[item.length-1]
+    })
+  }
+  let params = {
+    ContractType: constractTypeVal.value,
+    ContractStatus: constractStatusVal.value,
+    ProductId: Number(constractBelongVal.value),
+    ModifyStartTime: !timeRange.value?'':timeRange.value[0] ? `${timeRange.value[0]} 00:00:00` : "",
+    ModifyEndTime: !timeRange.value?'':timeRange.value[1] ? `${timeRange.value[1]} 23:59:59` : "",
+    SellerId: salesArr.join(','),
+    Keyword: searchVal.value,
+    KeywordType:searchType.value,
+    CurrentIndex: page.value,
+    PageSize: pageSize.value,
+    ContractBusinessType:tabsActive.value,
+  };
+  contractInterface.getContractList(params).then((res) => {
+    if (res.Ret === 200) {
+      tableList.value = res.Data.List;
+      total.value = res.Data.Paging.Totals;
+    }
+  });
+}
+
+//获取所属销售列表
+const getSellerList=()=>{
+  contractInterface.getSellerList().then((res) => {
+    if (res.Ret === 200) {
+      constractSellerOptions.value = res.Data.List;
+    }
+  });
+}
+
+// 选择文件上传
+const fileSelected=()=>{
+  //选择文件上传
+  if (document.getElementById("fileCard").files[0]) {
+    let hostfile = document.getElementById("fileCard").files[0];
+    let size = Math.floor(hostfile.size / 1024 / 1024);
+    if (size > 200) {
+      ElMessage.error("上传文件大小不能大于200M!");
+      hostfile = {};
+      return false;
+    }
+    if (hostfile.name.toLowerCase().includes(".pdf")||hostfile.name.toLowerCase().includes(".doc")||hostfile.name.toLowerCase().includes(".docx")) {
+      // let form = new FormData();
+      // form.append("file", hostfile); //hostfile.name
+      // customInterence.upload(form).then((res) => {
+      //   if (res.Ret === 200) {
+      //     // that.$message.success( '上传成功' );
+      //     this.uploadFileData.url = res.Data.ResourceUrl;
+      //     this.uploadFileData.name=hostfile.name.toLowerCase()
+      //   }
+      //   $("#fileCard").val("");
+      //   hostfile = {};
+      // });
+      uploadFileData.name=hostfile.name.toLowerCase()
+      uploadFileData.file=hostfile
+    } else {
+      ElMessage.error("请上传PDF/word文件!");
+    }
+  }
+}
+
+// 确定更新合同附件
+const handleConfirmUpdateContractFile = async ()=>{
+  if(!uploadFileData.file){
+    ElMessage.warning('请上传文件');
+    return
+  }
+  let form = new FormData();
+  form.append("file", uploadFileData.file)
+  form.append('ContractId',uploadFileData.contractId)
+  // const res=await contractInterface.updateContractFile({
+  //   ContractId:this.uploadFileData.contractId,
+  //   FileUrl:this.uploadFileData.url
+  // })
+  const res=await contractInterface.updateContractFile(form)
+  if(res.Ret===200){
+    ElMessage.success('更新成功')
+    getContractList()
+    showUploadAttachment.value=false
+  }
+}
+
+//下载合同模板
+const handleDownloadContractTemplate=()=>{
+  contractInterface.getContractTemplate().then((res) => {
+    if (res.Ret === 200) {
+      contractTemList.value = res.Data;
+      showDownload.value = true;
+    }
+  });
+}
+
+//刷新页面
+const handleRefreshPage=()=>{
+  page.value = 1;
+  searchVal.value = "";
+  timeRange.value = ["", ""];
+  constractTypeVal.value = "";
+  constractStatusVal.value = "";
+  constractBelongVal.value=''
+  constractSellerVal.value=''
+  getContractList();
+}
+
+//提交申请
+const handleSubmitApproval=(id)=>{
+  contractInterface.applyContract({ ContractId: Number(id) }).then((res) => {
+    if (res.Ret === 200) {
+      ElMessage.success("提交成功");
+      handleRefreshPage();
+    }
+  });
+}
+
+//撤回申请
+const handleCancelApplyContract=(ContractApprovalRecordId, ContractId)=>{
+  contractInterface.cancelApplyContract({ ContractApprovalRecordId, ContractId }).then((res) => {
+    if (res.Ret === 200) {
+      ElMessage.success("撤回成功");
+      handleRefreshPage();
+    }
+  });
+}
+
+/**
+  * 操作
+  * type 操作类型
+  * e    数据
+  * 查看套餐(viewPackage)、驳回理由(rejectReason)、申请重审(applyRetrial)
+  * 删除(delete)、下载(download)、作废合同(cancelConstract)、撤回申请(backApply)
+  * 修改合同(modifyConstract)、复制模板(copy)、编辑(edit)、提交审批(submitApproval)
+  * 未提交审核的下载(downloadTem) 查看附件(已签回 checkBack  已解约rescind)  销售更新合同附件(updatefConstractFile)
+  * 修改重审(modifyAndApply)
+*/
+const handleOperation=_.debounce(function(type, e) {
+  if(type==='checkBack'){
+    const url=e.CheckBackFileUrl
+    if(!url){
+      ElMessage.warning('文件错误')
+      return
+    }
+    const reg = /\.(pdf)$/;
+    // pdf
+    if(reg.test(url)){
+      window.open(url,'_blank');
+    }else{
+      window.open('https://view.officeapps.live.com/op/view.aspx?src='+url,'_blank');
+    }
+    // window.open(e.CheckBackFileUrl,'_blank');
+  }
+
+  if(type==='rescind'){
+    const url=e.RescindFileUrl
+    if(!url){
+      ElMessage.warning('文件错误')
+      return
+    }
+    const reg = /\.(pdf)$/;
+    // pdf
+    if(reg.test(url)){
+      window.open(url,'_blank');
+    }else{
+      window.open('https://view.officeapps.live.com/op/view.aspx?src='+url,'_blank');
+    }
+    // window.open(e.RescindFileUrl,'_blank');
+  }
+
+  if (type === "submitApproval") {
+    handleSubmitApproval(e.ContractId);
+    return;
+  }
+
+  if (type === "delete") {
+    ElMessageBox.confirm("是否确认删除合同?", "提示", {
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
+      type: "warning",
+    }).then(() => {
+      contractInterface.contractDelete({ ContractId: e.ContractId }).then((res) => {
+        if (res.Ret === 200) {
+          ElMessage.success("删除成功");
+          handleRefreshPage();
+        }
+      });
+    }).catch(()=>{})
+    return;
+  }
+
+  if (type === "edit") {
+    if(e.ContractBusinessType==='业务合同'){
+      $router.push({
+        path: "/editcontract",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }else{
+      $router.push({
+        path: "/editcontractdc",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }
+    
+    return;
+  }
+
+  if (type === "viewPackage") {
+    if(e.ContractBusinessType==='业务合同'){
+      serviceCon.value = e.Service;
+    }else{
+      let arr=[]
+      e.RelationContractList.forEach(item=>{
+        item.Service.forEach(item2=>{
+          arr.push(item2)
+        })
+      })
+      serviceCon.value=arr
+    }
+    
+    showPreview.value = true;
+    return;
+  }
+
+  if (type === "rejectReason") {
+    ElMessageBox.alert(e.ApprovalRemark, "驳回理由", {
+      confirmButtonText: "知道了",
+      showCancelButton: false,
+    }).then(() => {});
+    return;
+  }
+
+  if (type === "cancelConstract") {
+    ElMessageBox.confirm("作废后合同将不能再使用,是否确认作废合同?", "提示", {
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
+      type: "warning",
+    }).then(() => {
+      contractInterface.contractInvalid({ ContractId: e.ContractId }).then((res) => {
+        if (res.Ret === 200) {
+          ElMessage.success("作废成功");
+          handleRefreshPage();
+        }
+      });
+    }).catch(()=>{})
+    return;
+  }
+
+  if (type === "backApply") {
+    ElMessageBox.confirm("确认撤回该合同吗?", "提示", {
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
+      type: "warning",
+    }).then(() => {
+      handleCancelApplyContract(e.ContractApprovalRecordId, e.ContractId);
+    }).catch(()=>{})
+    return;
+  }
+
+  if (type === "download") {
+    let link = document.createElement("a");
+    link.href = e.FileUrl + "?response-content-type=application/octet-stream";
+    link.setAttribute("download", e.ContractCode);
+    link.style.display = "none"; //a标签隐藏
+    document.body.appendChild(link);
+    link.click();
+    return;
+  }
+
+  if(type==='downloadTem'){
+    let baseUrl = import.meta.env.VITE_APP_API_ROOT + "/contract/downLoad/tmpContract";
+    let token = localStorage.getItem("auth") || "";
+    let path=`${baseUrl}?${token}&ContractId=${e.ContractId}`
+    let link = document.createElement("a");
+    link.href = path;
+    link.setAttribute("download", e.ContractCode);
+    link.style.display = "none"; //a标签隐藏
+    document.body.appendChild(link);
+    link.click();
+    return
+  }
+
+  if (type === "modifyConstract") {
+    if(e.ContractBusinessType==='业务合同'){
+      $router.push({
+        path: "/editcontract",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }else{
+      $router.push({
+        path: "/editcontractdc",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }
+    
+    return;
+  }
+
+  if (type === "applyRetrial") {
+    if(e.ContractBusinessType==='业务合同'){
+      $router.push({
+        path: "/retrialcontract",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }else{
+      $router.push({
+        path: "/retrialcontractdc",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }
+    
+    return;
+  }
+
+  if (type === "copy") {
+    if(e.ContractBusinessType==='业务合同'){
+      $router.push({
+        path: "/copycontract",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }else{
+      $router.push({
+        path: "/copycontract",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+      $router.push({
+        path: "/copycontractdc",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }
+    
+    return;
+  } 
+
+  // 销售更新合同附件
+  if(type==='updatefConstractFile'){
+    let fileName=e.FileUrl.substring(e.FileUrl.lastIndexOf('/') + 1)
+    uploadFileData.name=fileName
+    uploadFileData.CompanyName=e.CompanyName
+    uploadFileData.contractId=e.ContractId
+    uploadFileData.url=e.FileUrl
+    showUploadAttachment.value=true
+  }
+
+  // 修改重审
+  if(type==='modifyAndApply'){
+    if(e.ContractBusinessType==='业务合同'){
+      $router.push({
+        path: "/modifyapply",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }else{
+      $router.push({
+        path: "/modifyapplydc",
+        query: {
+          contractId: e.ContractId,
+          type: type,
+        },
+      });
+    }
+
+    return
+  }
+},200)
+
+
+//关闭查看套餐弹窗
+const handleClosePreviewService=()=>{
+  showPreview.value = false;
+}
+
+//类型或者状态变更
+const handleSelectChange=()=>{
+  searchVal.value = "";
+  page.value = 1;
+  getContractList();
+}
+
+
+//页码改变
+const handlePageChange=(e)=>{
+  page.value = e;
+  getContractList();
+}
+
+//跳转合同详情
+const handleGoDetail=(type,id)=>{
+  if(type==='业务合同'){
+    $router.push({ path: "/contractdetail", query: { contractId: id } });
+  }else{
+    $router.push({ path: "/contractdetaildc", query: { contractId: id } });
+  }
+}
+
+//搜索
+const handleSearch=()=>{
+  timeRange.value = ["", ""];
+  constractTypeVal.value = "";
+  constractStatusVal.value = "";
+  constractSellerVal.value=''
+  constractBelongVal.value=''
+  page.value = 1;
+  getContractList();
+}
+//查看详细操作说明
+const explainDialog=()=>{
+  explainShowDownload.value=true;
+}
+
+// created
+if(sessionStorage.getItem('contractListBack')){
+  let cache=JSON.parse(sessionStorage.getItem('contractListBack'))
+  page.value=cache.page
+  searchVal.value=cache.searchVal
+  timeRange.value=cache.timeRange
+  constractBelongVal.value=cache.constractBelongVal
+  constractTypeVal.value=cache.constractTypeVal
+  constractStatusVal.value=cache.constractStatusVal
+  constractSellerVal.value=cache.constractSellerVal
+}
+if(RoleType.value === 'admin'){
+  constractStatusOptions.value= [
+    {
+      value: "待审批",
+      lable: "待审批",
+    },
+    {
+      value: "已审批",
+      lable: "已审批",
+    },
+    {
+      value: "已驳回",
+      lable: "已驳回",
+    },
+    {
+      value: "已作废",
+      lable: "已作废",
+    },
+    {
+      value: "已签回",
+      lable: "已签回",
+    },
+    {
+      value: "已解约",
+      lable: "已解约",
+    },
+  ] //合同状态选项
+}
+getContractList();
+getSellerList();
+</script>
+
+<template>
+  <div class="contractlist-container">
+    <div class="top-wrap">
+      <template v-if="RoleType === 'ficc_seller' || RoleType === 'rai_seller'"   style="margin-right:10px;">
+        <el-button type="primary" @click="showAddTypeDia=true" size="large">添加合同</el-button>
+        <el-button type="primary" plain @click="handleDownloadContractTemplate" size="large">合同操作指南</el-button>
+      </template>
+      <template v-if="!(RoleType === 'ficc_seller' || RoleType === 'rai_seller')" >
+        <a :href="exportExcel" download>
+          <el-button type="primary" size="large">下载EXCEL</el-button>
+        </a>
+      </template>
+
+      <el-input placeholder="合同编号/客户名称/社会信用码" v-model="searchVal" size="large"
+      style="max-width: 400px; float: right" @input="handleSearch" clearable>
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-input>
+      <el-select v-model="searchType" placeholder="请选择" style="width:120px;float: right;margin-right:10px" size="large">
+        <el-option label="客户名称" value="使用方"></el-option>
+        <el-option label="代付方" value="代付方"></el-option>
+      </el-select>
+
+    </div>
+    <div class="list-wrap">
+      <div style="margin-top: 10px; margin-bottom: 10px">
+        <el-date-picker style="margin-bottom: 20px;margin-right:20px" v-model="timeRange" type="daterange" size="large"
+        @change="handleSelectChange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
+        </el-date-picker>
+        <el-select v-if="tabsActive==='业务合同'" clearable v-model="constractTypeVal" @change="handleSelectChange" size="large"
+        placeholder="合同类型" style="margin-bottom: 20px;margin-right:20px">
+          <el-option v-for="item in constractTypeOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
+        </el-select>
+        <el-select clearable v-model="constractStatusVal" @change="handleSelectChange" placeholder="合同状态" size="large"
+        style="margin-bottom: 20px;margin-right:20px">
+          <el-option v-for="item in constractStatusOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
+        </el-select>
+        <template v-if="RoleType === 'admin'||RoleType==='compliance'||RoleType==='finance'">
+          <el-select clearable v-model="constractBelongVal" @change="handleSelectChange" placeholder="合同归属" 
+          style="margin-bottom: 20px;margin-right:20px" size="large">
+            <el-option v-for="item in constractBelongOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
+          </el-select>
+          <!-- <el-select clearable v-model="constractSellerVal" @change="handleSelectChange" placeholder="申请销售" style="margin-bottom: 20px;margin-right:20px">
+            <el-option v-for="item in constractSellerOptions" :key="item.AdminId" :label="item.RealName" :value="item.AdminId"> </el-option>
+          </el-select> -->
+          <el-cascader
+            v-model="constractSellerVal"
+            placeholder="申请销售"
+            style="min-width:225px;margin-bottom: 20px;margin-right:20px"
+            :options="constractSellerOptions"
+            :props="defaultSalesProps"
+            :show-all-levels="false"
+            collapse-tags
+            clearable
+            filterable
+            size="large"
+            @change="handleSelectChange">
+          </el-cascader>
+        </template>
+      </div>
+      <ul class="tabs-wrap">
+        <li 
+          v-for="item in tabs" 
+          :class="['tab',{'act':tabsActive === item.name}]"
+          @click="handleChangeTabs(item.name)"
+        >{{item.name}}</li>
+      </ul>
+      <el-table :data="tableList" border ref="table">
+        <el-table-column key="合同编号" align="center" prop="ContractCode" label="合同编号" width="160">
+          <template #default="scope">
+            <span class="constract-sn" @click="handleGoDetail(scope.row.ContractBusinessType,scope.row.ContractId)">{{ scope.row.ContractCode }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column key="客户名称" align="center" prop="CompanyName" :label="tabsActive==='业务合同'?'客户名称':'代付方'"></el-table-column>
+        <el-table-column key="社会信用码" align="center" prop="CreditCode" label="社会信用码" width="180"></el-table-column>
+        <el-table-column key="代付方" align="center" prop="RelationContractList" :label="tabsActive==='业务合同'?'付款方':'客户名称'">
+          <template #default="scope">
+            <div v-if="!scope.row.RelationContractList">{{scope.row.PayChannel=='无'?scope.row.CompanyName:scope.row.PayChannel}}</div>
+            <div v-else style="color:#409eff;cursor: pointer" @click="handlePreviewContract(scope.row.RelationContractList)">
+              <span v-if="scope.row.RelationContractList.length===1">{{scope.row.RelationContractList[0].CompanyName}}</span>
+              <span v-else>查看</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column key="销售" align="center" prop="SellerName" label="销售" width="80"></el-table-column>
+        <el-table-column key="合同类型" align="center" prop="ContractType" label="合同类型" width="80"></el-table-column>
+        <el-table-column key="合同有效期" align="center" label="合同有效期" width="180">
+          <template #default="scope">{{ scope.row.StartDateStr }}~{{ scope.row.EndDateStr }}</template>
+        </el-table-column>
+        <el-table-column key="合同金额" align="center" prop="Price" :label="tabsActive==='业务合同'?'合同金额':'代付金额'" width="100">
+          <template #default="scope">{{ formatPriceHasPoint(scope.row.Price) }}</template>
+        </el-table-column>
+        <el-table-column key="合同状态" align="center" prop="Status" label="合同状态" width="80">
+          <template #default="scope">
+            <span :style="{ color: scope.row.Status === '已驳回'||scope.row.Status === '已解约' ? '#FF0000' : null }">{{ scope.row.Status }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column key="更新时间" align="center" prop="ModifyTimeStr" label="更新时间" width="160" :formatter="formatter"></el-table-column>
+        <el-table-column key="seller操作" align="center" label="操作" width="200" v-if="RoleType === 'ficc_seller' || RoleType === 'rai_seller'">
+          <template #default="scope">
+            <div v-if="scope.row.Status === '待提交'">
+              <span class="btn" @click="handleOperation('submitApproval', scope.row)">提交审批</span>
+              <span class="btn" @click="handleOperation('edit', scope.row)">编辑</span>
+              <!-- <span class="btn" @click="handleOperation('downloadTem', scope.row)">草稿下载</span> -->
+              <span class="btn" @click="handleOperation('delete', scope.row)" style="color: #ff0000">删除</span>
+            </div>
+            <div v-if="scope.row.Status === '待审批'">
+              <span class="btn" @click="handleOperation('viewPackage', scope.row)">查看套餐</span>
+              <span class="btn" @click="handleOperation('backApply', scope.row)">撤回申请</span>
+            </div>
+            <div v-if="scope.row.Status === '已撤回'">
+              <span class="btn" @click="handleOperation('viewPackage', scope.row)">查看套餐</span>
+              <span class="btn" @click="handleOperation('modifyConstract', scope.row)">修改合同</span>
+              <span class="btn" @click="handleOperation('delete', scope.row)" style="color: #ff0000">删除</span>
+            </div>
+            <div v-if="scope.row.Status === '已审批'">
+              <span class="btn" @click="handleOperation('viewPackage', scope.row)">查看套餐</span>
+              <span class="btn" @click="handleOperation('cancelConstract', scope.row)">作废合同</span>
+              <span class="btn" @click="handleOperation('download', scope.row)">下载</span>
+              <span class="btn" @click="handleOperation('modifyAndApply', scope.row)">修改重审</span>
+              <!-- <span class="btn" @click="handleOperation('updatefConstractFile',scope.row)" v-if="scope.row.OpButton.UpdateFile">更新附件</span> -->
+            </div>
+            <div v-if="scope.row.Status === '已驳回'">
+              <span class="btn" @click="handleOperation('viewPackage', scope.row)">查看套餐</span>
+              <span class="btn" @click="handleOperation('rejectReason', scope.row)">驳回理由</span>
+              <span class="btn" @click="handleOperation('applyRetrial', scope.row)">申请重审</span>
+              <span class="btn" @click="handleOperation('delete', scope.row)" style="color: #ff0000">删除</span>
+            </div>
+            <div v-if="scope.row.Status === '已作废'">
+              <span class="btn" @click="handleOperation('copy', scope.row)">复制模板</span>
+              <span class="btn" @click="handleOperation('delete', scope.row)" style="color: #ff0000">删除</span>
+            </div>
+            <div v-if="scope.row.Status === '已签回'">
+              <span class="btn" @click="handleOperation('checkBack', scope.row)">查看附件</span>
+            </div>
+            <div v-if="scope.row.Status === '已解约'">
+              <span class="btn" @click="handleOperation('rescind', scope.row)">查看附件</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column key="admin操作" align="center" label="操作" width="150" v-if="RoleType === 'admin'">
+          <template #default="scope">
+            <span class="btn" @click="handleOperation('viewPackage', scope.row)">查看套餐</span>
+            <span class="btn" @click="handleOperation('download', scope.row)" v-if="scope.row.Status === '已审批'">下载</span>
+            <span class="btn" @click="handleOperation('rejectReason', scope.row)" v-if="scope.row.Status === '已驳回'">驳回理由</span>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination layout="total,prev,pager,next,jumper" background :current-page="page" size="large"
+      @current-change="handlePageChange" :page-size="pageSize" :total="total" class="pagination-wrap">
+      </el-pagination>
+    </div>
+
+    <!-- 下载提示弹框 -->
+    <el-dialog 
+      v-dialogDrag 
+      :append-to-body="true" 
+      v-model="showDownload" 
+      width="50%" 
+      center
+    >
+    <template #header>
+      <img src="../../assets/img/icons/warn.png" width="16" height="16" style="vertical-align: middle;margin-right: 4px" />
+      <span style="vertical-align: middle">合同操作指南:</span>
+    </template>
+      <div class="download-popup-wrap">
+        <!-- <img class="top-img" src="../../assets/img/constract/liucheng.png" alt="" /> -->
+        <div class="top-img"></div>
+        <!-- <a :href="item.Url+'?response-content-type=application/octet-stream'" :download="item.Title" v-for="item in contractTemList" :key="item.ContractTemplateId">{{ item.Title }}</a> -->
+        <a @click="explainDialog">查看详细操作说明</a>
+        <a @click="showlc=true" style="display:block;margin-top:10px;position:relative">查看详细操作流程图</a>
+      </div>
+    </el-dialog>
+
+    <!-- 查看套餐弹框 -->
+    <PreviewService :showPreview="showPreview" :serviceCon="serviceCon" @closePreviewService="handleClosePreviewService"></PreviewService>
+  
+    <!-- 查看合同列表弹框 -->
+    <el-dialog 
+      v-dialogDrag 
+      :append-to-body="true" 
+      v-model="showPreContractList" 
+      width="40%" 
+      center
+    >
+      <template #header>
+        <div style="font-size:15px">{{tabsActive==='业务合同'?'付款方列表':'代付方列表'}}</div>
+      </template>
+      <ul class="precontract-list">
+        <li 
+          v-for="item in preContractList" 
+          :key="item.ContractId+item.PaymentOnBehalfContractId"
+          @click="handleGoContractdtl(tabsActive==='业务合同'?item.PaymentOnBehalfContractId:item.ContractId)"
+        >{{item.CompanyName}}</li>
+      </ul>
+      <div style="text-align:center;margin:40px 0 30px 0">
+        <el-button type="primary" style="width:200px" @click="showPreContractList=false">关闭</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 选择新增合同类型 -->
+    <el-dialog 
+      v-dialogDrag
+      :append-to-body="true" 
+      v-model="showAddTypeDia" 
+      width="800px" 
+      class="self-dialog"
+      center
+    >
+      <div style="text-align:center;margin:30px 0 100px 0">
+        <img width="191" src="../../assets/img/constract/bzht.png" @click="$router.push('/addcontract')" style="margin-right:80px;cursor: pointer;">
+				<img width="191" src="../../assets/img/constract/dfht.png" @click="$router.push('/addcontractdc')" style="cursor: pointer;">
+        <p style="font-size:15px;color:#333;text-align:left;padding-left:100px;margin-top:30px">
+					注:标准代付指的是无法签署三方协议和代付合同时,可以选择和代付方签署该类型合同
+				</p>
+      </div>
+    </el-dialog>
+
+    <!-- 销售更新合同文件 -->
+    <el-dialog top="30vh" v-dialogDrag width="570px" v-model="showUploadAttachment" :modal-append-to-body="false" @close="showUploadAttachment=false">
+      <div slot="title">
+        <img width='15' src="../../assets/img/icons/edit1.png" alt="">
+        <span style="display:inline-block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:450px">更新合同附件({{uploadFileData.CompanyName}})</span>
+      </div>
+      <div class="upload-attachment-wrap">
+        <div style="display:flex;align-items: center;">
+          <input type="file" name="file" @change="fileSelected" id="fileCard" style="display: none" />
+          <div class="box"><span v-if="!uploadFileData.name" style="color:#999">请选择文件</span>{{uploadFileData.name}}</div>
+          <!-- <el-button type="primary" @click="handleUploadAttachment">选择文件</el-button> -->
+          <el-upload :before-upload="checkFileBeforeUpload">
+            <el-button type="primary">选择文件</el-button>
+          </el-upload>
+        </div>
+        <div style="text-align:center;margin:60px 0 30px 0">
+          <el-button type="primary" @click="handleConfirmUpdateContractFile">确定</el-button>
+          <el-button type="primary" plain @click="showUploadAttachment=false">取消</el-button>
+        </div>
+      </div>
+    </el-dialog>
+    <explain-dlg  :explainShowDownload="explainShowDownload" @close="explainShowDownload=false"/>
+    <el-dialog 
+      v-dialogDrag 
+      :append-to-body="true" 
+      v-model="showlc" 
+      width="90vw" 
+      top="5vh"
+      class="self-dialog"
+      center>
+        <img style="width:100%" src="../../assets/img/constract/bg.png" />
+    </el-dialog>
+  </div>
+</template>
+
+
+<style lang="scss">
+.el-message-box__header .el-message-box__title {
+  color: #333 !important;
+}
+.el-date-table td.start-date div::after {
+  content: "起";
+  display: block;
+  position: absolute;
+  top: 64%;
+  left: 50%;
+  transform: translateX(-50%) scale(0.9);
+  color: #666;
+  z-index: 1000;
+  font-size: 10px;
+}
+.el-date-table td.end-date div::after {
+  content: "终";
+  display: block;
+  position: absolute;
+  top: 64%;
+  left: 50%;
+  transform: translateX(-50%) scale(0.9);
+  color: #666;
+  z-index: 1000;
+  font-size: 10px;
+}
+.el-table__empty-block{
+  min-height: 300px;
+}
+
+.container-explain .el-dialog__header {
+    background-color: #fff !important;
+}
+
+.self-dialog{
+		// width: 100% !important;
+		max-width: 100% !important;
+		.el-dialog__header{
+			background-color: #fff;
+			.el-dialog__close.el-icon.el-icon-close{
+				color: #666;
+			}
+		}
+	}
+</style>
+
+<style lang="scss" scoped>
+.precontract-list{
+  border: 1px solid #DCDFE6;
+  li{
+    font-size: 14px;
+    color: #409eff;
+    cursor: pointer;
+    padding: 14px 20px;
+    border-bottom: 1px solid #DCDFE6;
+  }
+  li:last-child{
+    border: none;
+  }
+}
+
+.upload-attachment-wrap{
+  .box{
+    width: 380px;
+    display: inline-block;
+    box-sizing: border-box;
+    height: 40px;
+    line-height: 40px;
+    padding: 0 17px;
+    font-size: 14px;
+    border: 1px solid #DCDFE6;
+    border-radius: 4px;
+    margin-right: 20px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+}
+.top-wrap {
+  margin-bottom: 28px;
+  padding: 20px 30px;
+  // min-height: 50px;
+  background: #fff;
+  border: 1px solid #ececec;
+  border-radius: 4px;
+  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+}
+
+.tabs-wrap{
+  display: flex;
+  margin-bottom: 20px;
+  align-items: center;
+  .tab {
+    padding-bottom: 5px;
+		text-align: center;
+		font-size: 14px;
+		cursor: pointer;
+		transition-delay: 0.05s;
+    margin-right: 40px;
+    color: #333;
+		&:hover {
+			color: #409EFF;
+		}
+		&.act {
+      color: #409eff;
+			border-bottom: 2px solid #409EFF;
+		}
+	}
+}
+
+.list-wrap {
+  min-height: calc(100vh - 390px);
+  padding: 20px 30px 80px;
+  background: #fff;
+  margin-top: 20px;
+  position: relative;
+  border: 1px solid #ececec;
+  border-radius: 4px;
+  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+  .constract-sn {
+    cursor: pointer;
+    color: #409eff;
+  }
+  .btn {
+    font-size: 14px;
+    display: inline-block;
+    color: #409eff;
+    cursor: pointer;
+    margin: 0 3px;
+  }
+  .pagination-wrap {
+    position: absolute;
+    bottom: 24px;
+    right: 30px;
+  }
+}
+
+.download-popup-wrap {
+  text-align: center;
+  padding-bottom: 80px;
+  .top-img {
+    // width: 80%;
+    // display: block;
+    // margin: 20px auto;
+    width: 100%;
+    padding-bottom: 53%;
+    background-image: url('../../assets/img/constract/liucheng.png');
+    background-size: cover;
+    background-position: center;
+  }
+  a {
+    color: #409eff;
+    cursor: pointer;
+    // &::before {
+    //   content: "";
+    //   display: inline-block;
+    //   width: 15px;
+    //   height: 15px;
+    //   background-image: url("../../assets/img/constract/download.png");
+    //   background-size: cover;
+    //   margin-right: 10px;
+    // }
+  }
+}
+
+</style>

+ 1132 - 0
src/views/contract_manage/editContract.vue

@@ -0,0 +1,1132 @@
+<script setup>
+import { ref,reactive,computed,watch } from "vue";
+import {ElMessage,ElMessageBox} from "element-plus"
+import { useRouter,useRoute} from 'vue-router';
+import _ from 'lodash'
+import { InfoFilled } from '@element-plus/icons-vue'
+
+import { contractInterface,customInterence } from "@/api/api.js";
+import{province_sorce,city_sorce} from '@/utils/distpicker';
+import ServiceDialog from "./components/ServiceDialog.vue"; //套餐内容弹窗组件
+import QyServiceTable from "./components/QyServiceTable.vue"; //权益服务内容表格组件
+import FiccServiceTable from "./components/FiccServiceTable.vue"; //ficc服务内容表格组件
+import {CalculationDate} from '@/utils/CalculationDate'
+
+const $route = useRoute()
+const $router = useRouter()
+
+const province_sorce_value=province_sorce
+const city_sorce_value=city_sorce
+
+const contractTypeDisable1=ref(false) //能否选择新签合同
+const contractTypeDisable2=ref(false) //能否选择续约合同
+const contractTypeDisable3=ref(false) //能否选择补充协议
+const pickerOptions=ref(null)
+const timeDisable=ref(false)
+const cusLastcontract=ref(null)
+const RoleType=ref(localStorage.getItem("Role") || "")
+const radio=ref('1')//是否有补充内容 1有 2 无
+
+const currentRouteName=ref($route.meta.title)
+const contractId=ref($route.query.contractId)
+const operationList=ref([])
+const formData=ref({})
+const formRule={
+  ContractType: [{ required: true, message: "请选择合同类型", trigger: "change" }],
+  timeRange: [{ required: true, message: "请选择有效期限", trigger: "change" }],
+  OriginalPrice: [
+    { required: true, message: "请填写合同金额", trigger: "blur" },
+    // { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: "请输入正确的格式,可保留两位小数" },
+  ],
+  PayRemark: [{ required: true, message: "请填写付款方式说明", trigger: "blur" }],
+  CompanyName: [{ required: true, message: "请填写名称", trigger: "blur" }],
+  CreditCode: [{ required: true, message: "请填写信用码", trigger: "blur" }],
+  Province: [{ required: true, message: "请选择地址", trigger: "change" }],
+  Remark: [{ required: true, message: "请填写补充说明", trigger: "blur" }],
+  PayChannel:[{ required: true, message: "请填写付款方", trigger: "change" }]
+}
+
+const ficcServiceData=ref([])//ficc服务内容
+const qyServiceData=ref([])//权益服务内容
+const serviceShow=ref(false)
+const serviceCon=ref({})//选择的服务项 查看报价单/选择品种
+const selectServiceData=ref([])
+const editValue=ref({})//修改小套餐的value
+const PayChannelOptions=ref([])//搜索出付款方列表
+
+watch(()=>formData.value.ContractType,(nval)=>{
+  let obj={disabledDate() {return false}}
+  if(cusLastcontract.value){
+    if(nval==='续约合同'&&RoleType.value==='ficc_seller'){
+      // ficc 起始日期为权限中最大的时间
+      formData.value.timeRange=[]
+      let timearr=cusLastcontract.value.map(item=> item.EndDate)
+      let maxTime=Math.max.apply(null, timearr.map(item => (new Date(item)).getTime()));
+      let endDate=formatDate(new Date(maxTime))
+      console.log(endDate);
+      obj={
+        disabledDate(time) {
+          return time.getTime() < new Date(endDate).getTime();
+        }
+      }
+    }else{
+      obj={
+        disabledDate() {
+            return false
+          }
+      }
+    }
+    if(nval==='补充协议'){
+      let today=formatDate(new Date())
+      // 找出权限中最晚截止的那个作为截至日期
+      let timearr=cusLastcontract.value.map(item=> item.EndDate)
+      let maxTime=Math.max.apply(null, timearr.map(item => (new Date(item)).getTime()));
+      let endDate=formatDate(new Date(maxTime))
+      formData.value.timeRange=[today,endDate]
+      obj={disabledDate() {return true}}
+    }
+  }
+
+  if(nval==='补充协议'){
+    timeDisable.value=true
+  }else{
+    timeDisable.value=false
+  }
+  pickerOptions.value=obj
+},
+{immediate:true})
+
+const formItemRemark=ref(null)
+watch(radio,(nval, oval)=>{
+  formItemRemark.value.resetField();
+  if (nval === "1") {
+    formRule.Remark[0].required = true;
+  } else {
+    formRule.Remark[0].required = false;
+  }
+})
+
+// computed: {
+//   pickerOptions(){
+//     console.log('aaa');
+//     let obj={disabledDate() {return false}}
+//     if(this.cusLastcontract){
+//       if(this.formData.ContractType==='续约合同'&&this.RoleType==='ficc_seller'){
+//         // ficc 起始日期为权限中最大的时间
+//         this.formData.timeRange=[]
+//         let timearr=this.cusLastcontract.map(item=> item.EndDate)
+//         let maxTime=Math.max.apply(null, timearr.map(item => (new Date(item)).getTime()));
+//         let endDate=this.formatDate(new Date(maxTime))
+//         obj={
+//           disabledDate(time) {
+//             return time.getTime() < new Date(endDate).getTime();
+//           }
+//         }
+//       }else{
+//         obj={
+//           disabledDate() { 
+//               return false
+//             }
+//         }
+//       }
+//       if(this.formData.ContractType==='补充协议'){
+//         let today=this.formatDate(new Date())
+//         // 找出权限中最晚截止的那个作为截至日期
+//         let timearr=this.cusLastcontract.map(item=> item.EndDate)
+//         let maxTime=Math.max.apply(null, timearr.map(item => (new Date(item)).getTime()));
+//         let endDate=this.formatDate(new Date(maxTime))
+//         this.formData.timeRange=[today,endDate]
+//         this.timeDisable=true
+//         obj={disabledDate() {return true}}
+//       }else{
+//         this.timeDisable=false
+//       }
+//     }
+    
+//     return obj
+//   },
+// },
+
+// filters
+// 金额转中文大写
+const digitUppercase=(n)=>{
+  if (n) {
+    n=n.toString().replace(/,/g,'')
+    let fraction = ["角", "分"];
+    let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+    let unit = [
+      ["元", "万", "亿"],
+      ["", "拾", "佰", "仟"],
+    ];
+    let head = n < 0 ? "欠" : "";
+    n = Math.abs(n);
+    let s = "";
+    for (let i = 0; i < fraction.length; i++) {
+      s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, "");
+    }
+    // s = s || "整";
+
+    n = Math.floor(n);
+    for (let i = 0; i < unit[0].length && n > 0; i++) {
+      let p = "";
+      for (let j = 0; j < unit[1].length && n > 0; j++) {
+        p = digit[n % 10] + unit[1][j] + p;
+        n = Math.floor(n / 10);
+      }
+      s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s;
+    }
+    return (
+      "大写:" + (head + s.replace(/(零.)*零元/, "元").replace(/(零.)+/g, "零"))
+      // .replace(/^整$/, "零元整")
+    );
+  }
+}
+
+//计算多少年
+const formateYear=(e)=>{
+  if (!e) return;
+  if (e[0]) {
+    return `有效期为${CalculationDate(e[0],e[1])}`
+  } else {
+    return "";
+  }
+}
+
+// 社会信用码变更
+const getContractByCode=async()=>{
+  contractTypeDisable1.value=false
+  contractTypeDisable2.value=false
+  contractTypeDisable3.value=false
+  if(!formData.value.CreditCode) return
+  const res=await contractInterface.getContractTypeByCode({CreditCode:formData.value.CreditCode})
+  if(res.Ret==200){
+    let customeId=res.Data.Item&&res.Data.Item.CompanyId
+    if(customeId){
+      const res2=await customInterence.applyTurnContractType({CompanyId:customeId}) 
+      
+      if(res2.Ret===200){
+        if(res2.Data.ContractType==='新签合同'){
+          formData.value.ContractType=res2.Data.ContractType
+          contractTypeDisable1.value=false
+          contractTypeDisable2.value=true
+          contractTypeDisable3.value=true
+        }else{
+          if(RoleType.value==='ficc_seller'){
+            contractTypeDisable1.value=true
+            contractTypeDisable2.value=false
+            contractTypeDisable3.value=false
+          }
+          if(RoleType.value==='rai_seller'){
+            formData.value.ContractType=res2.Data.ContractType
+            contractTypeDisable1.value=true
+            contractTypeDisable2.value=false
+            contractTypeDisable3.value=true
+          }
+        }
+      }
+    }
+  }
+}
+
+// 解除搜索选中的客户绑定(需求修改不需要此操作2021-9-16)
+const handleUnbind=()=>{
+  ElMessageBox.confirm('此操作将解除与选择的客户绑定, 是否继续?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    contractTypeDisable1.value=false
+    contractTypeDisable2.value=false
+    contractTypeDisable3.value=false
+    // this.pickerOptions={}
+    cusLastcontract.value=null
+    timeDisable.value=false
+  }).catch(()=>{
+    console.log('取消解绑');
+  })
+}
+
+// 客户名称搜索框输入变化
+const handleCustomeInputChange=(e)=>{
+  // 将付款方初始化为客户名称
+  // const flag=this.formData.PayChannel.includes(this.formData.CompanyName)
+  // if(!flag){
+  //   this.formData.PayChannel.push(this.formData.CompanyName)
+  // }
+}
+
+// 搜索付款渠道
+// async querySearchAsyncPayChannel(queryString, cb){
+//   cb([])
+//   // if(!queryString) return
+//   let res=await contractInterface.getPayChannel({Keyword:queryString})
+//   if(res.Ret===200){
+//     if(res.Data&&res.Data.length>0){
+//       let arr=res.Data.map(item=>{
+//         return {value:item.PayChannel,...item}
+//       })
+//       cb(arr)
+//     }
+//   }
+// },
+
+// 付款渠道方式修改 多选
+const querySearchAsyncPayChannel=async (query,type)=>{
+  if(!type&&!query) return
+  let res=await contractInterface.getPayChannel({Keyword:query})
+  if(res.Ret===200){
+    PayChannelOptions.value=res.Data||[]
+  }
+}
+
+// 格式化时间
+const formatDate=(date)=>{
+  let year=date.getFullYear()
+  let month=date.getMonth()+1
+  let day=date.getDate()
+  return `${year}-${month<10?'0'+month:month}-${day<10?'0'+day:day}`
+}
+
+// 初始化客户搜索动作
+const initCustomeSelect=async(queryString)=>{
+  let CompanyType=localStorage.getItem('RoleType')
+  let res=await customInterence.customList({KeyWord:queryString,PageSize:10000,CompanyType:CompanyType,IncludeShare:true})
+  if(res.Ret===200){
+    if(res.Data.List&&res.Data.List.length>0){
+      handleSelectCustome(res.Data.List[0])
+    }
+  }
+}
+
+// 客户搜索
+const querySearchAsyncCustome=async(queryString, cb)=>{
+  cb([])
+  if(!queryString) return
+  let CompanyType=localStorage.getItem('RoleType')
+  let res=await customInterence.customList({KeyWord:queryString,PageSize:10000,CompanyType:CompanyType,IncludeShare:true})
+  // this.contractTypeDisable1=false
+  // this.contractTypeDisable2=false
+  // this.contractTypeDisable3=false
+  // // this.pickerOptions={}
+  // this.cusLastcontract=null
+  // this.timeDisable=false
+  if(res.Ret===200){
+    if(res.Data.List.length>0){
+      let arr=res.Data.List.map(item=>{
+        return {value:item.CompanyName,...item}
+      })
+      cb(arr)
+    }
+  }
+}
+
+//选择客户
+const handleSelectCustome=async(item)=>{
+  // 获取客户详情 更新表单数据
+  let res=await customInterence.customDetail({CompanyId:item.CompanyId})
+  if(res.Ret===200){
+    formData.value.CreditCode=res.Data.Item.CreditCode
+    formData.value.Province=res.Data.Item.Province
+    formData.value.City=res.Data.Item.City
+  }
+  // 更新合同类型
+  let res2=await customInterence.applyTurnContractType({CompanyId:item.CompanyId})
+  if(res2.Ret===200){
+    
+    if(res2.Data.ContractType==='新签合同'){
+      formData.value.ContractType=res2.Data.ContractType
+      contractTypeDisable1.value=false
+      contractTypeDisable2.value=true
+      contractTypeDisable3.value=true
+    }else{
+      if(RoleType.value==='ficc_seller'){
+        contractTypeDisable1.value=true
+        contractTypeDisable2.value=false
+        contractTypeDisable3.value=false
+      }
+      if(RoleType.value==='rai_seller'){
+        formData.value.ContractType=res2.Data.ContractType
+        contractTypeDisable1.value=true
+        contractTypeDisable2.value=false
+        contractTypeDisable3.value=true
+      }
+    }
+  }
+
+  // 获取客户大于今天的最后一份有效合同详情
+  let res3=await customInterence.lastContractInfo({CompanyId:item.CompanyId})
+  if(res3.Ret===200){
+    if(res3.Data&&res3.Data.length>0){
+      cusLastcontract.value=res3.Data
+    }else{
+      cusLastcontract.value=null
+    }
+  }
+}
+
+//判断合同期限 不小于一个月
+const validateTime=()=>{
+  if(formData.value.ContractType==='补充协议') return true
+  let start = new Date(formData.value.timeRange[0]).getTime();
+  let end = new Date(formData.value.timeRange[1]).getTime();
+  let oneMonth = 1000 * 60 * 60 * 24 * 29;
+  if (end - start >= oneMonth) {
+    return true;
+  } else {
+    ElMessage.warning("合同期限不能小于一个月");
+    return false;
+  }
+}
+
+//判断优惠后金额不能大于合同金额
+const validatePrice=()=>{
+  if (Number(formData.value.Price) > Number(formData.value.OriginalPrice)) {
+    ElMessage.warning("优惠后金额不得大于合同金额");
+    return false;
+  } else {
+    return true;
+  }
+}
+
+// 判断小套餐中是否选择品种/新增的行是否有数据
+const validateService=(data)=>{
+  //判断品种列是否有值
+  let arr = [];
+  data.forEach((item) => {
+    item.forEach((item2) => {
+      if (item2.HeadName === "品种") {
+        arr.push(...item2.ValueId);
+      }
+    });
+  });
+  // 判断行是否有值
+  let arr2 = [];
+  data.forEach((item, index) => {
+    let arr = item.filter((item2) => {
+      if (!item2.Value) return item2;
+    });
+    if (arr.length === item.length) {
+      arr2.push(index);
+    }
+  });
+
+  if (!arr.length&&formData.value.ContractType!=='补充协议') {
+    ElMessage.warning("至少选择一个品种");
+    return false;
+  }
+
+  if (arr2.length) {
+    ElMessage.warning("行内至少填一项");
+    return false;
+  }
+
+  return true;
+}
+
+//获取合同操作记录
+const getContractOperationList=()=>{
+  contractInterface.getContractOperationList({ ContractId: contractId.value }).then((res) => {
+    if (res.Ret === 200) {
+      operationList.value = res.Data.List;
+    }
+  });
+}
+
+//选地地区时 选则的省份改变重置city为空
+const provinceChange=(e)=>{
+  if(e.value!=formData.value.Province){
+    // this.formData.City=''
+    formData.value.Province=e.value
+  }
+}
+
+//选择地区
+const selectRegion=(e)=>{
+  formData.value.Province = e.province.value=='省'?'':e.province.value;
+  formData.value.City = e.city.value=='市'?'':e.city.value;
+}
+
+// 判断套餐权限
+const handleValidate=(e)=>{
+  let tag=true
+  let tagsmall=false
+  // ficc 补充协议 不允许有选择过的
+  if(RoleType.value === "ficc_seller"&&e.ContractType==='补充协议'){
+    // 是否选择大套餐 大套餐为全部品种 不能选
+    e.Service.forEach(item=>{
+      // 大套餐
+      if(item.ChartPermissionId===0&&item.ServiceTemplateId===1){
+        tag=false
+        ElMessage.warning('FICC大套餐不可选')
+      }
+      // 小套餐 判断其中ficc周报是否有重复选择的权限
+      if(item.ChartPermissionId===0&&item.ServiceTemplateId===2){
+        let temIdarr=[]
+        item.Detail.forEach(item2=>{
+          item2.forEach(item3=>{
+            if(item3.Value==='FICC周报'){
+              item2.forEach(item4=>{
+                if(item4.HeadName==='品种'){
+                  temIdarr=item4.ValueId
+                }
+              })
+            }
+          })
+        })
+
+        cusLastcontract.value.forEach(item4=>{
+          if(temIdarr.indexOf(item4.ChartPermissionId)!=-1){
+            tag=false
+            tagsmall=true
+            // this.$message.warning('小套餐中权限重复')
+          }
+        })
+      }
+
+      // 市场策略
+      if(item.ChartPermissionId!==0){
+        cusLastcontract.value.forEach(item2=>{
+          if(item2.ChartPermissionId===item.ChartPermissionId){
+            ElMessage.warning(`${item.Title}不可选`)
+            tag=false
+          }
+        })
+      }
+    })
+  }
+
+  // 权益 续约合同 
+  if(RoleType.value === "rai_seller"&&e.ContractType==='续约合同'){
+    const time1=new Date(formData.value.timeRange[0]).getTime()//选择的开始时间
+    const time2=new Date(formData.value.timeRange[1]).getTime()//选择的结束时间
+    cusLastcontract.value.forEach(item=>{
+      const time3=new Date(item.StartDate).getTime()
+      const time4=new Date(item.EndDate).getTime()
+      if(time1>time4||time2<time3){
+        console.log('选择时间和上一份无重叠');
+      }else{
+        console.log('时间重叠');
+        e.Service.forEach(item2=>{
+          console.log(item2.ChartPermissionId,item.ChartPermissionId);
+          if(item2.ChartPermissionId===item.ChartPermissionId){
+            ElMessage.warning('同行业有重叠的合同期限,请核实后再提交')
+            tag=false
+          }
+        })
+
+      }
+    })
+    
+  }
+
+  // 小套餐统一一个提示
+  if(tagsmall){
+    ElMessage.warning('小套餐中权限重复')
+  }
+  return tag
+}
+
+const formRef=ref(null)
+const FiccServiceTableRef=ref(null)
+const QyServiceTableRef=ref(null)
+const ServiceDialogRef=ref(null)
+//提交表单 存草稿、预览、提交
+const handleOperation=_.debounce(function(submitType) {
+  formRef.value.validate((valid) => {
+    if (valid) {
+      let temarr = [];
+      if (RoleType.value === "ficc_seller") {
+        FiccServiceTableRef.value.tableData.forEach((item) => {
+          let obj = {
+            ServiceTemplateId: "",
+            Value: "",
+            Detail: [],
+            Title: item.Title,
+            ChartPermissionId:item.ChartPermissionId
+          };
+          obj.ServiceTemplateId = item.ServiceTemplateId;
+          obj.Value = item.Value;
+          if (item.selected) {
+            //小套餐情况
+            if (item.Detail) {
+              if (ServiceDialogRef.value.tableHeadData.length === 0) {
+                let arr = [];
+                formData.value.Service.forEach((item2) => {
+                  if (item2.ServiceTemplateId === item.ServiceTemplateId) {
+                    arr = item2.DetailList.map((rowItem) => {
+                      let rowArr = [];
+                      for (let key in rowItem) {
+                        if (key.substr(0, 3) === "Col" && rowItem[key] !== "") {
+                          rowArr.push(JSON.parse(rowItem[key]));
+                        }
+                      }
+                      return rowArr;
+                    });
+                  }
+                });
+                obj.Detail = arr;
+              } else {
+                obj.Detail = [ServiceDialogRef.value.tableHeadData, ...ServiceDialogRef.value.tableData];
+              }
+            }
+            temarr.push(obj);
+          }
+        });
+      } else {
+        // 只要一个分类里面 主观和客观其中一个被勾选 这个分类就要传
+        QyServiceTableRef.value.selectAllArr.map(item =>{
+          if(QyServiceTableRef.value.checkList.find(it => it.indexOf(item.name)!=-1 && it.indexOf("升级")==-1)){
+            temarr.push({
+              ServiceTemplateId: item.ServiceTemplateId,
+              Value: item.value,
+              Detail: null,
+              Title: item.name,
+              ChartPermissionId:item.ChartPermissionId
+            })
+          }
+        })
+        QyServiceTableRef.value.tableData.list.forEach((item) => {
+          let obj = {
+            ServiceTemplateId: "",
+            Value: "",
+            Detail: null,
+            Title: item.Title,
+            Title: item.Title == item.fatherName ? item.Title:`${item.fatherName}(${item.Title})`,
+            ChartPermissionId:item.ChartPermissionId
+          };
+          obj.ServiceTemplateId = item.ServiceTemplateId;
+          obj.Value = item.Value;
+          let flag = ''
+          if(item.Title == item.fatherName){
+            //没有主客观
+              flag= QyServiceTableRef.value.checkList.indexOf(item.Title);
+          }else{
+            flag= QyServiceTableRef.value.checkList.indexOf(`${item.fatherName}(${item.Title})`);
+          }
+          if (flag !== -1) {
+            temarr.push(obj);
+          }
+        });
+      }
+
+      // 判断地址
+      if(formData.value.Province!='海外'&&!formData.value.City){
+        ElMessage.warning('请选择地址')
+        return
+      }
+
+      // 判断合同期限 不小于一个月
+      if (!validateTime()) {
+        return;
+      }
+      //判断金额
+      if (!validatePrice()) {
+        return;
+      }
+      //判断是否选择了套餐
+      if(!temarr.length){
+        ElMessage.warning('请选择套餐')
+        return
+      }
+
+      //判断小套餐
+      let flag = true;
+      temarr.forEach((item) => {
+        if (item.Detail&&item.Detail.length) {
+          flag = validateService(item.Detail.slice(1));
+        }
+      });
+      if (!flag) return;
+
+      let params = {
+        ContractType: formData.value.ContractType,
+        ContractBusinessType:"业务合同",
+        StartDate: formData.value.timeRange[0],
+        EndDate: formData.value.timeRange[1],
+        OriginalPrice: Number(formData.value.OriginalPrice.toString().replace(/,/g,'')),
+        Price: Number(formData.value.Price.toString().replace(/,/g,'')),
+        PayRemark: formData.value.PayRemark,
+        CompanyName: formData.value.CompanyName,
+        CreditCode: formData.value.CreditCode,
+        Province: formData.value.Province,
+        City: formData.value.City,
+        Address: formData.value.Address,
+        Fax: formData.value.Fax,
+        Phone: formData.value.Phone,
+        Postcode: formData.value.Postcode,
+        Remark: formData.value.Remark,
+        PayChannel:formData.value.PayChannel.join(','),
+        SellerRemark:formData.value.SellerRemark,
+        TemplateId: RoleType.value === "ficc_seller" ? 1 : 2,
+        Service: temarr,
+      };
+
+      console.log(params);
+      // 判断套餐权限
+      if(cusLastcontract.value&&!handleValidate(params)) return
+
+      // 存草稿
+      if(submitType==='存草稿'){
+        handleSave(params)
+      }
+
+      //预览
+      if(submitType==='预览'){
+        handlePreview(params)
+      }
+
+      //提交
+      if(submitType==='提交'){
+        handleSubmit(params)
+      }
+    }else{
+      ElMessage.warning('请完善必填项')
+    }
+  });
+},200)
+
+//存草稿
+const handleSave=(params)=>{
+  
+  let type = $route.query.type;
+  // 复制模板(copy) 
+  if (type === "copy") {
+    params = {
+      SourceId: formData.value.ContractId,
+      ...params,
+      IsAudit: false,
+    };
+    contractInterface.addContract(params).then((res) => {
+      if (res.Ret === 200) {
+        $router.go(-1);
+      }
+    });
+  }
+  // 申请重审(applyRetrial) 修改合同(modifyConstract) 编辑(edit)修改重审(modifyAndApply)
+  if (type === "applyRetrial" || type === "modifyConstract" || type === "edit"||type==='modifyAndApply') {
+    params = {
+      ContractId: formData.value.ContractId,
+      ...params,
+      ReAudit:false
+    };
+    contractInterface.editContract(params).then((res) => {
+      if (res.Ret === 200) {
+        $router.go(-1);
+      }
+    });
+  }
+    
+}
+
+//预览
+const handlePreview=(params)=>{
+  contractInterface.previewContract(params).then((res) => {
+    if (res.Ret === 200) {
+      sessionStorage.setItem("contractdtl", res.Data.Html);
+      let { href } = $router.resolve({ path: "/contractdtl" });
+      window.open(href, "_blank");
+    }
+  }); 
+}
+
+//提交
+const handleSubmit=(params)=>{
+  let type = $route.query.type;
+  // 复制模板(copy) 
+  if (type === "copy") {
+    params = {
+      SourceId: formData.value.ContractId,
+      ...params,
+      IsAudit: true,
+    };
+    contractInterface.addContract(params).then((res) => {
+      if (res.Ret === 200) {
+        $router.go(-1);
+      }
+    });
+  }
+  // 申请重审(applyRetrial) 修改合同(modifyConstract) 编辑(edit)修改重审(modifyAndApply)
+  if (type === "applyRetrial" || type === "modifyConstract" || type === "edit"||type==='modifyAndApply') {
+    params = {
+      ContractId: formData.value.ContractId,
+      ...params,
+    };
+    contractInterface.editContract(params).then((res) => {
+      if (res.Ret === 200) {
+        $router.go(-1);
+      }
+    });
+  }
+}
+
+
+//获取合同详情
+const getContractDetail=()=>{
+  contractInterface.getContractDetail({ ContractId: Number(contractId.value) }).then((res) => {
+    if (res.Ret === 200) {
+      formData.value = { ...res.Data, timeRange: [res.Data.StartDateStr, res.Data.EndDateStr] };
+      formData.value.PayChannel=res.Data.PayChannel.split(',')||['无']
+      if (res.Data.Remark) {
+        radio.value = "1";
+      } else {
+        radio.value = "2";
+      }
+      selectServiceData.value = res.Data.Service;
+      getServiceList();
+      initCustomeSelect(res.Data.CreditCode)
+    }
+  });
+}
+
+//获取服务套餐模板数据
+const getServiceList=()=>{
+  let ProductId = RoleType.value === "ficc_seller" ? 1 : 2;
+  contractInterface.getServiceList({ ProductId }).then((res) => {
+    if (res.Ret === 200) {
+      if (RoleType.value === "ficc_seller") {
+        ficcServiceData.value = res.Data;
+      } else {
+        qyServiceData.value = res.Data;
+      }
+    }
+  });
+}
+
+//小套餐点击保存 更新数据
+const serviceSave=(e)=>{
+  editValue.value = { ServiceTemplateId: e.ServiceTemplateId, Value: e.Value, tableData: e.tableData, tableHeadData: e.tableHeadData };
+  // this.ficcServiceData.forEach((item) => {
+  //   if (item.ServiceTemplateId === e.ServiceTemplateId) {
+  //     item.Value = e.Value;
+  //   }
+  // });
+  // this.selectServiceData.forEach((item) => {
+  //   if (item.ServiceTemplateId === e.ServiceTemplateId) {
+  //     item.Value = e.Value;
+  //   }
+  // });
+}
+
+//显示查看报价单弹窗
+const handleShowService=(e)=>{
+  serviceCon.value = e;
+  serviceShow.value = true;
+}
+
+//关闭查看报价单弹窗
+const serviceClose=()=>{
+  serviceShow.value = false;
+}
+
+// 金额输入框获取焦点
+const handlePriceBoxFocus=(key)=>{
+  let val=formData.value[key].toString()
+  val=val.replace(/,/g,'')
+  formData.value[key]=val
+}
+// 金额输入框获失去焦点
+const handlePriceBoxBlur=(key)=>{
+  let str=formData.value[key].toString()
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  formData.value[key]=num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+
+getContractDetail();
+getContractOperationList();
+
+</script>
+
+<template>
+  <div class="flex addconstract-container">
+    <el-form ref="formRef" :model="formData" label-position="left" :rules="formRule" label-width="110px" style="width: 80%"
+    size="large">
+      <section class="section">
+        <h2 class="section-title">客户信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="甲方名称" prop="CompanyName" style="width: 50%">
+              <!-- <el-input v-model="formData.CompanyName" placeholder="请输入名称" style="width: 350px"></el-input> -->
+              <el-autocomplete
+                v-model="formData.CompanyName"
+                :fetch-suggestions="querySearchAsyncCustome"
+                placeholder="请输入或者搜索客户名称"
+                @select="handleSelectCustome"
+                @blur="handleCustomeInputChange"
+                style="width: 50%"
+              ></el-autocomplete>
+            </el-form-item>
+            <el-form-item label="社会信用码" prop="CreditCode" style="width: 50%">
+              <el-input v-model="formData.CreditCode" placeholder="请输入社会信用码" style="width: 350px" :disabled="cusLastcontract" @input="getContractByCode"></el-input>
+              <!-- <span style="font-size:14px;color:#4099ef;cursor: pointer;" v-if="cusLastcontract" @click="handleUnbind">解除绑定</span> -->
+            </el-form-item>
+          </div>
+
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="公司地址" prop="Province" style="width: 50%">
+              <v-distpicker :province-source="province_sorce_value"
+                :city-source="city_sorce_value"  :province="formData.Province" :city="formData.City" hide-area @province="provinceChange" @selected="selectRegion"></v-distpicker>
+            </el-form-item>
+            <el-form-item label="详细地址" prop="address" style="width: 50%">
+              <el-input v-model="formData.Address" placeholder="请输入详细地址" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="传真" prop="customeCz" style="width: 50%">
+              <el-input v-model="formData.Fax" placeholder="请输入传真" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="电话" prop="customeTel" style="width: 50%">
+              <el-input v-model="formData.Phone" placeholder="请输入电话" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <el-form-item label="邮编" prop="postCode" class="border-top">
+            <el-input v-model="formData.Postcode" placeholder="请输入邮编" style="width: 350px"></el-input>
+          </el-form-item>
+        </div>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">合同信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="合同编号" style="width: 50%">
+              <span>{{ formData.ContractCode }}</span>
+            </el-form-item>
+            <el-form-item label="合同归属" style="width: 50%">
+              <span>{{ formData.ProductId === 1 ? "FICC" : "权益" }}</span>
+            </el-form-item>
+          </div>
+          <el-form-item label="合同类型" prop="ContractType" class="border-top">
+            <el-radio-group v-model="formData.ContractType">
+              <div style="display:flex">
+                <div style="margin-right:10px;">
+                  <el-radio label="新签合同" :disabled="contractTypeDisable1">新签合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>没有正式转试用记录的客户,在申请转正时提交的合同</template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right:10px">
+                  <el-radio label="续约合同" :disabled="contractTypeDisable2">续约合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>
+                      1、有正式转试用记录的客户,在申请转正时提交的合同<br>
+										  2、所有客户在续约申请时提交的合同
+                    </template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right:10px" v-if="RoleType!=='rai_seller'">
+                  <el-radio label="补充协议" :disabled="contractTypeDisable3">补充协议</el-radio>
+                </div>
+              </div>
+            </el-radio-group>
+          </el-form-item>
+          <div class="flex border-top">
+            <el-form-item label="合同期限" prop="timeRange" style="width: 50%">
+              <el-date-picker 
+                style="max-width: 350px;"
+                v-model="formData.timeRange" 
+                type="daterange" 
+                value-format="yyyy-MM-dd" 
+                range-separator="至" 
+                start-placeholder="开始日期" 
+                end-placeholder="结束日期" 
+                :disabled="timeDisable"
+                :picker-options="pickerOptions"> 
+              </el-date-picker>
+            </el-form-item>
+            <span style="line-height: 40px">{{ formateYear(formData.timeRange) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="合同金额" prop="OriginalPrice" style="width: 50%">
+              <el-input v-model="formData.OriginalPrice"  @focus="handlePriceBoxFocus('OriginalPrice')" @blur="handlePriceBoxBlur('OriginalPrice')" placeholder="请输入合同金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(formData.OriginalPrice) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item label="优惠后金额" prop="Price" style="width: 50%">
+              <el-input v-model="formData.Price" @focus="handlePriceBoxFocus('Price')" @blur="handlePriceBoxBlur('Price')" placeholder="请输入优惠后金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(formData.Price) }}</span>
+          </div>
+
+          <el-form-item label="付款方式说明" prop="PayRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.PayRemark" placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)" style="width: 80%"></el-input>
+            <p>说明模板:甲方自合同生效日起的十日之内一次性支付一年服务费,乙方收款后为甲方开具合法有效的增值税发票。</p>
+          </el-form-item>
+          <el-form-item label="付款方" prop="PayChannel" class="border-top">
+            <!-- <el-input type="textarea" v-model="formData.PayChannel" placeholder="填写代支付的券商名称/期货公司名称,若非代付填写无" style="width: 80%"></el-input> -->
+            <!-- <el-autocomplete
+              v-model="formData.PayChannel"
+              :fetch-suggestions="querySearchAsyncPayChannel"
+              placeholder="请输入"
+              style="width: 80%"
+            ></el-autocomplete> -->
+            <el-select
+                v-model="formData.PayChannel"
+                multiple
+                filterable
+                remote
+                allow-create
+                placeholder="请输入关键词"
+                :remote-method="querySearchAsyncPayChannel"
+                style="width: 80%">
+                <el-option
+                  v-for="item in PayChannelOptions"
+                  :key="item.PayChannel"
+                  :label="item.PayChannel"
+                  :value="item.PayChannel">
+                </el-option>
+              </el-select>
+            <p>如果为代付,则需要填写代付方名称(期货公司或者证券公司),请勿填写现金/转账</p>
+          </el-form-item>
+          <!-- <el-form-item label="备注" prop="SellerRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.SellerRemark" placeholder="审批人查看,不在生成合同中展示" style="width: 80%"></el-input>
+          </el-form-item> -->
+        </div>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">服务内容</h2>
+        <div class="section-container">
+          <!-- ficc 服务内容表格 -->
+          <FiccServiceTable
+            ref="FiccServiceTableRef"
+            :canEdit="true"
+            :serviceData="ficcServiceData"
+            :hasSercive="selectServiceData"
+            :editValue="editValue"
+            :contractType="formData.ContractType"
+            :isEdit="true"
+            @handleShowService="handleShowService"
+            v-if="RoleType === 'ficc_seller'"
+          ></FiccServiceTable>
+          <!-- 权益 服务内容表格 -->
+          <QyServiceTable ref="QyServiceTableRef" :canEdit="true" :serviceData="qyServiceData" :hasSercive="selectServiceData" @handleShowService="handleShowService" v-else></QyServiceTable>
+        </div>
+
+        <p style="margin-top: 30px; margin-bottom: 20px">补充内容(eg额外赠送、路演次数规定)</p>
+        <el-radio v-model="radio" label="2">无</el-radio>
+        <el-radio v-model="radio" label="1">有</el-radio>
+        <el-form-item prop="Remark" label-width="0" ref="formItemRemark">
+          <el-input v-if="radio === '1'" type="textarea" v-model="formData.Remark" rows="5" placeholder="请输入内容" style="margin: 20px 0; display: block; box-sizing: border-box"></el-input>
+        </el-form-item>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">审批备注</h2>
+        <div class="section-container">
+          <el-form-item label="备注" prop="SellerRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.SellerRemark" placeholder="请输入备注(仅供审批人查看,不在生成合同中展示)" style="width: 80%"></el-input>
+          </el-form-item>
+        </div>
+      </section>
+    </el-form>
+    <div class="right-wrap">
+      <div style="text-align: center" v-if="currentRouteName === '编辑合同' || currentRouteName === '复制模板'||currentRouteName === '重审合同'||currentRouteName === '修改重审'">
+        <el-button type="primary" plain style="width: 30%;min-width:70px;margin-bottom:10px" @click="handleOperation('存草稿')" size="large">存草稿</el-button>
+        <el-button type="primary" style="width: 30%;margin-left:3%;min-width:70px;margin-bottom:10px" @click="handleOperation('预览')" size="large">预览</el-button>
+        <el-button type="primary" style="width: 30%;margin-left:3%;min-width:70px;margin-bottom:10px" @click="handleOperation('提交')" size="large">提交</el-button>
+      </div>
+      <!-- <div style="text-align: center" v-if="currentRouteName === '重审合同'">
+        <el-button type="primary" plain style="width: 30%;min-width:70px;margin-bottom:10px" @click="handleSave">存草稿</el-button>
+        <el-button type="primary" style="width: 30%;min-width:70px" @click="handlePreview">预览</el-button>
+        <el-button type="primary" style="width: 30%;min-width:70px" @click="handleSubmit">提交</el-button>
+      </div> -->
+      <div class="timeline-wrap">
+        <el-timeline>
+          <el-timeline-item color="#409EFF" v-for="item in operationList" :key="item.Id" placement="top" :timestamp="item.CreateTimeStr"> {{ item.OpUserName }}{{ item.Remark }} </el-timeline-item>
+        </el-timeline>
+      </div>
+    </div>
+
+    <!-- 套餐 -->
+    <ServiceDialog ref="ServiceDialogRef" :serviceShow="serviceShow" @serviceClose="serviceClose" @serviceSave="serviceSave" :serviceCon="serviceCon"></ServiceDialog>
+  </div>
+</template>
+
+<style>
+.el-radio__input.is-checked .el-radio__inner {
+  background-color: transparent;
+}
+.el-radio__inner::after {
+  width: 6px;
+  height: 6px;
+  background-color: #409eff;
+}
+.el-checkbox__label {
+  font-size: 16px !important;
+}
+.el-form-item {
+  margin-bottom: 30px;
+}
+.el-input.is-disabled .el-input__inner {
+  color: #606266;
+}
+.el-radio__input.is-disabled + span.el-radio__label {
+  color: #606266;
+}
+.el-range-editor.is-disabled input {
+  color: #606266;
+}
+.el-textarea.is-disabled .el-textarea__inner {
+  color: #606266;
+}
+.el-timeline-item__tail {
+  border-left: 2px solid #409eff;
+}
+</style>
+
+<style lang="scss" scoped>
+.addconstract-container {
+  min-height: calc(100vh - 250px);
+  position: relative;
+  font-size: 16px;
+  color: #000;
+}
+.flex {
+  display: flex;
+}
+.section {
+  background-color: #fff;
+  border: 1px solid #aab4cc;
+  border-radius: 4px;
+  padding: 20px;
+  margin-bottom: 20px;
+  .section-title {
+    margin-bottom: 30px;
+  }
+  .border-top {
+    padding-top: 30px;
+    border-top: 1px solid #dcdfe6;
+  }
+}
+
+.right-wrap {
+  margin-left: 20px;
+  flex: 1;
+  .timeline-wrap {
+    margin-top: 10px;
+    background-color: #fff;
+    border: 1px solid #aab4cc;
+    padding: 20px;
+    border-radius: 4px;
+    text-align: left;
+    height: calc(100% - 120px);
+    max-height: 1130px;
+    overflow-y: auto;
+  }
+}
+</style>

+ 609 - 0
src/views/contract_manage/editContractDC.vue

@@ -0,0 +1,609 @@
+<script setup>
+import { ref,nextTick } from "vue";
+import {ElMessage} from "element-plus"
+import { useRouter,useRoute} from 'vue-router';
+import _ from 'lodash'
+import { InfoFilled } from '@element-plus/icons-vue'
+
+import { contractInterface } from "@/api/api.js";
+import{province_sorce,city_sorce} from '@/utils/distpicker';
+import QyServiceTable from "./components/QyServiceTable.vue"; //权益服务内容表格组件
+import FiccServiceTable from "./components/FiccServiceTable.vue"; //ficc服务内容表格组件
+import { CalculationDate } from "@/utils/CalculationDate";
+import {formatTime} from '@/hooks/mixins/index.js'
+
+const $router = useRouter()
+const $route = useRoute()
+
+const province_sorce_value=province_sorce
+const city_sorce_value=city_sorce
+
+const RoleType=ref(localStorage.getItem("Role") || "")
+const formData=ref({})
+const formRule={
+  CompanyName: [{ required: true, message: "请填写名称", trigger: "blur" }],
+  CreditCode: [{ required: true, message: "请填写信用码", trigger: "blur" }],
+  Province: [{ required: true, message: "请选择地址", trigger: "change" }],
+  OriginalPrice: [
+    { required: true, message: "请填写代付金额", trigger: "blur" },
+    // { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: "请输入正确的格式,可保留两位小数" },
+  ],
+  trueUseName: [{ required: true, message: "请输入关键字", trigger: "change" }],
+  PayRemark: [{ required: true, message: "请填写付款方式说明", trigger: "blur" }],
+}
+
+const searchList=ref([])
+const contractList=ref([])
+const showContractList=ref(false)
+const relationContractData=ref(null) //选择的关联合同数据
+const ficcServiceData=ref(null) //ficc 底部表格数据
+const qyServiceData=ref(null) //权益底部表格数据
+const serviceShow=ref(false) //是否显示查看报价单
+const serviceCon=ref({}) //选择的服务项 查看报价单/选择品种
+const operationList=ref([])
+const showEdit=ref(false)//是否显示编辑按钮
+
+const formatPrice=(str)=>{
+  if(!str) return ''
+  str=str.toString()
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  return num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+
+// 金额转中文大写
+const digitUppercase=(n)=>{
+  if(!n) return ''
+  n=n.toString().replace(/,/g,'')
+  let fraction = ["角", "分"];
+  let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+  let unit = [
+    ["元", "万", "亿"],
+    ["", "拾", "佰", "仟"],
+  ];
+  let head = n < 0 ? "欠" : "";
+  n = Math.abs(n);
+  let s = "";
+  for (let i = 0; i < fraction.length; i++) {
+    s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, "");
+  }
+  // s = s || "整";
+
+  n = Math.floor(n);
+  for (let i = 0; i < unit[0].length && n > 0; i++) {
+    let p = "";
+    for (let j = 0; j < unit[1].length && n > 0; j++) {
+      p = digit[n % 10] + unit[1][j] + p;
+      n = Math.floor(n / 10);
+    }
+    s = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + s;
+  }
+  return (
+    "大写:" + (head + s.replace(/(零.)*零元/, "元").replace(/(零.)+/g, "零"))
+    // .replace(/^整$/, "零元整")
+  );
+}
+//计算多少年
+const formateYear=(e)=>{
+  if (e[0]) {
+    return `有效期为${CalculationDate(e[0], e[1])}`;
+  } else {
+    return "";
+  }
+}
+
+// 搜索出客户
+const customeSearch=async(query)=>{
+  if (!query) return;
+  const res = await contractInterface.getBusinessContractCompanyNameList({ Keyword: query });
+  if (res.Ret === 200) {
+    searchList.value = res.Data;
+  }
+}
+
+// 选择客户并搜索出其下已签回合同
+const handleSelectTrueUseName=(e)=>{
+  nextTick(async()=>{
+    if(isBlurManual.value){
+      isBlurManual.value=false
+      return 
+    }
+    if (e) return;
+    const res = await contractInterface.getBusinessContractList({ CompanyName: formData.value.trueUseName });
+    if (res.Ret === 200) {
+      showContractList.value = true;
+      nextTick(() => {
+        contractList.value = res.Data.List;
+      });
+    }
+  })
+}
+
+// 确认关联
+const handleRelation=async()=>{
+  if (!formData.value.RelationContractId) {
+    ElMessage.warning("请选择一份合同进行关联");
+    return;
+  }
+  const res = await contractInterface.getContractDetail({ ContractId: formData.value.RelationContractId });
+  if (res.Ret === 200) {
+    relationContractData.value = res.Data;
+    getServiceList();
+    showContractList.value = false;
+  }
+}
+const trueUseNameRef=ref(null)
+const isBlurManual=ref(false)
+const closeTrueUseNameDia=()=>{
+  // element-plus 会在弹窗关闭后,返回焦点给el-select组件……
+  console.log('失去焦点');
+  isBlurManual.value=true
+  trueUseNameRef.value.blur()
+}
+
+// 获取合同详情
+const getDetail=async()=>{
+  const res=await contractInterface.getContractDetail({
+    ContractId:$route.query.contractId
+  })
+  if(res.Ret===200){
+    formData.value={
+      ...res.Data,
+      trueUseName:res.Data.RelationContractDetailList[0].CompanyName,
+      RelationContractId:res.Data.RelationContractDetailList[0].ContractId
+    }
+    relationContractData.value=res.Data.RelationContractDetailList[0]
+    getServiceList()
+    
+  }
+}
+
+//获取合同操作记录
+const getContractOperationList=()=>{
+  contractInterface.getContractOperationList({ContractId:$route.query.contractId}).then(res=>{
+    if(res.Ret===200){
+      operationList.value=res.Data.List&&res.Data.List.map(item=>{
+        return {...item,CreateTimeStr:item.CreateTimeStr.replace(/-/g,'.')}
+      })||[]
+    }
+  })
+}
+
+//获取服务套餐模板数据
+const getServiceList=()=>{
+  contractInterface.getServiceList({ ProductId: relationContractData.value.ProductId }).then((res) => {
+    if (res.Ret === 200) {
+      if (relationContractData.value.ProductId === 1) {
+        ficcServiceData.value = res.Data;
+      } else {
+        qyServiceData.value = res.Data;
+      }
+    }
+  });
+}
+
+//显示查看报价单弹窗
+const handleShowService=(e)=>{
+  // 小套餐情况处理表格数据
+  if (e.Detail) {
+    let temarr = e.Detail.map((rowItem) => {
+      let rowArr = [];
+      for (let key in rowItem) {
+        if (key.substring(0, 3) === "Col" && rowItem[key] !== "") {
+          rowArr.push(JSON.parse(rowItem[key]));
+        }
+      }
+      return rowArr;
+    });
+    serviceCon.value = { ...e, tableHeadData: temarr[0], tableData: temarr.slice(1) };
+  } else {
+    serviceCon.value = e;
+  }
+  serviceShow.value = true;
+}
+
+//选地地区时 选则的省份改变重置city为空
+const provinceChange=(e)=>{
+  if(e.value!=formData.value.Province){
+    formData.value.Province=e.value
+  }
+}
+
+//选择地区
+const selectRegion=(e)=>{
+  formData.value.Province =e.province.value=='省'?'':e.province.value;
+  formData.value.City = e.city.value=='市'?'':e.city.value;
+}
+const formRef=ref(null)
+// 提交
+const handleSubmit=(type)=>{
+  formRef.value.validate(async (valid) => {
+    if (valid) {
+      let params = {
+        ContractType:"新签合同",
+        ContractBusinessType:"代付合同",
+        Address: formData.value.Address,
+        City: formData.value.City,
+        CompanyName: formData.value.CompanyName,
+        CreditCode: formData.value.CreditCode,
+        Province: formData.value.Province,
+        Fax: formData.value.Fax,
+        Phone: formData.value.Phone,
+        Postcode: formData.value.Postcode,
+        OriginalPrice: Number(formData.value.OriginalPrice.toString().replace(/,/g,'')),
+        sellerRemark: formData.value.sellerRemark,
+        PayRemark: formData.value.PayRemark,
+        TemplateId: RoleType.value === "ficc_seller" ? 1 : 2,
+        RelationContractId: formData.value.RelationContractId,
+      };
+      if(!params.City){
+        ElMessage.warning("请选择城市")
+        return
+      }
+      let routertype=$route.query.type;
+      if(routertype==='copy'){
+        params={
+          SourceId:Number($route.query.contractId),
+          ...params,
+        }
+      }
+      if(routertype === "applyRetrial" || routertype === "modifyConstract" || routertype === "edit"||routertype==='modifyAndApply'){
+        params={
+          ContractId:Number($route.query.contractId),
+          ...params
+        }
+      }
+
+      if (type === "预览") {
+        params = { ...params, IsAudit: false,ReAudit:false };
+        handlePreview(params);
+        return;
+      } else if (type === "存草稿") {
+        params = { ...params, IsAudit: false,ReAudit:false };
+      } else {
+        params = { ...params, IsAudit: true,ReAudit:true };
+      }
+
+      if(routertype==='copy'){
+        const res = await contractInterface.addContract(params);
+        if (res.Ret === 200) {
+          $router.go(-1);
+        }
+      }
+      if(routertype === "applyRetrial" || routertype === "modifyConstract" || routertype === "edit"||routertype==='modifyAndApply'){
+        const res = await contractInterface.editContract(params);
+        if (res.Ret === 200) {
+          $router.go(-1);
+        }
+      }
+    }else{
+      ElMessage.warning('请完善必填项')
+    }
+  });
+}
+//前去预览
+const handlePreview=(params)=>{
+  contractInterface.previewContract(params).then((res) => {
+    if (res.Ret === 200) {
+      sessionStorage.setItem("contractdtl", res.Data.Html);
+      let { href } = $router.resolve({ path: "/contractdtl" });
+      window.open(href, "_blank");
+    }
+  });
+}//选地地区时 选则的省份改变重置city为空
+
+
+// 金额输入框获取焦点
+const handlePriceBoxFocus=(key)=>{
+  let val=formData.value[key].toString()
+  val=val.replace(/,/g,'')
+  formData.value[key]=val
+}
+
+// 金额输入框获失去焦点
+const handlePriceBoxBlur=(key)=>{
+  let str=formData.value[key].toString()
+  let num1='',num2=''
+  if(str.indexOf(".")!=-1){
+    num1=str.substring(0,str.indexOf("."))
+    num2=str.substring(str.length,str.indexOf("."))
+    if(Number(num2)<=0){
+      num2=''
+    }
+  }else{
+    num1=str
+  }
+  formData.value[key]=num1.replace(/(?!^)(?=(\d{3})+$)/g, ',')+num2
+}
+
+getDetail()
+getContractOperationList()
+
+</script>
+
+<template>
+  <div class="contractdetail-dc flex">
+    <el-form ref="formRef" :model="formData" label-position="left" :rules="formRule" label-width="110px" style="width: 80%"
+    size="large">
+      <section class="section">
+        <h2 class="section-title">客户信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="代付方" prop="CompanyName" style="width: 50%">
+              <el-input v-model="formData.CompanyName" placeholder="请输入名称" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="社会信用码" prop="CreditCode" style="width: 50%">
+              <el-input v-model="formData.CreditCode" placeholder="请输入社会信用码" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="公司地址" prop="Province" style="width: 50%">
+              <v-distpicker :province-source="province_sorce_value"
+                :city-source="city_sorce_value"  :province="formData.Province" :city="formData.City" hide-area @province="provinceChange" @selected="selectRegion"></v-distpicker>
+            </el-form-item>
+            <el-form-item label="详细地址" prop="Address" style="width: 50%">
+              <el-input v-model="formData.Address" placeholder="请输入详细地址" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="传真" prop="Fax" style="width: 50%">
+              <el-input v-model="formData.Fax" placeholder="请输入传真" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="电话" prop="Phone" style="width: 50%">
+              <el-input v-model="formData.Phone" placeholder="请输入电话" style="width: 350px"></el-input>
+            </el-form-item>
+          </div>
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item label="邮编" prop="Postcode" style="width: 50%">
+              <el-input v-model="formData.Postcode" placeholder="请输入邮编" style="width: 350px"></el-input>
+            </el-form-item>
+            <el-form-item label="代付金额" prop="OriginalPrice" style="width: 50%">
+              <el-input v-model="formData.OriginalPrice" @focus="handlePriceBoxFocus('OriginalPrice')" @blur="handlePriceBoxBlur('OriginalPrice')" placeholder="请输入金额" style="width: 350px"></el-input>
+              <span style="line-height: 40px;margin-left:20px">{{ digitUppercase(formData.OriginalPrice) }}</span>
+            </el-form-item>
+          </div>
+        </div>
+      </section>
+
+      <section class="section">
+        <el-form-item label="付款方式说明" prop="PayRemark">
+          <el-input type="textarea" v-model="formData.PayRemark" placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)" style="width: 80%"></el-input>
+          <p>说明模板:甲方自合同生效日起的十日之内一次性支付一年服务费,乙方收款后为甲方开具合法有效的增值税发票。</p>
+        </el-form-item>
+        <el-form-item label="实际使用方" prop="trueUseName" class="border-top">
+          <el-select v-model="formData.trueUseName" filterable remote placeholder="关键词搜索" ref="trueUseNameRef"
+          :remote-method="customeSearch" @visible-change="handleSelectTrueUseName" style="width: 500px">
+            <el-option v-for="item in searchList" :key="item" :label="item" :value="item"> </el-option>
+          </el-select>
+        </el-form-item>
+      </section>
+
+      <section class="section" v-if="relationContractData">
+        <h2 class="section-title">合同信息</h2>
+        <div class="section-container">
+          <div class="flex border-top" style="padding-top: 30px">
+            <el-form-item disabled label="合同编号" style="width: 50%">
+              <span>{{ relationContractData.ContractCode }}</span>
+            </el-form-item>
+            <el-form-item disabled label="合同归属" style="width: 50%">
+              <span>{{ relationContractData.ProductId === 1 ? "ficc" : "权益" }}</span>
+            </el-form-item>
+          </div>
+          <el-form-item disabled label="合同类型" class="border-top">
+            <el-radio-group v-model="relationContractData.ContractType">
+              <div style="display: flex">
+                <div style="margin-right: 10px">
+                  <el-radio label="新签合同" disabled>新签合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>没有正式转试用记录的客户,在申请转正时提交的合同</template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right: 10px">
+                  <el-radio label="续约合同" disabled>续约合同</el-radio>
+                  <el-tooltip effect="dark" style="cursor: pointer;width:20px;">
+                    <template #content>
+                      1、有正式转试用记录的客户,在申请转正时提交的合同<br>
+										  2、所有客户在续约申请时提交的合同
+                    </template>
+                    <el-icon :size="16" style="margin-left:-20px"><InfoFilled /></el-icon>
+                  </el-tooltip>
+                </div>
+                <div style="margin-right: 10px" v-if="RoleType !== 'rai_seller'">
+                  <el-radio label="补充协议" disabled>补充协议</el-radio>
+                </div>
+              </div>
+            </el-radio-group>
+          </el-form-item>
+          <div class="flex border-top" v-if="relationContractData.timeRange">
+            <el-form-item disabled label="合同期限" style="width: 50%">
+              <el-date-picker disabled v-model="relationContractData.timeRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
+            </el-form-item>
+            <span style="line-height: 40px">{{ formateYear(relationContractData.timeRange) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item disabled label="合同金额" style="width: 50%">
+              <el-input disabled :value="formatPrice(relationContractData.OriginalPrice)" placeholder="请输入合同金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(relationContractData.OriginalPrice) }}</span>
+          </div>
+
+          <div class="flex border-top">
+            <el-form-item disabled label="优惠后金额" style="width: 50%">
+              <el-input disabled :value="formatPrice(relationContractData.Price)" placeholder="请输入优惠后金额" style="width: 220px"></el-input>
+            </el-form-item>
+            <span style="line-height: 40px">{{ digitUppercase(relationContractData.Price) }}</span>
+          </div>
+
+          <el-form-item label="付款方式说明" disabled class="border-top">
+            <el-input
+              type="textarea"
+              disabled
+              v-model="relationContractData.PayRemark"
+              placeholder="请输入付款方式说明(请参考以下说明模板填写,请勿填写现金/转账等支付形式)"
+              style="width: 80%"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="付款方" disabled class="border-top">
+            <el-input
+              type="textarea"
+              disabled
+              v-model="relationContractData.PayChannel"
+              placeholder="代付,请填写代付的券商名称或期货公司名称;非代付,请填写无。(请勿填写现金/转账等支付形式)"
+              style="width: 80%"
+            ></el-input>
+          </el-form-item>
+        </div>
+      </section>
+
+      <section class="section" v-if="relationContractData">
+        <h2 class="section-title">服务内容</h2>
+          <div class="section-container">
+            <!-- ficc 服务内容表格 -->
+            <FiccServiceTable
+              :canEdit="false"
+              :serviceData="ficcServiceData"
+              :hasSercive="relationContractData.Service"
+              @handleShowService="handleShowService"
+              v-if="relationContractData.ProductId === 1 && ficcServiceData"
+            ></FiccServiceTable>
+
+            <!-- 权益 服务内容表格 -->
+            <QyServiceTable
+              :canEdit="false"
+              :serviceData="qyServiceData"
+              :hasSercive="relationContractData.Service"
+              @handleShowService="handleShowService"
+              v-if="relationContractData.ProductId === 2 && qyServiceData"
+            ></QyServiceTable>
+          </div>
+          <p style="margin-top: 30px; margin-bottom: 20px">补充内容(eg额外赠送、路演次数规定)</p>
+          <el-radio :model-value="relationContractData.Remark?'1':'2'" label="2" disabled>无</el-radio>
+          <el-radio :model-value="relationContractData.Remark?'1':'2'" label="1" disabled>有</el-radio>
+          <el-input v-if="relationContractData.Remark" disabled type="textarea" v-model="relationContractData.Remark" rows="5" placeholder="请输入内容" style="margin: 20px 0; display: block; box-sizing: border-box"></el-input>
+      </section>
+
+      <section class="section">
+        <h2 class="section-title">审批备注</h2>
+        <div class="section-container">
+          <el-form-item label="备注" prop="sellerRemark" class="border-top">
+            <el-input type="textarea" v-model="formData.sellerRemark" placeholder="请输入备注(仅供审批人查看,不在生成合同中展示)" style="width: 80%"></el-input>
+          </el-form-item>
+        </div>
+      </section>
+    </el-form>
+    <div class="right-wrap">
+      <div style="display: flex; justify-content: space-between">
+        <el-button type="primary" plain style="width: 30%;min-width:70px;margin-bottom:10px" @click="handleSubmit('存草稿')" size="large">存草稿</el-button>
+        <el-button type="primary" style="width: 30%;margin-left:3%;min-width:70px;margin-bottom:10px" @click="handleSubmit('预览')" size="large">预览</el-button>
+        <el-button type="primary" style="width: 30%;margin-left:3%;min-width:70px;margin-bottom:10px" @click="handleSubmit('提交')" size="large">提交</el-button>
+      </div>
+      <div class="timeline-wrap">
+        <el-timeline>
+          <el-timeline-item color="#409EFF" v-for="item in operationList" :key="item.Id" placement="top" :timestamp="item.CreateTimeStr">
+            {{item.OpUserName}}{{ item.Remark }}
+          </el-timeline-item>
+        </el-timeline>
+      </div>
+    </div>
+    <!-- 查看报价单弹窗 -->
+    <el-dialog v-dialogDrag v-model="serviceShow" width="60%" class="self-dialog-c" :modal-append-to-body="false" @close="serviceShow=false" :show-close="false">
+      <h2 class="title" style="text-align: center; color: #000">{{ RoleType == 'ficc_seller'? serviceCon.Title : serviceCon.showTitle }}</h2>
+      <img class="img" style="width: 100%; display: block; margin: 20px auto" 
+      :src="RoleType == 'ficc_seller'? serviceCon.Value : serviceCon.showValue" />
+      <div style="text-align: center; margin-bottom: 30px">
+        <el-button type="primary" @click="serviceShow=false" size="large">知道了</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 选择合同弹窗 -->
+    <el-dialog v-dialogDrag :title="`搜索到${formData.trueUseName}下合同`" :append-to-body="true" v-model="showContractList" width="50%" center
+    @close="closeTrueUseNameDia">
+      <el-table :data="contractList" border height="60vh">
+        <el-table-column align="center" width="50">
+          <template #default="scope">
+            <el-radio v-model="formData.RelationContractId" :label="scope.row.ContractId"><span></span></el-radio>
+          </template>
+        </el-table-column>
+        <el-table-column label="合同编号" prop="ContractCode" align="center"></el-table-column>
+        <el-table-column label="销售" prop="SellerName" align="center" width="80"></el-table-column>
+        <el-table-column label="合同类型" prop="ContractType" align="center" width="80"></el-table-column>
+        <el-table-column label="合同有效期" prop="ContractType" align="center" width="180">
+          <template #default="scope">{{ formatTime(scope.row.StartDateStr) }}~{{ formatTime(scope.row.EndDateStr) }}</template>
+        </el-table-column>
+        <el-table-column key="合同金额" align="center" prop="Price" label="合同金额" width="100"></el-table-column>
+        <el-table-column key="合同状态" align="center" prop="Status" label="合同状态" width="80"></el-table-column>
+        <el-table-column key="签回时间" align="center" prop="CheckBackFileTimeStr" label="签回时间" width="160">
+          <template #default="scope">{{ formatTime(scope.row.CheckBackFileTimeStr) }}</template>
+        </el-table-column>
+      </el-table>
+      <div style="text-align: center; margin: 30px 0">
+        <el-button type="primary" @click="handleRelation" size="large">确定关联</el-button>
+        <el-button type="primary" plain @click="showContractList = false" size="large">取消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<style>
+.contractdetail-dc .self-dialog-c .el-dialog__header {
+  background-color: #fff;
+  padding: 0;
+}
+.contractdetail-dc .self-dialog-c {
+  width: auto;
+  max-width: 60%;
+}
+.contractdetail-dc .el-timeline-item__tail {
+  border-left: 2px solid #409eff;
+}
+</style>
+<style lang="scss" scoped>
+.contractdetail-dc{
+    min-height: calc(100vh - 250px);
+    position: relative;
+    font-size: 16px;
+    color: #000;
+}
+.flex {
+  display: flex;
+}
+.right-wrap {
+  margin-left: 20px;
+  flex: 1;
+  .timeline-wrap {
+    margin-top: 20px;
+    background-color: #fff;
+    border: 1px solid #aab4cc;
+    padding: 20px;
+    border-radius: 4px;
+    text-align: left;
+    height: calc(100% - 120px);
+    max-height: 1130px;
+    overflow-y: auto;
+  }
+}
+.section {
+  background-color: #fff;
+  border: 1px solid #aab4cc;
+  border-radius: 4px;
+  padding: 20px 30px;
+  margin-bottom: 20px;
+  .section-title {
+    margin-bottom: 30px;
+  }
+  .border-top {
+    padding-top: 30px;
+    border-top: 1px solid #dcdfe6;
+  }
+}
+</style>