Karsa пре 1 година
родитељ
комит
909ff1d4e7

+ 2 - 0
package.json

@@ -17,6 +17,8 @@
     "element-plus": "2.4.4",
     "jquery": "^3.7.1",
     "js-md5": "^0.8.3",
+    "highcharts": "11.2.0",
+    "moment": "^2.30.1",
     "pinia": "^2.1.7",
     "vue": "^3.4.19",
     "vue-router": "^4.3.0",

+ 14 - 0
pnpm-lock.yaml

@@ -19,6 +19,12 @@ dependencies:
   js-md5:
     specifier: ^0.8.3
     version: 0.8.3
+  highcharts:
+    specifier: 11.2.0
+    version: 11.2.0
+  moment:
+    specifier: ^2.30.1
+    version: 2.30.1
   pinia:
     specifier: ^2.1.7
     version: 2.1.7(vue@3.4.20)
@@ -915,6 +921,10 @@ packages:
     engines: {node: '>=4'}
     dev: true
 
+  /highcharts@11.2.0:
+    resolution: {integrity: sha512-9i650YK7ZBA1Mgtr3avMkLVCAI45RQvYnwi+eHsdFSaBGuQN6BHoa4j4lMkSJLv0V4LISTK1z7J7G82Lzd7zwg==}
+    dev: false
+
   /immutable@4.3.5:
     resolution: {integrity: sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==}
     dev: true
@@ -1007,6 +1017,10 @@ packages:
       mime-db: 1.52.0
     dev: false
 
+  /moment@2.30.1:
+    resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+    dev: false
+
   /ms@2.1.2:
     resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
     dev: true

+ 81 - 0
src/common/js/util.js

@@ -0,0 +1,81 @@
+var SIGN_REGEXP = /([yMdhsm])(\1*)/g;
+var DEFAULT_PATTERN = 'yyyy-MM-dd';
+
+function padding(s, len) {
+    var len = len - (s + '').length;
+    for (var i = 0; i < len; i++) { s = '0' + s; }
+    return s;
+};
+
+export function filterMoney(value, num = 0) {
+    num = num > 0 && num <= 20 ? num : 0;
+    value = parseFloat((value + "").replace(/[^\d\.-]/g, ""))+ ""; //将金额转成比如 123.45的字符串
+    var valueArr = value.split(".")[0].split("").reverse() //将字符串的数变成数组
+    let valueString = "";
+    for (let i = 0; i < valueArr.length; i++) {
+        valueString += valueArr[i] + ((i + 1) % 3 == 0 && (i + 1) != valueArr.length ? "," : ""); //循环 取数值并在每三位加个','
+    }
+    const money = valueString.split("").reverse().join(""); //拼接上小数位
+    return money
+}
+
+export default {
+    getQueryStringByName: function (name) {
+        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
+        var r = window.location.search.substr(1).match(reg);
+        var context = "";
+        if (r != null)
+            context = r[2];
+        reg = null;
+        r = null;
+        return context == null || context == "" || context == "undefined" ? "" : context;
+    },
+    //时间撮格式化
+    formatDatee(time){
+        let date = new Date(time), //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+            Y = date.getFullYear() + '-',
+            M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-',
+            D = date.getDate() < 10 ? '0'+ date.getDate() + ' ' : date.getDate() + ' ',
+            h = date.getHours() + ':',
+            m = date.getMinutes() < 10 ? '0'+ date.getMinutes() + ':' : date.getMinutes() + ':',
+            s = date.getSeconds() < 10 ? '0'+ date.getSeconds() : date.getSeconds();
+        return Y + M + D + h + m + s;
+    },
+    formatDate: {
+        format: function (date, pattern) {
+            pattern = pattern || DEFAULT_PATTERN;
+            return pattern.replace(SIGN_REGEXP, function ($0) {
+                switch ($0.charAt(0)) {
+                    case 'y': return padding(date.getFullYear(), $0.length);
+                    case 'M': return padding(date.getMonth() + 1, $0.length);
+                    case 'd': return padding(date.getDate(), $0.length);
+                    case 'w': return date.getDay() + 1;
+                    case 'h': return padding(date.getHours(), $0.length);
+                    case 'm': return padding(date.getMinutes(), $0.length);
+                    case 's': return padding(date.getSeconds(), $0.length);
+                }
+            });
+        },
+        parse: function (dateString, pattern) {
+            var matchs1 = pattern.match(SIGN_REGEXP);
+            var matchs2 = dateString.match(/(\d)+/g);
+            if (matchs1.length == matchs2.length) {
+                var _date = new Date(1970, 0, 1);
+                for (var i = 0; i < matchs1.length; i++) {
+                    var _int = parseInt(matchs2[i]);
+                    var sign = matchs1[i];
+                    switch (sign.charAt(0)) {
+                        case 'y': _date.setFullYear(_int); break;
+                        case 'M': _date.setMonth(_int - 1); break;
+                        case 'd': _date.setDate(_int); break;
+                        case 'h': _date.setHours(_int); break;
+                        case 'm': _date.setMinutes(_int); break;
+                        case 's': _date.setSeconds(_int); break;
+                    }
+                }
+                return _date;
+            }
+            return null;
+        }
+    },
+};

+ 0 - 2
src/hooks/login/use-login.js

@@ -87,11 +87,9 @@ export function useLoginSuccess(res) {
   setUserInfo(res.Data);
 
   getOtherRolePath('myCalendar').then(path => {
-    nextTick(() => {
       // path&&router.push({ path });
       //先跳到主面板
       path&&router.push({ path:'/dashboard' });
-    })
   });
   
 }

+ 6 - 0
src/router/index.js

@@ -35,6 +35,12 @@ const routes = [
       title: "404"
     },
   },
+  {
+    path: '',
+    redirect: {
+      path: '/dashboard'
+    },
+  },
   {
     path: '/:pathMatch(.*)',
     redirect: {

+ 439 - 0
src/router/modules/customRoutes.js

@@ -0,0 +1,439 @@
+import Home from '@/layouts/index.vue'
+
+export default [
+  {
+    path: "/",
+    component: Home,
+    name: "customHome",
+    meta: {
+      title: '客户管理'
+    },
+    hidden: true,
+    icon_path: require("@/assets/img/home/custom_ico.png"),
+    children: [
+      {
+        path: "customSearch",
+        component: () => import("@/views/custom_manage/custom/customSearch.vue"),
+        name: "customSearch",
+        hidden: false,
+        meta: {
+          title: "客户检索",
+          keepAlive: false,
+        },
+      },
+      {
+        path: "customList",
+        component: () => import("@/views/custom_manage/custom/customList.vue"),
+        name: "customList",
+        hidden: false,
+        meta: {
+          title: "客户列表",
+          keepAlive: false,
+        },
+      },
+      // {
+      //   path: "customShareList",
+      //   component: () => import("@/views/custom_manage/customList/customShareList.vue"),
+      //   name: "正式客户共享",
+      //   hidden: false,
+      // },
+      // {
+      //   path: 'customCityList',
+      //   component: () => import('@/views/custom_manage/customList/customCityList.vue'),
+      //   name: '查看同城客户',
+      //   hidden: false,
+      //   meta: {
+      //       pathFrom: 'customShareList',
+      //       pathName: '正式客户共享'
+      //   }
+      // },
+      // {
+      //   path: "customAllList",
+      //   component: () => import("@/views/custom_manage/customList/customAllList.vue"),
+      //   name: "全量客户列表",
+      //   hidden: false,
+      // },
+      // {
+      //   path: "customListEn",
+      //   component: () => import("@/views/custom_manage/customList/customListEn.vue"),
+      //   name: "英文客户列表",
+      //   hidden: false,
+      // },
+      // {
+      //   path: "overseasCustomList",
+      //   component: () => import("@/views/custom_manage/overseasList/overseasCustomList.vue"),
+      //   name: "海外客户列表",
+      //   hidden: false,
+      // },
+      // {
+      //   path: "trialContactListEn",
+      //   component: () => import("@/views/custom_manage/customList/limitContactListEn.vue"),
+      //   name: "临时权限列表",
+      //   hidden: false,
+      // },
+      // {
+      //   path: "freezeContactListEn",
+      //   component: () => import("@/views/custom_manage/customList/limitContactListEn.vue"),
+      //   name: "终止权限列表",
+      //   hidden: false,
+      // },
+      // {
+      //   path: "pickList",
+      //   name: "领取列表",
+      //   component: () => import("@/views/custom_manage/pickList.vue"),
+      //   hidden: false,
+      //   meta: {
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "addCustom",
+      //   name: "新增客户",
+      //   component: () => import("@/views/custom_manage/customList/addCustom.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customList",
+      //     pathName: "客户列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "editCustom",
+      //   name: "编辑客户",
+      //   component: () => import("@/views/custom_manage/customList/editCustom.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customList",
+      //     pathName: "客户列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "addCustomEn",
+      //   component: () => import("@/views/custom_manage/customList/editCustomEn.vue"),
+      //   name: "新增英文客户",
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customListEn",
+      //     pathName: "英文客户列表",
+      //   },
+      // },
+      // {
+      //   path: "editCustomEn",
+      //   component: () => import("@/views/custom_manage/customList/editCustomEn.vue"),
+      //   name: "编辑英文客户",
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customListEn",
+      //     pathName: "英文客户列表",
+      //   },
+      // },
+      // {
+      //   path: "customDetail",
+      //   name: "客户详情",
+      //   component: () => import("@/views/custom_manage/customList/customDetail.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customList",
+      //     pathName: "客户列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "detailCustomEn",
+      //   component: () => import("@/views/custom_manage/customList/editCustomEn.vue"),
+      //   name: "英文客户详情",
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customListEn",
+      //     pathName: "英文客户列表",
+      //   },
+      // },
+      // {
+      //   path: "pickCustom",
+      //   name: "领取客户",
+      //   component: () => import("@/views/custom_manage/customList/pickCustom.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "pickList",
+      //     pathName: "领取列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // // 服务更新差分为 续约申请和补充协议其中 权益无补充协议
+      // {
+      //   path: "updateCustom",
+      //   name: "续约申请",
+      //   component: () => import("@/views/custom_manage/customList/updateServe.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customList",
+      //     pathName: "客户列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "addAgreement",
+      //   name: "补充协议",
+      //   component: () => import("@/views/custom_manage/customList/updateServe.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customList",
+      //     pathName: "客户列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "turnCustom",
+      //   name: "申请转正",
+      //   component: () => import("@/views/custom_manage/customList/applyTurn.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "customList",
+      //     pathName: "客户列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "approvalUpdate",
+      //   name: "续约审批",
+      //   component: () => import("@/views/custom_manage/approvalUpdate.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "approvalList",
+      //     pathName: "审批列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "approvalTurn",
+      //   name: "转正审批",
+      //   component: () => import("@/views/custom_manage/approvalTurn.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "approvalList",
+      //     pathName: "审批列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "potentialList",
+      //   component: () => import("@/views/custom_manage/potentialList.vue"),
+      //   name: "潜在用户",
+      //   hidden: false,
+      //   meta: {
+      //     keepAlive: false,
+      //   },
+      // },
+      {
+        path: "trialApplication",
+        component: () => import("@/views/custom_manage/officalTrial/trialApplication.vue"),
+        name: "trialApplication",
+        hidden: false,
+        meta: {
+          keepAlive: false,
+          title: '官网试用申请'
+        },
+      },
+      // {
+      //   path: "userFiccApplyList",
+      //   name: "用户申请列表",
+      //   component: () => import("@/views/ficc_manage/userApplication.vue"),
+      //   hidden: false,
+      // },
+      // {
+      //   path: "regionCustomerList",
+      //   component: () => import("@/views/custom_manage/customList/regionCustom.vue"),
+      //   name: "客户区域统计",
+      //   hidden: false,
+      //   meta: {
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "regionCustomerDetail",
+      //   component: () => import("@/views/custom_manage/customList/regionCustomDetail.vue"),
+      //   name: "正式客户列表",
+      //   hidden: false,
+      //   meta: {
+      //     pathFrom: "regionCustomerList",
+      //     pathName: "客户区域统计",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "contactsList",
+      //   component: () => import("@/views/custom_manage/contacts/contactsList.vue"),
+      //   name: "联系人列表",
+      //   hidden: false,
+      //   meta: {
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "mutualList",
+      //   name: "互动列表",
+      //   component: () => import("@/views/custom_manage/contacts/mutualList.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "contactsList",
+      //     pathName: "联系人列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "organizationList",
+      //   name: "机构互动列表",
+      //   component: () => import("@/views/custom_manage/contacts/organizationList.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "contactsList",
+      //     pathName: "联系人列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "wholeOrganization",
+      //   name: "全机构互动列表",
+      //   component: () => import("@/views/custom_manage/contacts/wholeOrganization.vue"),
+      //   hidden: true,
+      //   meta: {
+      //     pathFrom: "contactsList",
+      //     pathName: "联系人列表",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "customerlistmatch",
+      //   name: "客户名单匹配",
+      //   component: () => import("@/views/custom_manage/listMatch.vue"),
+      //   hidden: false,
+      // },
+      // {
+      //   path: "etaTrialList",
+      //   component: () => import("@/views/custom_manage/etaTrialList/etaTrialList.vue"),
+      //   name: "ETA试用",
+      //   hidden: false,
+      //   meta: {
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "etaApprovalList",
+      //   component: () => import("@/views/custom_manage/etaTrialList/etaTrialList.vue"),
+      //   name: "审批列表",
+      //   hidden: false,
+      //   meta: {
+      //     pathFrom: "etaTrialList",
+      //     pathName: "ETA试用",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "etaAddApproval",
+      //   component: () => import("@/views/custom_manage/etaTrialList/addApproval.vue"),
+      //   name: "新增申请",
+      //   hidden: false,
+      //   meta: {
+      //     pathFrom: "etaTrialList",
+      //     pathName: "ETA试用",
+      //     keepAlive: false,
+      //   },
+      // },
+      // {
+      //   path: "questionnaireSurvey",
+      //   component: () => import("@/views/custom_manage/etaTrialList/questionnaireSurvey.vue"),
+      //   name: "问卷调研",
+      //   hidden: false,
+      //   meta: {
+      //     pathFrom: "etaTrialList",
+      //     pathName: "ETA试用",
+      //   },
+      // },
+      // {
+      //   path: "questionnaireOption",
+      //   component: () => import("@/views/custom_manage/etaTrialList/questionnaireOption.vue"),
+      //   name: "问卷配置",
+      //   hidden: false,
+      //   meta: {
+      //     pathFrom: "etaTrialList",
+      //     pathName: "ETA试用",
+      //   },
+      // },
+      // {
+      //   path: "textQuestionDetail",
+      //   component: () => import("@/views/custom_manage/etaTrialList/textQuestionDetail.vue"),
+      //   name: "统计详情",
+      //   hidden: false,
+      //   meta: {
+      //     pathFrom: "etaTrialList",
+      //     pathName: "ETA试用",
+      //   },
+      // },
+      // {
+      //   path: "customerContractStatistics",
+      //   component: () => import("@/views/custom_manage/contractStatistics.vue"),
+      //   name: "开票到款统计",
+      //   hidden: false,
+      // },
+      // {
+			// 	path: "ficcApplyList",
+			// 	name: 'ficc申请记录',
+			// 	component: () => import('@/views/ficc_manage/apply/applyList.vue'),
+			// 	hidden: false,
+			// },
+      // {
+      //   path:'businessETAList',
+      //   name:"商家管理",
+      //   component: () => import('@/views/business_ETA_manage/businessList.vue'),
+			// 	hidden: false,
+      // },
+      // {
+      //   path:'addETABusiness',
+      //   name:"新增商家",
+      //   component: () => import('@/views/business_ETA_manage/addBusiness.vue'),
+			// 	hidden: false,
+      //   meta:{
+      //     pathFrom: "businessETAList",
+      //     pathName: "商家管理",
+      //   }
+      // },
+      // {
+      //   path:'editETABusiness',
+      //   name:"编辑商家",
+      //   component: () => import('@/views/business_ETA_manage/businessEdit.vue'),
+			// 	hidden: false,
+      //   meta:{
+      //     pathFrom: "businessETAList",
+      //     pathName: "商家管理",
+      //   }
+      // },
+      // {
+      //   path:'businessETADetail',
+      //   name:"商家详情",
+      //   component: () => import('@/views/business_ETA_manage/businessDetail.vue'),
+			// 	hidden: false,
+      //   meta:{
+      //     pathFrom: "businessETAList",
+      //     pathName: "商家管理",
+      //   }
+      // },
+      // {
+      //   path:'businessETAAuth',
+      //   name:"商家权限",
+      //   component: () => import('@/views/business_ETA_manage/businessAuth.vue'),
+      //   hidden: false,
+      //   meta:{
+      //     pathFrom: "businessETAList",
+      //     pathName: "商家管理",
+      //   }
+      // },
+      // {
+      //   path:'overseasCustomRoadshow',
+      //   name:"海外客户路演",
+      //   component: () => import('@/views/custom_manage/overseasList/overseasCustomRoadshow.vue'),
+      //   hidden: false
+      // }
+    ],
+  },
+];

+ 1 - 1
src/styles/global.scss

@@ -144,7 +144,7 @@ iframe {
   color: #666 !important;
 }
 .el-form-item__label {
-  font-size: 16px;
+  font-size: 15px;
 }
 .el-collapse-item__header {
   border: none;

+ 145 - 3
src/views/Resetpassword.vue

@@ -1,10 +1,152 @@
 <script setup>
-import { ref } from 'vue'
+import { reactive, ref } from 'vue'
+import { checkPassWord } from '@/utils/commonOptions';
+import md5 from "@/utils/md5.js";
+import { modifyPwd } from "@/api/api.js";
+import { ElMessage } from 'element-plus'
+import { useRouter } from 'vue-router'
+
+const $router = useRouter()
+
+
+const addForm = reactive({
+  OldPwd: "",
+  NewPwd: "",
+  twoNewPwd: "",
+})
+const rules = {
+  OldPwd: [
+    {
+      required: true,
+      message: "请输入原密码",
+      trigger: "blur",
+    },
+  ],
+  NewPwd: [
+      {
+        validator:(rule,value,callback)=>{
+            if(!checkPassWord(value)){
+                callback(new Error('密码要求8位及以上,包含数字、大写字母、小写字母、特殊字符中的三个类型'))
+            }else{
+                callback()
+            }
+        }
+      },
+    {
+      required: true,
+      message: "请输入确认密码",
+      trigger: "blur",
+    },
+  ],
+  twoNewPwd: [
+    {
+      required: true,
+      message: "请输入确认密码",
+      trigger: "blur",
+    },
+  ],
+}
+
+const formRef = ref(null)
+async function addSubmit() {
+  await formRef.value.validate()
+
+  if (addForm.NewPwd != addForm.twoNewPwd) {
+    ElMessage.warning("新密码两次输入不一致,请核对!");
+    return false;
+  }
+
+  const res = await modifyPwd({
+    OldPwd: md5.hex_md5(addForm.OldPwd),
+    NewPwd: md5.hex_md5(addForm.NewPwd),
+  })
+  if (res.Ret == 200) {
+    ElMessage.success("修改密码成功,请重新登录!");
+    setTimeout(function () {
+      localStorage.setItem("auth", "");
+      localStorage.setItem("userName", "");
+      localStorage.setItem("Role", "");
+      localStorage.setItem("RoleType", "");
+      localStorage.setItem("AdminId", "");
+      localStorage.setItem("AdminName", "");
+      localStorage.setItem("RoleIdentity", "");
+      localStorage.setItem("ManageType", "");
+      $router.push({ path: "/login" });
+    }, 1000);
+  }
+}
+
+function historyBack() {
+  $router.go(-1)
+}
 
 </script>
 <template>
-  <div>修改密码</div>
+  <el-card class="box-card">
+    <template #header>
+      <div class="clearfix">
+        <b>修改密码</b>
+      </div>
+    </template>
+
+    <el-form
+      :model="addForm"
+      :rules="rules"
+      ref="formRef"
+      label-width="120px"
+      style="width: 500px"
+    >
+      <el-form-item label="原密码" prop="OldPwd">
+        <el-input
+          v-model="addForm.OldPwd"
+          type="password"
+          clearable
+          maxlength="20"
+          placeholder="请输入不超过20个字符"
+          show-password
+        />
+      </el-form-item>
+      <el-form-item label="新密码" prop="NewPwd">
+        <el-input
+          type="password"
+          v-model="addForm.NewPwd"
+          placeholder="请输入长度不超过20个字符"
+          maxlength="20"
+          show-password
+          clearable
+        >
+        </el-input>
+      </el-form-item>
+      <el-form-item label="确认新密码" prop="twoNewPwd">
+        <el-input
+          type="password"
+          v-model="addForm.twoNewPwd"
+          placeholder="请输入长度不超过20个字符"
+          maxlength="20"
+          show-password
+          clearable
+        >
+        </el-input>
+      </el-form-item>
+      
+      <el-form-item style="text-align: center;">
+        <el-button type="primary"  @click="addSubmit"
+          >确定</el-button
+        >
+        <el-button
+          type="primary"
+          plain
+          @click="historyBack"
+          >返回</el-button
+        >
+      </el-form-item>
+    </el-form>
+  </el-card>
 </template>
 <style scoped lang="scss">
-
+.box-card {
+    .el-form-item{
+      margin-bottom: 40px;
+    }
+}
 </style>

+ 10 - 0
src/views/custom_manage/custom/customList.vue

@@ -0,0 +1,10 @@
+<script setup>
+import { ref } from 'vue'
+
+</script>
+<template>
+  <div></div>
+</template>
+<style scoped lang="scss">
+
+</style>

+ 1110 - 0
src/views/custom_manage/custom/customSearch.vue

@@ -0,0 +1,1110 @@
+<script setup>
+import { ref,computed,reactive,onBeforeMount } from "vue";
+import { customInterence } from '@/api/api.js'
+import { useRouter } from 'vue-router'
+import { Search,MoreFilled } from '@element-plus/icons-vue'
+import { ElMessageBox,ElMessage } from 'element-plus'
+import mPage from '@/components/mPage.vue'
+
+const $router = useRouter()
+
+const Role = computed(() => {
+  let role = localStorage.getItem('Role') || '';
+  return role;
+})
+const RaiSellerRole = computed(() => {
+  return ['rai_seller','rai_admin','admin'].includes(Role)
+})
+const RoleType = computed(() => {
+  let type = localStorage.getItem('RoleType') || '';
+  return type;
+})
+const RoleIdentity = computed(() => {
+  let role = localStorage.getItem('RoleIdentity') || '';
+  return role;
+})
+const SellerAdminId = computed(() => {
+  let type = localStorage.getItem('AdminId') || '';
+  return type;
+})
+
+
+/* 获取表格数据 */
+const search_txt = ref('')
+const isShowloadding = ref(false)
+const noResult = ref(false)
+const	pageinfo = reactive({	// 分页信息
+  total: 0,
+  page_no: 1,
+  page_size: 10
+})
+const tableData = ref([])
+function getTableData() {
+  isShowloadding.value = true;
+  customInterence.searchList({
+    KeyWord:search_txt.value,
+    PageSize:pageinfo.page_size,
+    CurrentIndex:pageinfo.page_no
+  }).then(res => {
+    if(res.Ret === 200) {
+      tableData.value = res.Data?res.Data.List:[];
+      pageinfo.total=res.Data && res.Data.Paging ? res.Data.Paging.Totals : 0
+      tableData.value.forEach(item => {
+        item.ApproveStatus = item.ApproveStatus=='待审批'?'待审批':''
+      })
+      noResult.value = res.Data.List.length ? false : true;
+      isShowloadding.value = false
+    }else {
+      tableData.value = [];
+      noResult.value = true;
+      setTimeout(()=> {
+        isShowloadding.value = false;
+      },100)
+    }
+  })	
+}
+
+// 页码改变事件
+function handleCurrentChange(page){
+  pageinfo.page_no=page
+  getTableData()
+}
+
+
+// 处理状态的数据
+function transformedArray(row){
+  return [
+    {
+      SigningStatus: row.CompanyStatusButton.FiccSigningStatus,
+      Status: row.CompanyStatusButton.FiccStatus
+    },
+    {
+      SigningStatus: row.CompanyStatusButton.RaiSigningStatus,
+      Status: row.CompanyStatusButton.RaiStatus,
+    }
+  ];
+}
+
+//处理时长显示
+function formateDuration(time,status){
+  let timearr=time.split('/')
+  let statusarr=status.split('/').map((item,index)=>{
+    if(item=='冻结'){
+      return `解冻天数:${timearr[index]?timearr[index]:'--'}`
+    }else if(item=='流失'){
+      return `流失天数:${timearr[index]?timearr[index]:'--'}`
+    }else if(item=='永续'){
+      return '永续'
+    }else{
+      return `剩余天数:${timearr[index]?timearr[index]:'--'}`
+    }
+  })
+
+  return statusarr.join('/')
+}	
+
+
+const btnCommandList = {
+  BtnAddAgreement: '补充协议',
+  BtnApplyReceive: '申请领取',
+  BtnDelay: '申请延期',
+  BtnDelete: '删除',
+  BtnDetail: '',
+  BtnEdit: '编辑',
+  BtnFreeze: '冻结',
+  BtnModifySeller: '修改销售',
+  BtnReceive: '领取客户',
+  BtnReceiveOther: '领取',
+  BtnSuspend: '启用/暂停',
+  BtnThaw: '申请解冻',
+  BtnTryOut: '增开试用',
+  BtnTurnPositive: '申请转正',
+  BtnUpdate: '续约申请',
+  BtnView: '查看权限',
+  BtnRemarkView: '备注',
+  IsResearchShow:'研选详情'
+}
+// 按钮列表
+function btnList(btnItem,part){
+  const allBtnList=[]
+  for (const key in btnItem) {
+    btnItem[key]&&key!=='BtnClose' && allBtnList.push(key)
+  }
+  if(part==='front'){
+    // 返回前三个按钮
+    return allBtnList.slice(0,3)
+  }else{
+    // 返回三个后按钮
+    return allBtnList.slice(3)
+  }
+}
+// 用于返回按钮名称
+function	btnName(btnItem,isSuspend){
+  if(btnItem!=='BtnSuspend') return btnCommandList[btnItem]
+  return isSuspend===1?'启用':'暂停'
+}
+
+/* 查看详情 */
+function goDetail(item) {
+  if(!item.BtnItem.BtnView) return
+  $router.push({
+    path:'/customDetail',
+    query: {
+      id:item.CompanyId
+    }
+  })
+}
+
+/* 操作 */
+function itemclickHandle(query) {
+  if(query.type == '申请转正') {
+    applyTurn(query.data)
+  }else if(query.type == '申请延期' || query.type == '申请解冻') {
+    applyHandle(query.type,query.data)
+  }else if(query.type == '申请领取') {
+    if(RaiSellerRole.value && query.data.IsScrounge == 1){
+      ElMessageBox.confirm('此客户存在长期且反复申请试用,但从未签约的情况,确定要领取吗?','申请领取',{
+        type:'warning'
+      }).then(() => {
+        applyHandle('申请领取',query.data)
+      }).catch(() => {});
+    }else{
+      applyHandle('申请领取',query.data)
+    }
+  }else if(query.type == '修改销售') {
+    updateSale(query.data);
+  }else if(query.type == '启用' || query.type == '暂停') {
+    suspendHandle(query.data)
+  }else if(query.type == '冻结') {
+    freezHandle(query.data);
+  }else if(query.type == '领取') {
+    receiveOtherHandle(query.data);
+  }else if(query.type == '增开试用') {
+    addTrialHandle(query.data)
+  }else if(query.type=='编辑'){
+    editHandle(query.data)
+  }else if(query.type=='删除'){
+    delHandle(query.data)
+  }else if(query.type=='查看权限'){
+    lookHandle(query.data)
+  }else if(query.type=='续约申请'){
+    updateHandle(query.data)
+  }else if(query.type=='补充协议'){
+    addAgreement(query.data)
+  }else if(query.type=='领取客户'){
+    if(RaiSellerRole.value && query.data.IsScrounge == 1){
+      ElMessageBox.confirm('此客户存在长期且反复申请试用,但从未签约的情况,确定要领取吗?','领取客户',{
+        type:'warning'
+      }).then(() => {
+        receiveHandle(query.data)
+      }).catch(() => {})
+    }else{
+      receiveHandle(query.data)
+    }
+  }else if(query.type=='备注'){
+    lookRemarkHandle(query.data)
+  }else if(query.type=='研选详情'){
+    researchDetailHandle(query.data)
+  }
+}
+
+
+const completeForm = ref({
+  show:false,
+})//补全信息弹窗
+//获取客户详情判断基本信息是否完整 id 客户id type 1 跨部门 0 不是跨部门
+async function getCustomerDetail(id,type){
+  
+  let res=await customInterence.customDetail({
+    CompanyId:id
+  })
+  if(res.Ret!=200) return
+
+  // 跨部门领取
+  if(type===1){
+    if((res.Data.Item.RegionType!='海外'&&!res.Data.Item.Province&&!res.Data.Item.City)||!res.Data.Item.CreditCode){
+
+      completeForm.value={
+        CompanyId:id,
+        name:res.Data.Item.CompanyName,
+        nameDisable:res.Data.Item.CompanyName!='',
+        Province:res.Data.Item.Province,
+        City:res.Data.Item.City,
+        CityDisable:res.Data.Item.City!='',
+        CreditCode:res.Data.Item.CreditCode,
+        CreditCodeDisable:res.Data.Item.CreditCode!='',
+        RegionType:res.Data.Item.RegionType,
+        
+        flag:true,//是否为跨部门
+        show:true
+      }
+    }else{
+      completeForm.value.show=false
+    }
+  }else{
+    let RoleType=RoleType.value
+    let IndustryId='',Source=';'
+    if(RoleType=='ficc'){
+      IndustryId=res.Data.FiccItem.IndustryId
+      Source=res.Data.FiccItem.Source
+    }else if(RoleType=='权益'){
+      IndustryId=res.Data.RaiItem.IndustryId
+      Source=res.Data.RaiItem.Source
+    }
+    // let IndustryId=res.Data.CreateAuth == 1?res.Data.FiccItem.IndustryId:res.Data.RaiItem.IndustryId
+    // let Source=res.Data.CreateAuth == 1?res.Data.FiccItem.Source:res.Data.RaiItem.Source
+    if((res.Data.Item.RegionType!='海外'&&!res.Data.Item.Province&&!res.Data.Item.City)||!res.Data.Item.CreditCode||!IndustryId||!Source){
+      completeForm.value={
+        nameDisable:res.Data.Item.CompanyName!='',
+        CityDisable:res.Data.Item.City!='',
+        CreditCodeDisable:res.Data.Item.CreditCode!='',
+        IndustryIdDisable:IndustryId!=' ',
+        SourceDisable:Source!='',
+        CompanyId:id,
+        name:res.Data.Item.CompanyName,
+        Province:res.Data.Item.Province,
+        City:res.Data.Item.City,
+        CreditCode:res.Data.Item.CreditCode,
+        IndustryId:IndustryId?IndustryId:'',
+        Source:Source,
+        RegionType:res.Data.Item.RegionType,
+        flag:false,//是否为跨部门
+        show:true
+      }
+    }else{
+      completeForm.value.show=false
+    }
+  }
+
+  return new Promise((resolve,reject)=>{
+    resolve(completeForm.value.show)
+  })
+    
+}
+
+
+/* 申请转正 */
+const contractModel = reactive({
+  show:true,
+  data:null,//客户信息(列表用户数据)
+	type:'',//类型 申请转正、续约申请、补充协议
+})
+async function applyTurn(item) {
+  //判断是否需要补全信息
+  let flag=await getCustomerDetail(item.CompanyId,0) 
+  if(flag) return
+  contractModel.show=true
+  contractModel.data=item
+  contractModel.type='申请转正'
+}
+/* 续约申请操作 */
+async function updateHandle(item) {
+  //判断是否需要补全信息
+  let flag = await getCustomerDetail(item.CompanyId)
+  if(flag) return
+  contractModel.show=true
+  contractModel.data=item
+  contractModel.type='续约申请'
+}
+// 补充协议
+async function addAgreement(item) {
+  //判断是否需要补全信息
+  let flag = await getCustomerDetail(item.CompanyId)
+  if(flag) return
+  contractModel.show=true
+  contractModel.data=item
+  contractModel.type='补充协议'
+}
+
+
+
+/* 申请延期 解冻 领取小弹窗 */
+const isApply = ref(false)//申请弹窗
+const applyForm = ref({})//客户信息
+const applyTit = ref('')
+const isPickLoss = ref(false)//联系人弹窗时记录是否是领取流失客户
+const	isPickSelf = ref(false)//是否为领取自己的流失客户
+const regionType = ref("")
+const isAddContact = ref(false) //添加联系人弹窗
+const addCompanyId = ref('')//新增联系人的公司id
+const diaform = ref({
+  name:'',
+  sex:1,
+  telCode:'86',
+  tel1:'',
+  tel2:'',
+  mail:'',
+  post:'',
+  desiger:'',
+  depart:'',
+  carte:'',
+  Source:'pick_custom'
+})
+async function applyHandle(tit,item) {
+  //判断是否需要补全信息
+  let flag=await getCustomerDetail(item.CompanyId,0)
+  if(flag) return
+  applyTit.value = tit;
+  applyForm.value = item;
+  
+  // 如果是申请领取(即领取自己流失客户)先添加联系人再进行申请操作
+  if(tit=='申请领取'&& (item.SellerId !== SellerAdminId.value)){
+    isPickLoss.value = true;
+    isPickSelf.value = true
+    regionType.value = item.RegionType;
+    addCompanyId.value = item.CompanyId;
+    diaform.value = {
+      name:'',
+      sex:1,
+      telCode:'86',
+      tel1:'',
+      tel2:'',
+      mail:'',
+      post:'',
+      desiger:'',
+      depart:'',
+      carte:'',
+      Source:'pick_custom'
+    },
+    isAddContact.value = true;
+  }else{
+    isApply.value = true;
+  }
+
+  
+}
+/* 领取流失客户 */
+async function receiveHandle(item) {
+  //判断是否需要补全信息
+  let flag = await getCustomerDetail(item.CompanyId,0)
+  if(flag) return
+
+  if(RaiSellerRole.value && item.IsScrounge == 1){
+    // 已经弹过二次确认弹窗 避免再一次的弹窗
+    isPickLoss.value = true;
+    regionType.value = item.RegionType;
+    addCompanyId.value = item.CompanyId;
+    diaform.value.telCode='86'
+    isAddContact.value = true;
+    return 
+  }
+  
+  ElMessageBox.confirm('是否确认领取该客户?','提示',{
+    type:'warning'
+  }).then(() => {
+
+      isPickLoss.value = true;
+      addCompanyId.value = item.CompanyId;
+      regionType.value=item.RegionType
+      diaform.value.telCode='86'
+      isAddContact.value = true;
+  }).catch(() => {});
+}
+
+
+/* 修改销售操作 */
+const isMove = ref(false)//修改销售
+const moveform = ref({
+  companyType:'',
+  companyId:'',//客户id
+  companyName:'',
+  sale:'',//修改的销售
+})
+const moveRule = {
+  sale:[
+    { required: true, message: '所属销售不能为空', trigger: 'blur' },
+  ]
+}
+function updateSale(item) {
+  moveform.value = {
+    companyType:item.CompanyType,
+    companyName:item.CompanyName,
+    companyId:item.CompanyId,
+    sale:''
+  }
+  handleModifysalesArr(item.SellerId)
+  isMove.value = true;
+}
+const salesArr = ref([])//修改销售时可选择的数据
+// 处理修改销售数据 不可以修改到已存在销售
+function handleModifysalesArr(id){
+  const AllSalesArr = _.cloneDeep(modifysalesArrtem.value)
+  salesArr.value=AllSalesArr.map(item=>{
+    if(item.ChildrenList){
+      item.ChildrenList=item.ChildrenList.filter(e=>{
+        if(e.ChildrenList){
+          e.ChildrenList = e.ChildrenList.filter(i=>{return i.AdminId!=id})
+        }
+        return  e.AdminId!=id
+      })
+    }
+    return item
+  })
+}
+const modifysalesArrtem = ref([])//从后台获取的修改销售的所有数据
+/* 获取销售 */
+function getSale() {
+  customInterence.getSale({AllSeller:true}).then(res => {
+    if(res.Ret === 200) {
+      modifysalesArrtem.value = res.Data.List;
+    }
+  })
+}
+getSale();
+
+
+/* 启用/暂停 */
+function suspendHandle(item) {
+  customInterence.Suspend({
+    CompanyId:item.CompanyId
+  }).then(res => {
+    if(res.Ret === 200) {
+      ElMessage.success(res.Msg);
+      item.IsSuspend = item.IsSuspend === 1 ? 0 : 1;
+    }
+  })
+}
+
+
+/* 冻结客户 */
+const isFreezeReason = ref(false)//冻结理由弹窗
+const freezeData = ref({
+  reason:"",//冻结理由
+  CompanyId:'',
+  CompanyType:""
+})
+function freezHandle(item) {
+  isFreezeReason.value = true
+  freezeData.value.CompanyId=item.CompanyId
+  let RoleType=localStorage.getItem('RoleType')
+  freezeData.value.CompanyType=RoleType
+}
+
+
+/* 领取权益/ficc客户 */
+async function receiveOtherHandle(item) {
+  //判断是否需要补全信息
+  let flag=await getCustomerDetail(item.CompanyId,1)
+  if(flag) return
+
+  $router.push({
+    path:'/pickCustom',
+    query:{
+      id:item.CompanyId
+    }
+  })
+}
+
+
+/* 增加试用 */
+const isAddTrial = ref(false)//增加试用弹窗
+const addTryId = ref('')//增开试用的id
+function addTrialHandle(item) {
+  authList.value = [];
+  customInterence.lookauth({
+    CompanyId:item.CompanyId,
+    LookType:1
+  }).then(res => {
+    if(res.Ret === 200) {
+      let auth = [];
+      // res.Data.List 有值为 ficc
+      // res.Data.ListRai 有值为 权益
+      if(res.Data.List) {
+        res.Data.List.forEach(item=> {
+          let obj = {
+            checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
+            isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
+            defaultAuth:item.CheckList,
+            customType:'ficc',
+            ...item,
+          }
+          auth.push(obj)
+        })
+      }else if(res.Data.ListRai) {
+        auth = filterRaiAuth(res.Data.ListRai,auth)
+
+      }
+     
+      authList = auth;
+    }
+  })
+  addTryId.value = item.CompanyId;
+  isAddTrial.value = true;
+}
+function filterRaiAuth(data,auth) {
+     // 权益 RaiMerge 0不管 1合并 2拆分 所传入的数据结构不一样
+    data[0].RaiMerge==1
+      ? data.forEach(item=> { // 合并
+          let obj = {
+            checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
+            isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
+            defaultAuth:item.CheckList,
+            ...item,
+          }
+          auth.push(obj)
+        })
+      : data.forEach(item=> { // 拆分
+          let obj = {
+            defaultAuth:item.CheckList,
+            customType:'权益',
+            ...item,
+          }	
+          // 组合所需的数据格式
+          obj.dataList=[
+            {
+              PermissionTypeName:'',
+              medicine:{
+                value:'医药',
+                isIndeterminate:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==1,
+                isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length == 2,
+                isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==2
+              },
+              consumption:{
+                value:'消费',
+                isIndeterminate:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==1,
+                isCheckAll:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length == 2,
+                isDisabled:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==2
+              },
+              technology:{
+                value:'科技',
+                isIndeterminate:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==1,
+                isCheckAll:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length == 2,
+                isDisabled:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==2
+              },
+              smart:{
+                value:'智造',
+                isIndeterminate:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==1,
+                isCheckAll:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 2,
+                isDisabled:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==2
+              },
+              strategy:{
+                value:'策略'
+              },
+              experts:{
+                value:'专家'
+              },
+              roadshow:{
+                value:'路演服务'
+              },
+              choose:{
+                value:'研选订阅'
+              },
+              points:{
+                value:'研选扣点包'
+              },
+            },
+            {
+              PermissionTypeName:{
+                value:'主观',
+                isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
+                  obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length),
+                isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
+                  obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length == 4,
+                isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
+                  obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length ==4
+              },
+              medicine:{
+                value:obj.Items[0].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[0].ChartPermissionId)
+              },
+              consumption:{
+                value:obj.Items[2].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[2].ChartPermissionId)
+              },
+              technology:{
+                value:obj.Items[4].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[4].ChartPermissionId)
+              },
+              smart:{
+                value:obj.Items[6].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[6].ChartPermissionId)
+              },
+              strategy:{
+                value:obj.Items[8].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
+              },
+              experts:{
+                value:obj.Items[9].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
+              },
+              roadshow:{
+                value:obj.Items[10].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
+              },
+              choose:{
+                value:obj.Items[11].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+              },
+              points:{
+                value:obj.Items[12].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[12].ChartPermissionId)
+              }
+            },
+            {
+              PermissionTypeName:{
+                value:'客观',
+                isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
+                  obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length),
+                isCheckAll:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
+                  obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 4,
+                isDisabled:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
+                  obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==4
+              },
+              medicine:{
+                value:obj.Items[1].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[1].ChartPermissionId)
+              },
+              consumption:{
+                value:obj.Items[3].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[3].ChartPermissionId)
+              },
+              technology:{
+                value:obj.Items[5].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[5].ChartPermissionId)
+              },
+              smart:{
+                value:obj.Items[7].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[7].ChartPermissionId)
+              },
+              strategy:{
+                value:obj.Items[8].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
+              },
+              experts:{
+                value:obj.Items[9].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
+              },
+              roadshow:{
+                value:obj.Items[10].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
+              },
+              choose:{
+                value:obj.Items[11].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+              },
+              points:{
+                value:obj.Items[12].ChartPermissionId,
+                isDisabled:item.CheckList.includes(obj.Items[12].ChartPermissionId)
+              }
+            }
+          ]
+
+          auth.push(obj)
+        })
+        
+    return auth
+}
+
+
+/* 编辑客户 */
+function editHandle(item) {
+  $router.push({
+    path:'/editCustom',
+    query:{
+      id:item.CompanyId
+    }
+  })
+}
+
+
+/* 删除 */
+function delHandle(item) {
+  ElMessageBox.confirm('删除后客户将不能查阅报告,确定删除吗?','提示',{
+    type:'warning'
+  }).then(() => {
+    customInterence.customDel({
+      CompanyId:item.CompanyId
+    }).then(res => {
+      if(res.Ret === 200) {
+        ElMessage.success(res.Msg)
+
+        getTableData();
+      }
+    })
+  }).catch(() => {});
+}
+
+
+/* 查看权限 */
+const isLook = ref(false)//权限弹窗
+const authList = ref([])
+const lookAuthList = ref([])//查看的权限
+const lookAuthListEquity = ref([])
+const isPermissionTypeShow = ref(false)
+function lookHandle(item) {
+  authList.value = [];
+  lookAuthList.value = [];
+  customInterence.lookauth({
+    CompanyId:item.CompanyId
+  }).then(res => {
+    if(res.Ret === 200) {
+    let auth = [];			
+      res.Data.List ?	res.Data.List.forEach(item=> { 
+        auth.push(item.Items)
+      }):''
+      lookAuthList.value = auth.flat(Infinity);
+      getRowSpan();
+      let authEquity =[] //权益
+      res.Data.ListRai ?	res.Data.ListRai.forEach(item=> {//权益
+        // 过滤没有权限的套餐
+        authEquity.push(item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId)))
+      }):''
+      lookAuthListEquity.value = authEquity.flat(Infinity) //权益
+      isPermissionTypeShow.value = lookAuthListEquity.value.some(item => !item.IsMerge)
+      
+      getSpanArr(lookAuthListEquity.value) //权益
+    }
+  })
+  isLook.value = true;
+}
+/* 处理合并数组 */
+const rowSpanArr = ref([])
+const position = ref(0)
+function getRowSpan() {
+  rowSpanArr.value = [];
+  /* [2,0,1] */
+  lookAuthList.value.forEach((item, index) => {
+    if (index === 0) {
+      rowSpanArr.value.push(1);
+      position.value = 0;
+    } else {
+      if (lookAuthList.value[index].ClassifyName === lookAuthList.value[index - 1].ClassifyName) {
+        rowSpanArr.value[position.value] += 1; //项目名称相同,合并到同一个数组中
+        rowSpanArr.value.push(0);
+        lookAuthList.value[index].ClassifyName = lookAuthList.value[index - 1].ClassifyName;
+      } else {
+        rowSpanArr.value.push(1);
+        position.value = index;
+      }
+    }
+  });
+}
+/* 合并行规则 */
+function objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+  if (columnIndex === 0) {
+    const _row = this.rowSpanArr[rowIndex];
+      return {
+        rowspan: _row,
+        colspan: 1
+      };
+  }
+}
+
+
+/* 查看备注 */
+const lookRemarkTitle = ref('')//查看备注标题
+const	lookRemarkList = ref([])//查看备注列表
+const	lookRemarkTextarea = ref('')//备注的文本框
+const	isRemarkLook = ref(false)////查看备注弹窗
+const	lookRemarkItem = ref({})////查看备注的item项
+function lookRemarkHandle(item) {
+  /*
+  lookRemarkTitle:'',//查看备注标题
+  lookRemarkList:[],//查看备注列表
+  */
+  lookRemarkTitle.value = "备注";
+  lookAuthList.value = [];
+  lookRemarkItem.value = item;
+  customInterence.lookRemarkAuth({
+    CompanyId:item.CompanyId
+  }).then(res => {
+    if(res.Ret === 200) {
+      lookRemarkList.value=res.Data;
+    }
+  })
+  isRemarkLook.value = true;
+}
+
+const isPermissionDetailShow = ref(false)// 权限详情 弹框
+const	researchDetailId = ref(0)
+function researchDetailHandle(item) {
+  isPermissionDetailShow.value = true
+  researchDetailId.value = item.CompanyId
+}
+
+
+
+function handleContractModel() {
+
+}
+
+</script>
+<template>
+  <div class="customSearch_container">
+    <div class="customSearch_top">
+      <el-input
+        placeholder="客户名称/社会信用码/手机号码/邮箱"
+        v-model="search_txt"
+        style="max-width: 520px"
+        @keyup.enter="getTableData"
+        clearable
+      >
+        <template #prefix>
+          <el-icon><Search /></el-icon>
+        </template>
+      </el-input>
+      <el-button
+        type="primary"
+        @click="
+          pageinfo.page_no = 1;
+          getTableData();
+        "
+        style="margin-left: 20px"
+        >客户检索</el-button
+      >
+    </div>
+    <div class="customSearch_cont">
+      <el-table
+        ref="table"
+        :data="tableData"
+        v-loading="isShowloadding"
+        element-loading-text="客户检索中..."
+        border
+      >
+        <el-table-column prop="CompanyName" label="客户名称" align="center">
+          <template #default="scope">
+            <span
+              class="mouse-enter"
+              :style="
+                scope.row.Status == '潜在' ? '' : 'color:#bbb;cursor:pointer;'
+              "
+              @click="goDetail(scope.row)"
+              v-if="scope.row.IsSuspend === 1 || scope.row.Status == '潜在'"
+            >
+              {{ scope.row.CompanyName }}
+            </span>
+            <span
+              v-else
+              :class="scope.row.BtnItem.BtnView ? 'customName' : ''"
+              :style="{
+                color: scope.row.BtnItem.BtnView ? '#409EFF' : '#606266',
+                cursor: scope.row.BtnItem.BtnView ? 'pointer' : 'text',
+              }"
+              @click="goDetail(scope.row)"
+              >{{ scope.row.CompanyName }}</span
+            >
+            <el-tooltip
+              content="此客户存在长期且反复申请试用,但从未签约的情况,请谨慎领取"
+              placement="top"
+              :open-delay="500"
+              v-if="RaiSellerRole && scope.row.IsScrounge == 1"
+            >
+              <img
+                width="16"
+                style="cursor: pointer"
+                src="../../assets/img/icons/warning_triangle_yellow.png"
+              />
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column prop="CreditCode" label="社会信用码" align="center">
+          <template #default="scope">
+            <span :style="scope.row.IsSuspend === 1 ? 'color:#bbb' : ''">{{
+              scope.row.CreditCode
+            }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="Status" label="客户状态" align="center">
+          <template #default="scope">
+            <p
+              :style="
+                scope.row.IsSuspend === 1
+                  ? 'color:#bbb;margin:3px 0'
+                  : 'margin:3px 0'
+              "
+              v-for="item in transformedArray(scope.row)"
+              :key="item"
+            >
+              <template v-if="item.Status">
+                {{ item.Status }}
+                <br v-if="item.SigningStatus" />
+                <el-tag
+                  v-if="item.SigningStatus"
+                  :type="item.SigningStatus === '已签约过' ? '' : 'warning'"
+                  size="small"
+                  >{{ item.SigningStatus }}</el-tag
+                >
+              </template>
+            </p>
+          </template>
+        </el-table-column>
+        <el-table-column prop="CompanyType" label="客户类型" align="center">
+          <template #default="scope">
+            <span :style="scope.row.IsSuspend === 1 ? 'color:#bbb' : ''">{{
+              scope.row.CompanyType
+            }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="SellerName" label="销售" align="center">
+          <template #default="scope">
+            <span :style="scope.row.IsSuspend === 1 ? 'color:#bbb' : ''">{{
+              scope.row.SellerName || "--"
+            }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="Duration" label="时长(天)" align="center">
+          <template #default="scope">
+            <span :style="scope.row.IsSuspend === 1 ? 'color:#bbb' : ''">{{
+              formateDuration(scope.row.Duration,scope.row.Status)
+            }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" min-width="120">
+          <template
+            #default="scope"
+          >
+            <!-- 新操作栏 -->
+            <div style="color: #4099ef; font-size: 24px" v-if="!scope.row.ApproveStatus || scope.row.ApproveStatus === '待审批'">
+              <span
+                :class="item === 'BtnDelete' ? 'deletesty' : 'editsty'"
+                style="margin: 0 5px"
+                @click.stop="
+                  itemclickHandle({
+                    type: btnName(item, scope.row.IsSuspend),
+                    data: scope.row,
+                  })
+                "
+                v-for="(item, index) in btnList(scope.row.BtnItem, 'front')"
+                :key="index"
+                >{{ btnName(item, scope.row.IsSuspend) }}</span
+              >
+              <el-dropdown
+                placement="bottom-start"
+                @command="itemclickHandle"
+                v-if="btnList(scope.row.BtnItem, 'back').length"
+              >
+                <span class="el-dropdown-link" style="margin:0 5px">
+                  <el-icon><MoreFilled /></el-icon>
+                </span>
+                <template #dropdown>
+                  <el-dropdown-menu>
+                    <el-dropdown-item
+                      :command="{
+                        type: btnName(item, scope.row.IsSuspend),
+                        data: scope.row,
+                      }"
+                      v-for="(item, index) in btnList(
+                        scope.row.BtnItem,
+                        'back'
+                      )"
+                      :key="index"
+                    >
+                      <span>{{ btnName(item, scope.row.IsSuspend) }}</span>
+                    </el-dropdown-item>
+                  </el-dropdown-menu>
+                </template>
+              </el-dropdown>
+            </div>
+          </template>
+        </el-table-column>
+        <template #empty>
+          <div
+            style="line-height: 44px; margin: 60px 0; color: #999"
+            v-if="noResult"
+          >
+            <img
+              src="~@/assets/img/cus_m/nodata.png"
+              alt=""
+              style="display: block; width: 160px; height: 128px; margin: auto"
+            />
+            <span>暂无信息</span>
+          </div>
+          <div
+            style="line-height: 44px; margin: 200px 0; color: #999"
+            v-else
+          ></div>
+        </template>
+      </el-table>
+      <!-- 分页 -->
+      <el-col :span="24" class="toolbar">
+        <mPage
+          :total="pageinfo.total"
+          :page_no="pageinfo.page_no"
+          :pageSize="pageinfo.page_size"
+          @handleCurrentChange="handleCurrentChange"
+        />
+      </el-col>
+    </div>
+    
+  </div>
+</template>
+<style scoped lang="scss">
+.customSearch_container {
+	.customSearch_top {
+		display: flex;
+		// justify-content:flex-end;
+		align-items: center;
+		border: 1px solid #ECECEC;
+		padding: 20px 30px;
+		background: #fff;
+		border-radius: 4px;
+		box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+	}
+	.customSearch_cont {
+		min-height: calc(100vh - 320px);
+		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);
+	}
+	.menu_lists {
+		padding: 40px 18px;
+		border-radius: 4px;
+		.menu_item {
+			display: flex;
+			// align-items: center;
+			margin-bottom: 30px;
+			&:last-child {
+				margin-bottom: 0;
+			}
+			.list_item {
+				margin-right: 20px;
+				margin-bottom: 10px;
+				&:last-child {
+					margin-right: 0;
+				}
+			}
+		}
+	}
+	.look-remark-commit {
+		width: 426px;
+		height: 41px;
+		background: #409EFF;
+		margin:  30px auto;
+		text-align: center;
+		line-height: 41px;
+		color: #fff;
+		box-shadow: 0px 2px 6px 1px rgba(64, 158, 255, 0.05);
+		border-radius: 4px 4px 4px 4px;
+		cursor: pointer;
+	
+	}
+	.mouse-enter {
+		&:hover {
+			text-decoration:underline;
+		}
+	}
+
+  .look-remark-commit {
+		width: 426px;
+		height: 41px;
+		background: #409EFF;
+		margin:  30px auto;
+		text-align: center;
+		line-height: 41px;
+		color: #fff;
+		box-shadow: 0px 2px 6px 1px rgba(64, 158, 255, 0.05);
+		border-radius: 4px 4px 4px 4px;
+		cursor: pointer;
+	
+	}
+  
+  :deep(.el-dropdown) {
+    vertical-align: middle;
+  }
+}
+</style>
+

+ 222 - 0
src/views/custom_manage/officalTrial/trialApplication.vue

@@ -0,0 +1,222 @@
+<script setup>
+import { ref,computed } from 'vue'
+import { ElMessageBox,ElMessage } from 'element-plus'
+import { Search } from '@element-plus/icons-vue'
+import { customInterence } from "@/api/api.js";
+import mPage from '@/components/mPage.vue'
+
+
+const isShowloadding = ref(false)
+const tableData =   ref([]) //表格数据
+const page_no =  ref(1)
+const pageSize =  ref(10)
+const total =  ref(0)
+const lang = ref("中文官网")
+const search_txt = ref("") // 搜索关键字
+/* 获取表格数据 */
+function getTableData() {
+  isShowloadding.value = true;
+  customInterence
+    .trialList({
+      PageSize: 10,
+      CurrentIndex: page_no.value,
+      SourceType: lang.value,
+      KeyWord: search_txt.value,
+    })
+    .then((res) => {
+      if (res.Ret === 200) {
+        total.value = res.Data.Paging.Totals;
+      
+        tableData.value = res.Data.List;
+      } else {
+        tableData.value = [];
+      }
+      isShowloadding.value = false;
+    })
+}
+getTableData()
+
+
+/* 页码改变 */
+function  handleCurrentChange(page) {
+  page_no.value = page;
+  getTableData();
+}
+
+
+/* 点击"未处理" */
+function statusHandle(item) {
+  ElMessageBox.confirm("请确认已处理客户申请?", "提示", {
+  type: "warning",
+  })
+  .then(() => {
+    customInterence
+      .trialStatus({
+      Id: item.Id,
+      })
+      .then((res) => {
+      
+      if (res.Ret === 200) {
+        ElMessage.success("操作成功!");
+        getTableData();
+      }
+      });
+  })
+  .catch(() => {});
+}
+
+/* 中英文按钮 */
+function cEnClick(txt) {
+  search_txt.value = "";
+  lang.value = txt;
+
+  page_no.value = 1;
+  getTableData();
+}
+
+const cnColumn = [
+  { label: '企业名称',key: 'CompanyName' },
+  { label: '姓名',key: 'RealName' },
+  { label: '手机号/邮箱',key: 'Phone' },
+  { label: '所属行业',key: 'Industry' },
+  { label: '申请时间',key: 'CreateTimeStr' },
+  { label: '申请品种',key: 'ProductInfo' },
+]
+const enColumn = [
+  { label: '企业名称',key: 'CompanyName' },
+  { label: '姓名',key: 'RealName' },
+  { label: '邮箱',key: 'Email' },
+  { label: '信息',key: 'Message' },
+  { label: '发送时间',key: 'CreateTimeStr' },
+]
+const columns = computed(() => {
+  return lang.value==='中文官网' ? cnColumn : enColumn
+})
+
+</script>
+<template>
+  <div class="trialApplication_container">
+		<div class="trialApplication_top">
+			<div class="left">
+				<el-button type="primary" ref="btnCn" :plain="lang!=='中文官网'" @click="cEnClick('中文官网')">中文网站</el-button>
+				<el-button type="primary" ref="btnEn" :plain="lang!=='英文官网'" @click="cEnClick('英文官网')"
+					>英文网站</el-button
+				>
+			</div>
+			<div class="right">
+        <el-input
+          placeholder="公司名称/手机号码"
+          v-model="search_txt"
+          clearable
+          style="max-width: 500px"
+          ref="searchInput"
+        >
+          <template #prefix>
+            <el-icon><Search /></el-icon>
+          </template>
+        </el-input>
+        
+			  <el-button @click="getTableData" type="primary">客户检索</el-button>
+			</div>
+		</div>
+		<div class="trialApplication_cont">
+			<!-- 中文官网 -->
+			<el-table
+			ref="table"
+			:data="tableData"
+			v-loading="isShowloadding"
+			element-loading-text="数据加载中..."
+			border
+			>
+			<el-table-column
+				:label="item.label"
+				align="center"
+        v-for="item in columns"
+        :key="item.key"
+			>
+				<template #default="scope">
+          <span v-if="key==='Phone'">{{scope.row[item.key] || scope.row.Email}}</span>
+          
+					<span v-else>{{ scope.row[item.key] }}</span>
+				</template>
+			</el-table-column>
+			<el-table-column label="操作" align="center">
+				<template #default="scope">
+					<div style="color: #4099ef; font-size: 24px">
+					<span
+						v-if="scope.row.Status == '待处理'"
+						class="processed editsty"
+						@click.stop="statusHandle(scope.row)"
+						>标记处理 
+					</span>
+					</div>
+				</template>
+			</el-table-column>
+      <template #empty>
+        <div style="line-height: 44px; margin: 60px 0; color: #999">
+          <img
+            src="~@/assets/img/cus_m/nodata.png"
+            alt=""
+            style="display: block; width: 160px; height: 128px; margin: auto"
+          />
+          <span>暂无信息</span>
+        </div>
+      </template>
+    </el-table>
+
+			<el-col :span="24" class="toolbar">
+         <mPage
+          :total="total"
+          :page_no="page_no"
+          :pageSize="pageSize"
+          @handleCurrentChange="handleCurrentChange"
+        />
+			</el-col>
+		</div>
+	</div>
+</template>
+<style lang="scss" scoped>
+.trialApplication_container {
+  .el-form-item__label {
+    font-size: 16px;
+    padding-right: 20px !important;
+  }
+  .trialApplication_top {
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    align-items: center;
+    border: 1px solid #ececec;
+    padding: 20px 30px;
+    background: #fff;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    .left {
+      width: 215px;
+    }
+    .right {
+      width: 617px;
+    }
+    a {
+      float: left;
+    }
+    a:last-of-type {
+      float: right;
+      margin-left: 19px;
+    }
+  }
+  .trialApplication_cont {
+    padding: 20px 30px 80px;
+    margin-top: 20px;
+    background-color: #fff;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    position: relative;
+    border: 1px solid #ececec;
+    border-radius: 4px;
+  }
+  /* 待处理hover效果 */
+  .el-table__row td:last-of-type .cell div span {
+    cursor: pointer;
+  }
+}
+</style>

+ 28 - 0
src/views/dashboard_manage/components/chart.vue

@@ -0,0 +1,28 @@
+<script setup>
+import { watch,ref,nextTick } from 'vue'
+import Highcharts from 'highcharts';
+
+const props = defineProps({
+  id: {
+    type: String
+  },
+  options: {
+    type: Object
+  }
+})
+
+const chart = ref(null)
+function initChart() {
+  console.log('initchart')
+  nextTick(() => {
+    chart.value = Highcharts.chart(props.id,props.options) 
+  })
+}
+initChart()
+
+</script>
+<template>
+  <div :id="id" class="chart-wrapper"></div>
+</template>
+<style scoped lang="scss">
+</style>

+ 229 - 0
src/views/dashboard_manage/hooks/use-chart.js

@@ -0,0 +1,229 @@
+import { filterMoney } from '@/common/js/util';
+
+const baseOpt = {
+  title: {
+    text: ''
+  },
+  accessibility: {
+    enabled: false
+  },
+  chart: {
+    style: {
+      fontSize: 16
+    }
+  },
+  credits: {
+    enabled: false
+  },
+  legend: {
+    align: 'right',
+    verticalAlign: 'top'
+  },
+}
+
+export function useChart(type,data,key=null) {
+  const chartType = {
+    'bar': renderBar,
+    'line': renderLine,
+    'pie': renderPie
+  }
+
+  let options = chartType[type](data,key)
+
+  return options;
+}
+
+//柱形图
+const titleMap = {
+  'NewCompanyTotal': '新签客户',
+  'RenewalCompanyTotal': '续约客户',
+  'NotRenewalCompanyTotal': '未续约客户',
+  'CompanyTotal': '客户数',
+}
+function renderBar(data) {
+  const opt = {
+    colors: ['#5470c6', '#9a60b4', '#ea7ccc'],
+    yAxis: {
+      labels: {
+        style: {
+          color: '#999'
+        }
+      },
+      title: {
+        enabled: false
+      }
+    },
+    xAxis: {
+      categories: data.Date,
+      labels: {
+        style: {
+          color: '#999'
+        }
+      },
+      tickWidth: 1,
+      tickLength: 5,
+    },
+    series: [],
+    ...baseOpt
+  }
+  const filterKey = Object.keys(data).filter(key => !['Date','Title'].includes(key));
+
+  filterKey.forEach(key => {
+    let obj = {
+      data: data[key],
+      type: 'column',
+      name: titleMap[key],
+    };
+    opt.series.push(obj);
+  });
+
+
+  return opt
+}
+
+//折线图
+function renderLine(data) {
+  const opt = {
+    colors: ['#CD5C5C', '#25DEDB'],
+    plotOptions: {
+      series: {
+        marker: {
+          fillColor: '#FFFFFF',
+          lineWidth: 2,
+          lineColor: null
+        }
+      }
+    },
+    xAxis: {
+      categories: data.Date,
+      labels: {
+        style: {
+          color: '#999'
+        }
+      },
+      tickWidth: 1,
+      tickLength: 5,
+    },
+    yAxis: [
+      {
+        gridLineWidth: 0,
+        labels: {
+          style: {
+            color: '#999'
+          }
+        },
+        title: {
+          text: '合同数',
+          align:'high',
+          style: {
+            color: '#999'
+          },
+          y: -10,
+          offset: 0,
+          rotation: 0,
+        }
+      },
+      {
+        gridLineWidth: 0,
+        opposite: true,
+        labels: {
+          style: {
+            color: '#999'
+          }
+        },
+        title: {
+          text: '合同金额/元',
+          align:'high',
+          style: {
+            color: '#999'
+          },
+          y: -10,
+          offset: 0,
+          rotation: 0,
+        }
+      },
+    ],
+    series: [
+      {
+        data: [],
+        type: 'line',
+        name: '合同数',
+        yAxis: 0,
+      },
+      {
+        type: 'line',
+        name: '合同金额',
+        yAxis: 1,
+        data: [],
+      },
+    ],
+    ...baseOpt
+  }
+  
+  opt.series[0].data = data.ContractTotal;
+  opt.series[1].data = data.MoneyTotal;
+
+  return opt
+}
+
+//饼图
+const keyMap = {
+  'MoneyTotal': {
+    title: '有效合同金额',
+    color: '#FE4545'
+  },
+  'ContractTotal': {
+    title: '有效合同数',
+    color: '#FF7113'
+  },
+  'FormalCompanyCount': {
+    title: '正式客户数',
+    color: '#486CFF'
+  }
+}
+function renderPie(data,key) {
+  const opt = {
+    ...baseOpt,
+    chart: {
+      width: 200,
+      height: 200
+    },
+    yAxis: {
+      title: ''
+    },
+    title: {
+      floating:true,
+      y:80,
+      text: filterMoney(data[key]),
+      style: {
+        fontSize: 20
+      }
+    },
+    subtitle: {
+      floating:true,
+      y:100,
+      text: keyMap[key].title,
+      style: {
+        fontSize: 12
+      }
+    },
+    series: [{
+      type: 'pie',
+      name: '',
+      innerSize: '82%',
+      label: {
+        enabled: false
+      },
+      data: [{
+        name: keyMap[key].title,
+        color: keyMap[key].color,
+        y: data[key],
+        dataLabels: {
+          enabled: false
+        }
+      }]
+    }]
+  }
+
+  return opt
+}

+ 307 - 4
src/views/dashboard_manage/workBench.vue

@@ -1,9 +1,312 @@
 <script setup>
+import { ref,reactive,toRefs,computed } from 'vue'
+import { useRouter } from 'vue-router'
+import { dataMainInterface } from "@/api/api.js";
+import { useAppStore } from '@/store/modules/app'
+import { InfoFilled } from '@element-plus/icons-vue'
+import { useChart } from './hooks/use-chart'
+import Chart from './components/chart.vue'
 
+const $router = useRouter()
+
+const appStore = useAppStore();
+
+const dataAuth = computed(() => appStore.dataAuth)
+
+const showData = ref(false)
+
+const staticLabels = [
+  {
+    label: "正式客户数",
+  },
+  {
+    label: "试用客户数",
+  },
+  {
+    label: "新签客户数",
+  },
+  {
+    label: "续约客户数",
+  },
+  {
+    label: "未续约客户数",
+  },
+]
+
+const dataState = reactive({
+  dataInfo: {},
+  total_formal: 0, //正式客户数
+  total_trial: 0, //试用客户数
+  total_newsign: 0, //新签客户数
+  total_renew: 0, //续约客户数
+  total_notrenew: 0, //未续约客户数
+})
+ // 获取数据
+function getWorkdata() {
+  dataMainInterface.workdata().then((res) => {
+    if (res.Ret === 200) {
+      dataState.dataInfo = res.Data;
+
+      dataState.total_formal = res.Data.FormalCompanyCount;
+      dataState.total_trial = res.Data.TrialCompanyTotal;
+      dataState.total_newsign = res.Data.NewCompanyTotal;
+      dataState.total_renew = res.Data.RenewalCompanyTotal;
+      dataState.total_notrenew = res.Data.NotRenewalCompanyTotal;
+      showData.value = true;
+
+      getChartsOpts()
+    }
+  });
+}
+getWorkdata()
+
+// 获取图表option
+const optionState = reactive({
+  incremeOption: null,
+  expireOption: null,
+  incomeOption: null,
+  moneyOption: null,
+  contractOption: null,
+  formalCompanyOption: null,
+})
+function getChartsOpts() {
+  optionState.incremeOption = useChart('bar',dataState.dataInfo.IncrementalCompanyChartList);
+
+  optionState.expireOption = useChart('bar',dataState.dataInfo.WillExpireChartList); 
+
+  optionState.incomeOption = useChart('line',dataState.dataInfo.IncomeChartList);
+
+  optionState.moneyOption = useChart('pie',dataState.dataInfo.ContractData,'MoneyTotal');
+
+  optionState.contractOption = useChart('pie',dataState.dataInfo.ContractData,'ContractTotal');
+
+  optionState.formalCompanyOption = useChart('pie',dataState.dataInfo.ContractData,'FormalCompanyCount');
+}
+
+//顶部数据块点击跳转
+function handleTopGo(type) {
+  if (type === "正式客户数") {
+    $router.push({
+      path: "/customList",
+      query: {
+        act_status: "正式",
+      },
+    });
+  } else if (type === "试用客户数") {
+    $router.push({
+      path: "/customList",
+      query: {
+        act_status: "试用",
+      },
+    });
+  } else if (type === "新签客户数") {
+    $router.push({
+      path: "/stocklist",
+      query: {
+        type: "新签客户",
+      },
+    });
+  } else if (type === "续约客户数") {
+    $router.push({
+      path: "/stocklist",
+      query: {
+        type: "续约客户",
+      },
+    });
+  } else if (type === "未续约客户数") {
+    $router.push({
+      path: "/stocklist",
+      query: {
+        type: "未续约客户",
+      },
+    });
+  }
+}
+
+/* 页面跳转 */
+const pathMap = {
+  'incre': '/incrementalist',
+  'expire': '/expiringlist',
+  'income': '/incomelist',
+  'contract': '/contractlist',
+}
+function linkHandle(type) {
+  $router.push({
+    path: pathMap[type]
+  });
+}
+
+const { dataInfo,total_formal,total_trial,total_newsign,total_renew,total_notrenew } = toRefs(dataState)
 </script>
 <template>
-  <div>工作台</div>
-</template>
-<style scoped>
+  <div class="workbench-container" :loading="!showData">
+    <div class="workbench_top">
+      <h3>系统实时数据(每30分钟更新)</h3>
+      <el-row type="flex" justify="space-between" class="label-row">
+        <el-col v-for="item in staticLabels" :key="item.label" :span="4">
+          <el-card class="base-card" @click="handleTopGo(item.label)" shadow="hover">
+            <template #header>
+              <div class="clearfix">
+                <span>
+                  {{ item.label }}
+                  <el-tooltip
+                    v-if="item.label === '新签客户数' || item.label === '续约客户数' || item.label === '未续约客户数'"
+                    class="item"
+                    effect="dark"
+                    :content="
+                      item.label === '新签客户数'
+                        ? '当前状态为正式,且处于新签合同的存续期内的客户'
+                        : item.label === '续约客户数'
+                        ? '当前状态为正式,且处于续约合同的存续期内的客户'
+                        : '历史上有过正式转试用记录,且查询时间点为非正式、非永续状态的客户'
+                    "
+                    placement="top"
+                  >
+                    <i class="el-icon-info"></i>
+                  </el-tooltip>
+                </span>
+              </div>
+            </template>
+            <div class="card-cont">
+              {{ item.label === '正式客户数'
+                    ? total_formal
+                    : item.label === '试用客户数'
+                    ? total_trial
+                    : item.label === '新签客户数'
+                    ? total_newsign
+                    : item.label === '续约客户数'
+                    ? total_renew
+                    : item.label === '未续约客户数'
+                    ? total_notrenew
+                    : '' }}
+              <!-- <countTo
+                :duration="2000"
+                :startVal="0"
+                :endVal="
+                  item.label === '正式客户数'
+                    ? total_formal
+                    : item.label === '试用客户数'
+                    ? total_trial
+                    : item.label === '新签客户数'
+                    ? total_newsign
+                    : item.label === '续约客户数'
+                    ? total_renew
+                    : item.label === '未续约客户数'
+                    ? total_notrenew
+                    : ''
+                "
+              /> -->
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+    <el-row type="flex" justify="space-between" class="label-row" style="margin-top: 40px"  v-if="showData">
+      <el-col :span="11">
+        <el-card shadow="never" class="chart-item">
+          <span class="editsty lookdtl" @click="linkHandle('incre')" v-if="dataAuth">查看数据详情>></span>
+          <h2 class="pie-title">
+            {{ dataInfo.IncrementalCompanyChartList.Title }}
+            <el-tooltip class="item" effect="dark" placement="top-start">
+              <template #content>
+                <div>
+                  新签客户:新签合同的起始日期包含在所选时间段内的客户 <br />续约客户:续约合同的起始日期包含在所选时间段内且不包含在新签合同存续期内的客户
+                </div>
+              </template>
+              <el-icon><InfoFilled /></el-icon>
+            </el-tooltip>
+          </h2>
+          <Chart id="barChart1" :options="optionState.incremeOption"/>
+        </el-card>
+      </el-col>
+      <el-col :span="11" :pull="1">
+        <el-card shadow="never" class="chart-item">
+          <span class="editsty lookdtl" @click="linkHandle('expire')" v-if="dataAuth">查看数据详情>></span>
+          <h2 class="pie-title">
+            {{ dataInfo.WillExpireChartList.Title }}
+            <el-tooltip class="item" effect="dark" content="合同截止日期在所选时间段内的客户" placement="top-start">
+              <el-icon><InfoFilled /></el-icon>
+            </el-tooltip>
+          </h2>
+          <Chart id="barChart2" :options="optionState.expireOption"/>
+        </el-card>
+      </el-col>
+      <el-col :span="11">
+        <el-card shadow="never" class="chart-item">
+          <span class="editsty lookdtl" @click="linkHandle('income')" v-if="dataAuth">查看数据详情>></span>
+          <h2 class="pie-title">
+            {{ dataInfo.IncomeChartList.Title }}
+            <el-tooltip class="item" effect="dark" placement="top-start">
+              <template #content>
+                <div>合同数:合同起始日期在所选月份区间内的合同数 <br />合同金额:合同金额的总和</div>
+              </template>
+              <el-icon><InfoFilled /></el-icon>
+            </el-tooltip>
+          </h2>
+          <Chart id="lineChart" :options="optionState.incomeOption"/>
+        </el-card>
+      </el-col>
+      <el-col :span="11" :pull="1">
+        <el-card shadow="never" class="chart-item">
+          <span class="editsty lookdtl" @click="linkHandle('contract')" v-if="dataAuth">查看数据详情>></span>
+          <h2 class="pie-title">
+            {{ dataInfo.ContractData.Title }}
+            <el-tooltip class="item" effect="dark" placement="top-start">
+              <template #content>
+                <div>有效合同数:当前未到期的合同总数量(合同截止日期≥所选日期) <br />合同总金额:当前未到期的合同金额总和 <br />正式客户数:当前处于有效合同执行期的客户数</div>
+              </template>
+              <el-icon><InfoFilled /></el-icon>
+            </el-tooltip>
+          </h2>
+          <div class="pie-cont">
+            <Chart id="pieChart1" :options="optionState.contractOption"/>
 
-</style>
+            <Chart id="pieChart2" :options="optionState.moneyOption"/>
+
+            <Chart id="pieChart3" :options="optionState.formalCompanyOption"/>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<style scoped lang="scss">
+.workbench-container {
+  .label-row {
+    margin-top: 20px;
+    flex-wrap: wrap;
+    .base-card {
+      color: #999;
+      font-size: 16px;
+      cursor: pointer;
+      .card-cont {
+        font-size: 30px;
+        color: #333;
+      }
+    }
+    .chart-item {
+      min-height: 500px;
+      border: 1px solid #e6e6e6;
+      box-shadow: -2px 3px 6px rgba(172, 172, 172, 0.13);
+      margin-bottom: 40px;
+      .lookdtl {
+        display: block;
+        text-align: right;
+        margin-bottom: 15px;
+        &:hover {
+          text-decoration: underline;
+        }
+      }
+      .pie-cont {
+        display: flex;
+        justify-content: space-around;
+        margin-top: 60px;
+      }
+      .pie-title {
+        font-size: 19px;
+        color: #555;
+      }
+    }
+  }
+}
+</style>