@dongkboy 7 месяцев назад
Родитель
Сommit
d8ce415fb6
30 измененных файлов с 5420 добавлено и 310 удалено
  1. 2 0
      src/api/index.ts
  2. 62 0
      src/api/modules/partner.ts
  3. 34 21
      src/components/SearchForm/index.vue
  4. 1 1
      src/router/modules/operation.ts
  5. 91 0
      src/router/modules/partner.ts
  6. 8 2
      src/router/modules/representative.ts
  7. 15 15
      src/router/modules/sale.ts
  8. 2 1
      src/router/routes.ts
  9. 4 3
      src/store/modules/route.ts
  10. 19 18
      src/views/additionalOrder/adjust/adjustRecord.vue
  11. 2 0
      src/views/externalAgreement/agreement/agreementIndex.vue
  12. 2 0
      src/views/externalAgreement/costManagement.vue
  13. 19 18
      src/views/insurancePolicy/adjustRecord.vue
  14. 1 0
      src/views/operationManagement/modules/addOperation.vue
  15. 848 0
      src/views/partnerManagement/LevelRule.vue
  16. 153 0
      src/views/partnerManagement/commissionChangeLog.vue
  17. 148 0
      src/views/partnerManagement/commissionDetails.vue
  18. 430 0
      src/views/partnerManagement/commissionRule.vue
  19. 134 0
      src/views/partnerManagement/expiredCommission.vue
  20. 1643 0
      src/views/partnerManagement/modules/addPartner.vue
  21. 465 0
      src/views/partnerManagement/partner.vue
  22. 657 0
      src/views/partnerManagement/partnerDetail.vue
  23. 176 0
      src/views/partnerManagement/purchaseHistory.vue
  24. 399 0
      src/views/partnerManagement/upgradeDowngradeRecord.vue
  25. 3 1
      src/views/quoteConfig/agreement/agreementIndex.vue
  26. 2 0
      src/views/quoteConfig/costManagement.vue
  27. 2 0
      src/views/representative/externalCostApproval.vue
  28. 66 135
      src/views/representative/member.vue
  29. 2 0
      src/views/representative/quoteApproval.vue
  30. 30 95
      src/views/representative/salesman.vue

+ 2 - 0
src/api/index.ts

@@ -10,6 +10,7 @@ import appApi from './modules/app'
 import userApi from './modules/user'
 import roleApi from './modules/role'
 import institutionApi from './modules/institution'
+import partnerApi from './modules/partner'
 import areaApi from "./modules/area"
 import operationApi from './modules/operation.ts'
 import menuApi from './modules/menu.ts'
@@ -125,6 +126,7 @@ const api = {
   userApi: userApi(axiosInstance),
   roleApi: roleApi(axiosInstance),
   institutionApi:institutionApi(axiosInstance),
+  partnerApi:partnerApi(axiosInstance),
   areaApi:areaApi(axiosInstance),
   operationApi: operationApi(axiosInstance),
   menuApi:menuApi(axiosInstance),

+ 62 - 0
src/api/modules/partner.ts

@@ -0,0 +1,62 @@
+import { ApiInstance } from '../type'
+const institutionApi = (axiosInstance: ApiInstance) => ({
+
+  // 佣金变更记录
+  kickbackChangeQueryPage: (data: any) => axiosInstance.post('/partner/kickbackChange/queryPage', data),
+  // 人员等级列表
+  queryGradeName: () => axiosInstance.get('/partner/rule/queryGradeName'),
+  // 合伙人升降级记录
+  liftingRecordQueryPage: (data: any) => axiosInstance.post('/partner/liftingRecord/queryPage', data),
+  // 升降记录审批
+  liftingRecordaudit: (data: any) => axiosInstance.post('/partner/liftingRecord/audit', data),
+  // 降级升降记录审核
+  liftingRecorddowngradeAudit: (data: any) => axiosInstance.post('/partner/liftingRecord/downgradeAudit', data),
+  //获取等级配置金额
+  unlockLevels: (params: any) => axiosInstance.get('/partner/liftingRecord/unlockLevel?grade=' + params),
+  // 解锁等级
+  confirmUnlocking: (data: any) => axiosInstance.post('/partner/liftingRecord/confirmUnlocking', data),
+  // 佣金明细查询
+  commissionDetailsPage: (data: any) => axiosInstance.post('/partner/commissionDetails/queryPage', data),
+
+  // 合伙人等级规则保存
+  partnersaveRule: (data: any) => axiosInstance.post('/partner/rule/save', data),
+  // 合伙人等级规则查询
+  partnerqueryRule: () => axiosInstance.get('/partner/rule/query'),
+  //合伙人佣金规则查询
+  commissionQuery: () => axiosInstance.get('/partner/commission/query'),
+  //佣金规则提交
+  commissionsave: (data: any) => axiosInstance.post('/partner/commission/save', data),
+  //查询购买记录
+  purchaseRecordPage: (data: any) => axiosInstance.post('/purchaseRecord/queryPage', data),
+  //查看购买凭证
+  purchaseviewVouchers: (params: any) => axiosInstance.get('/purchaseRecord/viewVouchers?id=' + params),
+  //查询过期佣金
+  expiredCommissionPage: (data: any) => axiosInstance.post('/expiredCommission/queryPage', data),
+
+
+  // 合伙人管理
+  // 合伙人人员列表
+  partnerQueryPage: (data: any) => axiosInstance.post('/partner/queryPage', data),
+  //查询合伙人上级推荐人
+  selectByUserNameAndMobile: (grade: any) => axiosInstance.get('/userInfo/selectByUserNameAndMobile?grade=' + grade),
+  // 查询业务员
+  selectByMobile: (params: any) => axiosInstance.get('/userInfo/selectByMobile?mobile=' + params),
+  // 添加合伙人
+  saveByPartner: (data: any) => axiosInstance.post('/userInfo/saveByPartner', data),
+  // 启用禁用
+  enableDisable: (id: any, status: any) => axiosInstance.get('/partner/enableDisable?userId=' + id + '&status=' + status),
+  // 关系查询
+  relationalQuery: (params: any) => axiosInstance.get('/partner/relationalQuery?id=' + params),
+  // 查询合伙人等级
+  queryGrade: (params: any) => axiosInstance.get('/partner/getUserGradeList?userId=' + params),
+  // 添加新等级
+  addNewGrade: (data: any) => axiosInstance.post('/partner/addUserIdentity', data),
+  // 查询合伙人审核列表
+  partnerReviewList: (data: any) => axiosInstance.post('/userInfo/partnerReviewList', data),
+  //审核接口
+  userInfoPartnerReview: (params: any) => axiosInstance.get('/userInfo/partnerReview?userInfoId=' + params.userInfoId + '&reviewStatus=' + params.reviewStatus),
+
+})
+
+
+export default institutionApi

+ 34 - 21
src/components/SearchForm/index.vue

@@ -7,14 +7,22 @@
             :placeholder="field.placeholder" clearable class="el-inputs" />
           <component v-else-if="field.type === 'select'" is="el-select" v-model="formInline[field.model]"
             :placeholder="field.placeholder" clearable class="el-inputs" v-bind="field">
-            <el-option v-for="(item, index) in field.options" :key="index" :label="item.label" :value="item.value" />
+            <el-option v-for="(item, index) in field.options" :key="index" :label="item[field.props?.label || 'label']"
+              :value="item[field.props?.value || 'value']">
+              <template #default="scope">
+                <slot :name="`${field.model}-option`" :item="item" >
+                  {{ item[field.props?.label || 'label'] }}
+                </slot>
+              </template>
+            </el-option>
+
           </component>
           <component v-else-if="field.type === 'cascader'" is="el-cascader" v-model="formInline[field.model]"
-            :options="field.options" :props="field.props" :placement="field.placement" filterable clearable @change="field.onChange"
-            class="el-inputs" />
+            :options="field.options" :props="field.props" :placement="field.placement" filterable clearable
+            @change="field.onChange" class="el-inputs" />
           <component v-else-if="field.type === 'date'" is="el-date-picker" v-model="formInline[field.model]"
             :type="field.dateType" range-separator="至" :start-placeholder="field.startplaceholder"
-            format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" time-format="HH:mm:ss"
+            :format="field.format" :value-format="field.valueFormat" :time-format="field.timeFormat"
             :end-placeholder="field.endplaceholder" clearable @change="field.onChange" />
         </ElFormItem>
       </ElCol>
@@ -36,6 +44,8 @@
 </template>
 
 <script lang="ts" setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+
 const props = withDefaults(defineProps<{
   fields: Array<{
     label: string; // 字段标签
@@ -46,6 +56,12 @@ const props = withDefaults(defineProps<{
     props?: any; // Cascader 组件的其他 props
     onChange?: (value: any) => void; // 变化事件
     dateType?: string; // 日期选择器类型
+    format?: string; // 日期格式
+    valueFormat?: string; // 日期值格式
+    timeFormat?: string; // 时间格式
+    startplaceholder?: string; // 开始日期占位符
+    endplaceholder?: string; // 结束日期占位符
+    clearable?: boolean; // 是否可清空
     [key: string]: any,
   }>; // 字段信息数组
   formInline: any; // 表单数据
@@ -57,11 +73,8 @@ const props = withDefaults(defineProps<{
   span: 8,
   isOffset: false,
 });
-const windowWidth = ref(window.innerWidth);
 
-onBeforeMount(() => {
-  console.log(props)
-});
+const windowWidth = ref(window.innerWidth);
 
 onMounted(() => {
   window.addEventListener('resize', updateWindowWidth)
@@ -85,19 +98,19 @@ const btnOffset = computed(() => {
     return 0;
   }
   // 计算逻辑
-	const items = props.fields.length;
-	const columns = 24 / props.span; // 列布局
-	const spanPerItem = props.span; // 每列的span
-	const itemsOnLastRow = items % columns;
+  const items = props.fields.length;
+  const columns = 24 / props.span; // 列布局
+  const spanPerItem = props.span; // 每列的span
+  const itemsOnLastRow = items % columns;
 
-	if (itemsOnLastRow === 0) {
-		// 如果刚好占满最后一行,按钮就需要另起一行,并偏移3个位置
-		return (columns - 1) * spanPerItem; 
-	} else {
-		// 如果最后一行没占满,计算需要空出的位置数量
-		const emptySlots = columns - 1 - itemsOnLastRow;
-		return emptySlots * spanPerItem;
-	}
+  if (itemsOnLastRow === 0) {
+    // 如果刚好占满最后一行,按钮就需要另起一行,并偏移3个位置
+    return (columns - 1) * spanPerItem;
+  } else {
+    // 如果最后一行没占满,计算需要空出的位置数量
+    const emptySlots = columns - 1 - itemsOnLastRow;
+    return emptySlots * spanPerItem;
+  }
 });
 
 const handleSearch = () => {
@@ -111,4 +124,4 @@ const handleReset = () => {
 .el-inputs {
   width: 100% !important;
 }
-</style>
+</style>

+ 1 - 1
src/router/modules/operation.ts

@@ -50,7 +50,7 @@ const routes: RouteRecordRaw = {
         title: '电销组管理',
       },
     },
-
+  
   ],
 }
 

+ 91 - 0
src/router/modules/partner.ts

@@ -0,0 +1,91 @@
+import type { RouteRecordRaw } from 'vue-router'
+
+const Layout = () => import('@/layouts/index.vue')
+
+const routes: RouteRecordRaw = {
+  path: '/partnerManagement',
+  component: Layout,
+  redirect: '/partnerManagement/partner',
+  name: 'partnerManagement',
+  meta: {
+    title: '合伙人管理',
+  },
+  children: [
+    {
+      path: 'partner',
+      name: 'partnerList',
+      component: () => import('@/views/partnerManagement/partner.vue'),
+      meta: {
+        title: '合伙人管理',
+      },
+      children:[]
+    },
+    {
+      path: 'partnerDetail',
+      name: 'PartnerDetail',
+      component: () => import('@/views/partnerManagement/partnerDetail.vue'),
+      meta: {
+        title: '合伙人详情',
+        menu: false,
+      },
+    },
+    {
+      path: 'commissionChangeLog',
+      name: 'CommissionChangeLog',
+      component: () => import('@/views/partnerManagement/commissionChangeLog.vue'),
+      meta: {
+        title: '佣金变更记录',
+      },
+    },
+    {
+      path: 'upgradeDowngradeRecord',
+      name: 'UpgradeDowngradeRecord',
+      component: () => import('@/views/partnerManagement/upgradeDowngradeRecord.vue'),
+      meta: {
+        title: '升降级记录',
+      },
+    },
+    {
+      path: 'commissionDetails',
+      name: 'CommissionDetails',
+      component: () => import('@/views/partnerManagement/commissionDetails.vue'),
+      meta: {
+        title: '佣金明细',
+      },
+    },
+    {
+      path: 'levelRule',
+      name: 'LevelRule',
+      component: () => import('@/views/partnerManagement/LevelRule.vue'),
+      meta: {
+        title: '等级规则',
+      },
+    },
+    {
+      path: 'commissionRule',
+      name: 'CommissionRule',
+      component: () => import('@/views/partnerManagement/commissionRule.vue'),
+      meta: {
+        title: '佣金规则',
+      },
+    },
+    {
+      path: 'purchaseHistory',
+      name: 'PurchaseHistory',
+      component: () => import('@/views/partnerManagement/purchaseHistory.vue'),
+      meta: {
+        title: '购买记录',
+      },
+    },
+    {
+      path: 'expiredCommission',
+      name: 'ExpiredCommission',
+      component: () => import('@/views/partnerManagement/expiredCommission.vue'),
+      meta: {
+        title: '过期佣金',
+      },
+    },
+  ],
+}
+
+export default routes

+ 8 - 2
src/router/modules/representative.ts

@@ -67,9 +67,15 @@ const routes: RouteRecordRaw = {
           },
         },
       ]
-
     },
-
+    {
+      path: 'partnerReview',
+      name: 'PartnerReview',
+      component: () => import('@/views/representative/partnerReview.vue'),
+      meta: {
+        title: '合伙人审核',
+      },
+    },
 
   ],
 }

+ 15 - 15
src/router/modules/sale.ts

@@ -3,49 +3,49 @@ import type { RouteRecordRaw } from 'vue-router'
 const Layout = () => import('@/layouts/index.vue')
 
 const routes: RouteRecordRaw = {
-  path: '/sale',  
+  path: '/sale',
   component: Layout,
-  redirect: '/sale/list',  
+  redirect: '/sale/list',
   name: 'sale',
   meta: {
     title: '分销管理',
   },
   children: [
     {
-      path: 'list',  
+      path: 'list',
       name: 'saleList',
-      component: () => import('@/views/sale/list.vue'),  
+      component: () => import('@/views/sale/list.vue'),
       meta: {
         title: '分销员管理',
       },
-      children:[]
+      children: []
     },
-     {
-      path: 'commission',  
+    {
+      path: 'commission',
       name: 'saleCommission',
-      component: () => import('@/views/sale/commission.vue'),  
+      component: () => import('@/views/sale/commission.vue'),
       meta: {
         title: '佣金明细',
       },
-      children:[]
+      children: []
     },
-     {
-      path: 'review',  
+    {
+      path: 'review',
       name: 'saleReview',
-      component: () => import('@/views/sale/review.vue'),  
+      component: () => import('@/views/sale/review.vue'),
       meta: {
         title: '分销员审核',
       },
-      children:[]
+      children: []
     },
     {
       path: 'settings',
-      name: 'saleSettings',  
+      name: 'saleSettings',
       component: () => import('@/views/sale/settings.vue'),
       meta: {
         title: '分销设置',
       },
-      children:[]
+      children: []
     },
   ],
 }

+ 2 - 1
src/router/routes.ts

@@ -22,6 +22,7 @@ import basics from './modules/basics.ts'
 import systemManage from './modules/system.ts'
 import consoleManage from './modules/console.ts' //数据报表
 import sale from './modules/sale.ts'//分销管理
+import partner from './modules/partner.ts'//合伙人管理
 // import {  } from "@/store/modules/user";
 // 固定路由(默认路由
 // console.log(useUserStore)
@@ -100,7 +101,7 @@ const asyncRoutes: Route.recordMainRaw[] = [
       title: "业务管理",
       icon: "i-uim:box",
     },
-    children: [operationManagement,sale],
+    children: [operationManagement,sale,partner],
   },
   {
     meta: {

+ 4 - 3
src/store/modules/route.ts

@@ -222,10 +222,11 @@ const useRouteStore = defineStore(
         console.log('第二个', JSON.parse(res.data.sysPerms))
         const userInfo = JSON.parse(localStorage.getItem('userInfo'))
         let routes = JSON.parse(res.data.sysConfig)
+
         if(userInfo) {
-          let arr = []
-          arr = filterTreeByPerms(routes, userInfo.auths)
-          routesRaw.value = converDeprecatedAttribute(formatBackRoutes(arr) as any)
+          // let arr = []
+          // arr = filterTreeByPerms(routes, userInfo.auths)//暂时去掉
+          routesRaw.value = converDeprecatedAttribute(formatBackRoutes(routes) as any)
           console.log('第三个', routesRaw.value)
         } else {
           routesRaw.value = converDeprecatedAttribute(formatBackRoutes(JSON.parse(res.data.sysConfig)) as any)

+ 19 - 18
src/views/additionalOrder/adjust/adjustRecord.vue

@@ -30,10 +30,10 @@ const columns: any = [
 	{
 		prop: "orderNo", label: "订单号", width: 200,
 	},
-	{ 
+	{
 		prop: "licenseNo", label: "车牌号", width: 100,
 	},
-	{ 
+	{
 		prop: "companyName", label: "保险公司", width: 200,
 	},
 	{
@@ -57,14 +57,14 @@ const columns: any = [
 			return { type: type, text: name };
 		}
 	},
-	{ 
+	{
 		prop: "type", label: "批改类型", width: 150,
 		formatter: (row: any) => {
 			let name = typeData.find(val => val.value == row.type)?.label;
 			return name;
 		}
 	},
-	{ 
+	{
 		prop: "changePremium", label: "保费变化", width: 150,
 		formatter: (row: any) => {
 			if (!row.afterPremium) {
@@ -74,16 +74,16 @@ const columns: any = [
 			return val > 0 ? `-¥${val}` : `¥${Math.abs(val)}`;
 		}
 	},
-	{ 
+	{
 		prop: "afterPremium", label: "批改后保费", width: 150,
 		formatter: (row: any) => {
 			return row.afterPremium ? `¥${row.afterPremium}` : '--';
 		}
 	},
-	{ 
+	{
 		prop: "createBy", label: "批改人", width: 150,
 	},
-	{ 
+	{
 		prop: "createTime", label: "批改时间", width: 200,
 	},
 ];
@@ -110,6 +110,7 @@ const fields = computed(() => {
 		},
 		{
 			label: "批改时间", model: "time", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+      format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
 			onChange: (value: any) => {
 				if (value) {
 					formInline.value.endDate = value[1];
@@ -151,9 +152,9 @@ onBeforeMount(async () => {
 // 分页数据
 const getData = () => {
 	const { time, ...params } = formInline.value;
-	api.insurancePolicyApi.adjustList({ 
-		pages: pageInfo.value.pageNum, 
-		size: pageInfo.value.pageSize, 
+	api.insurancePolicyApi.adjustList({
+		pages: pageInfo.value.pageNum,
+		size: pageInfo.value.pageSize,
 		...params
 	}).then((res: any) => {
 		if (res.code == '200') {
@@ -215,21 +216,21 @@ defineOptions({
 <template>
 	<PageMain class="vh100">
 		<SearchForm :isOffset="true"
-			:fields="fields" :formInline="formInline" 
-			:onSearch="searchForm" :onReset="resetForm" 
+			:fields="fields" :formInline="formInline"
+			:onSearch="searchForm" :onReset="resetForm"
 		/>
-		<ComplexTable 
-			:columns="columns" :columnwidth="200" 
+		<ComplexTable
+			:columns="columns" :columnwidth="200"
 			:showIndex="false" :showSelect="true"
-			:pageInfo="pageInfo" 
-			:tableData="tableData" 
-			@getList="getList" 
+			:pageInfo="pageInfo"
+			:tableData="tableData"
+			@getList="getList"
 			@selectionChange="selectionChange">
 			<template v-slot:table-title-btn>
 				<el-button class="radius-2px width-100" type="primary" :loading="exportLoading" @click="handleExport">导出</el-button>
 			</template>
 			<template v-slot:operation="scope">
-				<el-button type="primary" link 
+				<el-button type="primary" link
 					@click="toDetail(scope)">
 					详情
 				</el-button>

+ 2 - 0
src/views/externalAgreement/agreement/agreementIndex.vue

@@ -155,6 +155,7 @@ const fields = ref([
   },
   {
     label: "生效时间", model: "value1", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       formInline.takeStartDate = value[0];
       formInline.takeEndDate = value[1];
@@ -162,6 +163,7 @@ const fields = ref([
   },
   {
     label: "失效时间", model: "value2", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       formInline.loseStartDate = value[0];
       formInline.loseEndDate = value[1];

+ 2 - 0
src/views/externalAgreement/costManagement.vue

@@ -163,6 +163,7 @@ const fields = ref([
   },
   {
     label: "生效时间", model: "effectiveTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       console.log(value)
       formInline.effectiveTime = value;
@@ -170,6 +171,7 @@ const fields = ref([
   },
   {
     label: "失效时间", model: "failureTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       formInline.failureTime = value;
     }

+ 19 - 18
src/views/insurancePolicy/adjustRecord.vue

@@ -30,10 +30,10 @@ const columns: any = [
 	{
 		prop: "orderNo", label: "订单号", width: 200,
 	},
-	{ 
+	{
 		prop: "licenseNo", label: "车牌号", width: 100,
 	},
-	{ 
+	{
 		prop: "companyName", label: "保险公司", width: 200,
 	},
 	{
@@ -57,14 +57,14 @@ const columns: any = [
 			return { type: type, text: name };
 		}
 	},
-	{ 
+	{
 		prop: "type", label: "批改类型", width: 150,
 		formatter: (row: any) => {
 			let name = typeData.find(val => val.value == row.type)?.label;
 			return name;
 		}
 	},
-	{ 
+	{
 		prop: "changePremium", label: "保费变化", width: 150,
 		formatter: (row: any) => {
 			if (!row.afterPremium) {
@@ -74,16 +74,16 @@ const columns: any = [
 			return val > 0 ? `-¥${val}` : `¥${Math.abs(val)}`;
 		}
 	},
-	{ 
+	{
 		prop: "afterPremium", label: "批改后保费", width: 150,
 		formatter: (row: any) => {
 			return row.afterPremium ? `¥${row.afterPremium}` : '--';
 		}
 	},
-	{ 
+	{
 		prop: "createBy", label: "批改人", width: 150,
 	},
-	{ 
+	{
 		prop: "createTime", label: "批改时间", width: 200,
 	},
 ];
@@ -113,6 +113,7 @@ const fields = computed(() => {
 		},
 		{
 			label: "批改时间", model: "time", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+      format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
 			onChange: (value: any) => {
 				if (value) {
 					formInline.value.endDate = value[1];
@@ -154,9 +155,9 @@ onBeforeMount(async () => {
 // 分页数据
 const getData = () => {
 	const { time, ...params } = formInline.value;
-	api.insurancePolicyApi.adjustList({ 
-		pages: pageInfo.value.pageNum, 
-		size: pageInfo.value.pageSize, 
+	api.insurancePolicyApi.adjustList({
+		pages: pageInfo.value.pageNum,
+		size: pageInfo.value.pageSize,
 		...params
 	}).then((res: any) => {
 		if (res.code == '200') {
@@ -218,21 +219,21 @@ defineOptions({
 <template>
 	<PageMain class="vh100">
 		<SearchForm :isOffset="true"
-			:fields="fields" :formInline="formInline" 
-			:onSearch="searchForm" :onReset="resetForm" 
+			:fields="fields" :formInline="formInline"
+			:onSearch="searchForm" :onReset="resetForm"
 		/>
-		<ComplexTable 
-			:columns="columns" :columnwidth="200" 
+		<ComplexTable
+			:columns="columns" :columnwidth="200"
 			:showIndex="false" :showSelect="true"
-			:pageInfo="pageInfo" 
-			:tableData="tableData" 
-			@getList="getList" 
+			:pageInfo="pageInfo"
+			:tableData="tableData"
+			@getList="getList"
 			@selectionChange="selectionChange">
 			<template v-slot:table-title-btn>
 				<el-button class="radius-2px width-100" type="primary" :loading="exportLoading" @click="handleExport">导出</el-button>
 			</template>
 			<template v-slot:operation="scope">
-				<el-button type="primary" link 
+				<el-button type="primary" link
 					@click="toDetail(scope)">
 					详情
 				</el-button>

+ 1 - 0
src/views/operationManagement/modules/addOperation.vue

@@ -712,6 +712,7 @@ const disabledDateEnd = (time: Date) => {
 // 编辑的id
 let editId = ref('')
 const initEditData = (id, ids) => {
+  console.log(id,ids)
   if(ids) {
     editId.value = id
     api.operationApi.operationDetail(id).then(res => {

+ 848 - 0
src/views/partnerManagement/LevelRule.vue

@@ -0,0 +1,848 @@
+<!-- 模板区域 -->
+<template>
+  <div>
+    <PageMain style="padding: 20px;margin-bottom: 100px;">
+      <el-tabs v-model="activeName" @tab-click="handleClick">
+        <el-tab-pane label="等级一" name="level1">
+          <h5>等级规则</h5>
+          <el-form ref="formRef" :model="dataList[0]" label-width="80px" style="width: 800px;">
+            <el-form-item label="等级名称">
+              <el-input v-model="dataList[0].gradeName"></el-input>
+            </el-form-item>
+            <el-form-item label="升级策略">
+              <el-radio-group v-model="dataList[0].upgrade">
+                <el-radio disabled label="1">支持</el-radio>
+                <el-radio disabled label="2">不支持</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="保级策略">
+              <el-radio-group v-model="dataList[0].relegation">
+                <el-radio disabled label="1">支持</el-radio>
+                <el-radio disabled label="2">不支持</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-form>
+        </el-tab-pane>
+        <el-tab-pane label="等级二" name="level2">
+          <h5>等级规则</h5>
+          <el-form ref="formRef" :model="dataList[1]" label-width="80px">
+            <el-form-item label="等级名称">
+              <el-input v-model="dataList[1].gradeName" style="width: 800px;"></el-input>
+            </el-form-item>
+            <el-form-item label="升级策略">
+              <div class="flex f-c ">
+                <el-radio-group v-model="dataList[1].upgrade">
+                  <el-radio label="1">支持</el-radio>
+                  <el-radio label="2">不支持</el-radio>
+                </el-radio-group>
+                <el-form-item label="考核周期" class="m-top-10 spacing " v-if="dataList[1].upgrade === '1'">
+                  <el-radio-group v-model="dataList[1].cycle.cycle" class="flex f-c a-start">
+                    <el-radio label="1">不限期</el-radio>
+                    <el-radio label="2">
+                      <span class="mr-2">固定天数</span>
+                      成为该等级后,限期
+                      <el-input class="width" :disabled="['1', '3'].includes(dataList[1].cycle.cycle)"
+                        v-model="dataList[1].cycle.fixedDays" style="margin: 0 5px;" placeholder="请输入1~365的正整数"
+                        :maxlength="3">
+                        <template v-slot:append>天</template>
+                      </el-input>
+                    </el-radio>
+                    <el-radio label="3">
+                      <span class="mr-2">固定日期</span>
+                      <el-date-picker class="width" v-model="dataList[1].cycle.min"
+                        :disabled="['1', '2'].includes(dataList[1].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                      <span style="margin: 0 5px;">至</span>
+                      <el-date-picker class="width" v-model="dataList[1].cycle.max"
+                        :disabled="['1', '2'].includes(dataList[1].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                    </el-radio>
+                  </el-radio-group>
+                  <div class="m-btn-10  m-top-10" style="width: 100%;">
+                    在上个等级时,限期内,以下条件
+                    <el-select v-model="dataList[1].appraise" placeholder="请选择" style="width: 150px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    可升级成为该等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[1].requirement" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[1].gradeName}下属成员出单保费` :
+                        '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item label="考核规则" class="m-top-20 spacing " v-if="dataList[1].upgrade === '1'">
+                  <div class="m-btn-10   flex a-c">
+                    成为该等级后,
+                    <el-input class="width" v-model="dataList[1].khDays" style="margin: 0 5px;"
+                      placeholder="请输入1~365的正整数" :maxlength="3"></el-input>
+                    天内,以下条件
+                    <el-select v-model="dataList[1].relSatisfy" placeholder="请选择" style="width: 150px;margin: 0 5px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    即可保持该等级,否则降至上一等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[1].strategyArray" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[1].gradeName}下属成员出单保费` :
+                        '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <div class="flex a-c m-top-10">
+                  <el-checkbox v-model="dataList[1].fallTick"></el-checkbox>
+                  <span style="margin: 0 5px;">降级后,支付锁定金额的</span>
+                  <el-input class="width" v-model="dataList[1].fallAmount" style="margin: 0 5px;">
+                    <template v-slot:append>%</template></el-input>
+                  可解锁该等级
+                </div>
+              </div>
+            </el-form-item>
+          </el-form>
+        </el-tab-pane>
+        <el-tab-pane label="等级三" name="level3">
+          <h5>等级规则</h5>
+          <el-form ref="formRef" :model="dataList[2]" label-width="80px">
+            <el-form-item label="等级名称">
+              <el-input v-model="dataList[2].gradeName" style="width: 800px;"></el-input>
+            </el-form-item>
+            <el-form-item label="升级策略">
+              <div class="flex f-c ">
+                <el-radio-group v-model="dataList[2].upgrade">
+                  <el-radio label="1">支持</el-radio>
+                  <el-radio label="2">不支持</el-radio>
+                </el-radio-group>
+                <el-form-item label="考核周期" class="m-top-10 spacing " v-if="dataList[2].upgrade === '1'">
+                  <el-radio-group v-model="dataList[2].cycle.cycle" class="flex f-c a-start">
+                    <el-radio label="1">不限期</el-radio>
+                    <el-radio label="2">
+                      <span class="mr-2">固定天数</span>
+                      成为该等级后,限期
+                      <el-input class="width" :disabled="['1', '3'].includes(dataList[2].cycle.cycle)"
+                        v-model="dataList[2].cycle.fixedDays" style="margin: 0 5px;" placeholder="请输入1~365的正整数"
+                        :maxlength="3">
+                        <template v-slot:append>天</template>
+                      </el-input>
+                    </el-radio>
+                    <el-radio label="3">
+                      <span class="mr-2">固定日期</span>
+                      <el-date-picker class="width" v-model="dataList[2].cycle.min"
+                        :disabled="['1', '2'].includes(dataList[2].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                      <span style="margin: 0 5px;">至</span>
+                      <el-date-picker class="width" v-model="dataList[2].cycle.max"
+                        :disabled="['1', '2'].includes(dataList[2].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                    </el-radio>
+                  </el-radio-group>
+                  <div class="m-btn-10  m-top-10" style="width: 100%;">
+                    在上个等级时,限期内,以下条件
+                    <el-select v-model="dataList[2].appraise" placeholder="请选择" style="width: 150px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    可升级成为该等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[2].requirement" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[2].gradeName}下属成员出单保费`
+                        : '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item label="考核规则" class="m-top-20  spacing " v-if="dataList[2].upgrade === '1'">
+                  <div class="m-btn-10   flex a-c">
+                    成为该等级后,
+                    <el-input class="width" v-model="dataList[2].khDays" style="margin: 0 5px;"
+                      placeholder="请输入1~365的正整数" :maxlength="3"></el-input>
+                    天内,以下条件
+                    <el-select v-model="dataList[2].relSatisfy" placeholder="请选择" style="width: 150px;margin: 0 5px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    即可保持该等级,否则降至上一等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[2].strategyArray" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[2].gradeName}下属成员出单保费`
+                        : '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <div class="flex a-c m-top-10">
+                  <el-checkbox v-model="dataList[2].fallTick"></el-checkbox>
+                  <span style="margin: 0 5px;">降级后,支付锁定金额的</span>
+                  <el-input class="width" v-model="dataList[2].fallAmount" style="margin: 0 5px;">
+                    <template v-slot:append>%</template></el-input>
+                  可解锁该等级
+                </div>
+              </div>
+            </el-form-item>
+          </el-form>
+        </el-tab-pane>
+        <el-tab-pane label="等级四" name="level4">
+          <h5>等级规则</h5>
+          <el-form ref="formRef" :model="dataList[3]" label-width="80px">
+            <el-form-item label="等级名称">
+              <el-input v-model="dataList[3].gradeName" style="width: 800px;"></el-input>
+            </el-form-item>
+            <el-form-item label="升级策略">
+              <div class="flex f-c ">
+                <el-radio-group v-model="dataList[3].upgrade">
+                  <el-radio label="1">支持</el-radio>
+                  <el-radio label="2">不支持</el-radio>
+                </el-radio-group>
+                <el-form-item label="考核周期" class="m-top-10 spacing " v-if="dataList[3].upgrade === '1'">
+                  <el-radio-group v-model="dataList[3].cycle.cycle" class="flex f-c a-start">
+                    <el-radio label="1">不限期</el-radio>
+                    <el-radio label="2">
+                      <span class="mr-2">固定天数</span>
+                      成为该等级后,限期
+                      <el-input class="width" :disabled="['1', '3'].includes(dataList[3].cycle.cycle)"
+                        v-model="dataList[3].cycle.fixedDays" style="margin: 0 5px;" placeholder="请输入1~365的正整数"
+                        :maxlength="3">
+                        <template v-slot:append>天</template>
+                      </el-input>
+                    </el-radio>
+                    <el-radio label="3">
+                      <span class="mr-2">固定日期</span>
+                      <el-date-picker class="width" v-model="dataList[3].cycle.min"
+                        :disabled="['1', '2'].includes(dataList[3].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                      <span style="margin: 0 5px;">至</span>
+                      <el-date-picker class="width" v-model="dataList[3].cycle.max"
+                        :disabled="['1', '2'].includes(dataList[3].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                    </el-radio>
+                  </el-radio-group>
+                  <div class="m-btn-10  m-top-10" style="width: 100%;">
+                    在上个等级时,限期内,以下条件
+                    <el-select v-model="dataList[3].appraise" placeholder="请选择" style="width: 150px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    可升级成为该等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[3].requirement" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[3].gradeName}下属成员出单保费`
+                        : '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item label="考核规则" class=" m-top-20 spacing " v-if="dataList[3].upgrade === '1'">
+                  <div class="m-btn-10   flex a-c">
+                    成为该等级后,
+                    <el-input class="width" v-model="dataList[3].khDays" style="margin: 0 5px;"
+                      placeholder="请输入1~365的正整数" :maxlength="3"></el-input>
+                    天内,以下条件
+                    <el-select v-model="dataList[3].relSatisfy" placeholder="请选择" style="width: 150px;margin: 0 5px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    即可保持该等级,否则降至上一等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[3].strategyArray" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[3].gradeName}下属成员出单保费`
+                        : '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <div class="flex a-c m-top-10">
+                  <el-checkbox v-model="dataList[3].fallTick"></el-checkbox>
+                  <span style="margin: 0 5px;">降级后,支付锁定金额的</span>
+                  <el-input class="width" v-model="dataList[3].fallAmount" style="margin: 0 5px;">
+                    <template v-slot:append>%</template></el-input>
+                  可解锁该等级
+                </div>
+              </div>
+            </el-form-item>
+          </el-form>
+        </el-tab-pane>
+        <el-tab-pane label="等级五" name="level5">
+          <h5>等级规则</h5>
+          <el-form ref="formRef" :model="dataList[4]" label-width="80px">
+            <el-form-item label="等级名称">
+              <el-input v-model="dataList[4].gradeName" style="width: 800px;"></el-input>
+            </el-form-item>
+            <el-form-item label="升级策略">
+              <div class="flex f-c ">
+                <el-radio-group v-model="dataList[4].upgrade">
+                  <el-radio label="1">支持</el-radio>
+                  <el-radio label="2">不支持</el-radio>
+                </el-radio-group>
+                <el-form-item label="考核周期" class="m-top-10 spacing " v-if="dataList[4].upgrade === '1'">
+                  <el-radio-group v-model="dataList[4].cycle.cycle" class="flex f-c a-start">
+                    <el-radio label="1">不限期</el-radio>
+                    <el-radio label="2">
+                      <span class="mr-2">固定天数</span>
+                      成为该等级后,限期
+                      <el-input class="width" :disabled="['1', '3'].includes(dataList[4].cycle.cycle)"
+                        v-model="dataList[4].cycle.fixedDays" style="margin: 0 5px;" placeholder="请输入1~365的正整数"
+                        :maxlength="3">
+                        <template v-slot:append>天</template>
+                      </el-input>
+                    </el-radio>
+                    <el-radio label="3">
+                      <span class="mr-2">固定日期</span>
+                      <el-date-picker class="width" v-model="dataList[4].cycle.min"
+                        :disabled="['1', '2'].includes(dataList[4].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                      <span style="margin: 0 5px;">至</span>
+                      <el-date-picker class="width" v-model="dataList[4].cycle.max"
+                        :disabled="['1', '2'].includes(dataList[4].cycle.cycle)" type="date" placeholder="选择日期"
+                        value-format="YYYY-MM-DD">
+                      </el-date-picker>
+                    </el-radio>
+                  </el-radio-group>
+                  <div class="m-btn-10  m-top-10" style="width: 100%;">
+                    在上个等级时,限期内,以下条件
+                    <el-select v-model="dataList[4].appraise" placeholder="请选择" style="width: 150px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    可升级成为该等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[4].requirement" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[4].gradeName}下属成员出单保费`
+                        : '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item label="考核规则" class=" m-top-20 spacing " v-if="dataList[4].upgrade === '1'">
+                  <div class="m-btn-10   flex a-c">
+                    成为该等级后,
+                    <el-input class="width" v-model="dataList[4].khDays" style="margin: 0 5px;"
+                      placeholder="请输入1~365的正整数" :maxlength="3"></el-input>
+                    天内,以下条件
+                    <el-select v-model="dataList[4].relSatisfy" placeholder="请选择" style="width: 150px;margin: 0 5px;">
+                      <el-option label="全部满足" value="1"></el-option>
+                      <el-option label="满足任意一条" value="2"></el-option>
+                    </el-select>
+                    即可保持该等级,否则降至上一等级
+                  </div>
+                  <div class="flex f-c row">
+                    <div class="flex a-c mb-2" v-for="(item, index) in dataList[4].strategyArray" :key="index">
+                      <el-checkbox v-model="item.checked"></el-checkbox>
+                      <span style="margin: 0 10px;">{{ index === 0 ? '邀请合伙人达' : index === 1 ?
+                        `${dataList[4].gradeName}下属成员出单保费`
+                        : '自己的出单保费达' }}</span>
+                      <el-input class="width" v-model="item.min" style="margin: 0 5px;" placeholder="请输入">
+                        <template v-slot:append>{{ index ? '元' : '人' }}</template>
+                      </el-input>
+                    </div>
+                  </div>
+                </el-form-item>
+                <div class="flex a-c m-top-10">
+                  <el-checkbox v-model="dataList[4].fallTick"></el-checkbox>
+                  <span style="margin: 0 5px;">降级后,支付锁定金额的</span>
+                  <el-input class="width" v-model="dataList[4].fallAmount" style="margin: 0 5px;">
+                    <template v-slot:append>%</template></el-input>
+                  可解锁该等级
+                </div>
+              </div>
+            </el-form-item>
+          </el-form>
+        </el-tab-pane>
+      </el-tabs>
+    </PageMain>
+    <FixedActionBar>
+      <ElButton type="primary" @click="saveRule">
+        保存
+      </ElButton>
+    </FixedActionBar>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElForm } from 'element-plus'
+import api from '@/api';
+
+// 定义类型接口
+interface Requirement {
+  min: string
+  max: string
+  type: string
+  checked: boolean
+}
+
+interface StrategyArray {
+  min: string
+  max: string
+  checked: boolean
+  type: string
+  taskDays: number | null
+}
+
+interface Cycle {
+  min: string
+  max: string
+  cycle: string
+  fixedDays: string
+  type: string
+}
+
+interface DataItem {
+  upgrade: string
+  relegation?: string
+  grade: string
+  gradeName: string
+  strategy: string
+  appraise: string
+  relSatisfy: string
+  cycle: Cycle
+  requirement: Requirement[]
+  strategyArray: StrategyArray[]
+  fallTick: boolean
+  fallAmount: string
+  khDays: string
+  [key: string]: any
+}
+
+// 响应式数据
+const activeName = ref('level1')
+
+const dataList = reactive<DataItem[]>([
+  {
+    upgrade: '2', // 升级
+    relegation: '2', // 保级
+    grade: '1', // 等级
+    gradeName: '创始人',
+    strategy: '1',
+    appraise: '1',
+    relSatisfy: '1',
+    cycle: {
+      min: '',
+      max: '',
+      cycle: '1',
+      fixedDays: '',
+      type: '1'
+    },
+    requirement: [
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+
+    ],
+    strategyArray: [
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      }
+    ],
+    fallTick: false,
+    fallAmount: '',
+    khDays: ''
+  },
+  {
+    grade: '2', // 等级
+    gradeName: '管理人', // 等级名称
+    upgrade: '1', // 升级策略
+    strategy: '1', // 保级策略
+    appraise: '1', // 考核满足
+    relSatisfy: '1', // 保级满足
+    cycle: { // 考核周期
+      min: '',
+      max: '',
+      cycle: '1',
+      fixedDays: '',
+      type: '1'
+    },
+    requirement: [ // 考核条件
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      }
+    ],
+    strategyArray: [ // 保级策略
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      }
+    ],
+    fallTick: false,
+    fallAmount: '',
+    khDays: ''
+  },
+  {
+    grade: '3',
+    gradeName: '合伙人',
+    upgrade: '1',
+    strategy: '1',
+    appraise: '1',
+    relSatisfy: '1',
+    cycle: {
+      min: '',
+      max: '',
+      cycle: '1',
+      fixedDays: '',
+      type: '1'
+    },
+    requirement: [
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      }
+    ],
+    strategyArray: [
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      }
+    ],
+    fallTick: false,
+    fallAmount: '',
+    khDays: ''
+  },
+  {
+    grade: '4',
+    gradeName: '工作室',
+    upgrade: '1',
+    strategy: '1',
+    appraise: '1',
+    relSatisfy: '1',
+    cycle: {
+      min: '',
+      max: '',
+      cycle: '1',
+      fixedDays: '',
+      type: '1'
+    },
+    requirement: [
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      }
+    ],
+    strategyArray: [
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      }
+    ],
+    fallTick: false,
+    fallAmount: '',
+    khDays: ''
+  },
+  {
+    grade: '5',
+    gradeName: '团队长',
+    upgrade: '1',
+    strategy: '1',
+    appraise: '1',
+    relSatisfy: '1',
+    cycle: {
+      min: '',
+      max: '',
+      cycle: '1',
+      fixedDays: '',
+      type: '1'
+    },
+    requirement: [
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      },
+      {
+        min: '',
+        max: '',
+        type: '2',
+        checked: false,
+      }
+    ],
+    strategyArray: [
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      },
+      {
+        min: '',
+        max: '',
+        checked: false,
+        type: '3',
+        taskDays: null,
+      }
+    ],
+    fallTick: false,
+    fallAmount: '',
+    khDays: ''
+  }
+])
+
+// 生命周期函数
+onMounted(() => {
+  queryRule()
+})
+
+// 方法函数
+const handleClick = (tab: any, event: Event) => {
+  console.log(tab, event)
+  activeName.value = tab.props.name;
+
+}
+// 保存等级规则
+const saveRule = () => {
+  api.partnerApi.partnersaveRule(dataList).then((res: any) => {
+    if (res.code === '200') {
+      ElMessage({
+        type: 'success',
+        message: res.msg,
+      })
+      queryRule()
+    } else {
+      ElMessage({
+        type: 'error',
+        message: res.msg,
+      })
+    }
+  })
+}
+// 查询等级规则
+const queryRule = () => {
+  api.partnerApi.partnerqueryRule().then((res: any) => {
+    if (res.code === '200') {
+      // 合并数据,保持响应式
+      res.data.forEach((item: DataItem, index: number) => {
+        if (dataList[index]) {
+          // 深度合并
+          Object.keys(item).forEach(key => {
+            const k = key as keyof DataItem;
+            if (typeof item[k] === 'object' && item[k] !== null && !Array.isArray(item[k])) {
+              Object.assign(dataList[index][k] as any, item[k]);
+            } else {
+              dataList[index][k] = item[k];
+            }
+          });
+        }
+      })
+    } else {
+      ElMessage({
+        type: 'error',
+        message: res.msg,
+      })
+    }
+  })
+}
+</script>
+
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.spacing {
+  .el-radio {
+    margin-bottom: 10px;
+  }
+}
+
+.body {
+  padding: 20px 20px 60px;
+  box-sizing: border-box;
+}
+
+.width {
+  width: 220px;
+}
+
+.footer {
+  position: fixed;
+  bottom: 0;
+  right: 0;
+  background-color: #fff;
+  z-index: 9;
+  padding: 20px;
+  width: 100%;
+  box-sizing: border-box;
+  box-shadow: 0 0 1px 0 #ccc;
+  transition: all 0.1s, box-shadow 0.5s;
+}
+
+.row {
+  width: 800px;
+  background-color: #f2f2f2;
+  padding: 20px 20px 0;
+  box-sizing: border-box;
+  border-radius: 5px;
+}
+
+:deep(.el-form-item__content .el-input-group) {
+  vertical-align: unset;
+}
+</style>

+ 153 - 0
src/views/partnerManagement/commissionChangeLog.vue

@@ -0,0 +1,153 @@
+<!-- 模板区域 -->
+<template>
+  <div>
+    <PageMain class="vh100 flex-1 overflow-hidden flex flex-col">
+      <SearchForm :fields="fields" :formInline="formInline" :onSearch="findpage" :onReset="resetForm" />
+      <div class="flex-1 overflow-auto">
+        <ComplexTable :tableData="tableData" :columns="columns" :showIndex="false" :columnwidth="250"
+          :showOperation="false" :showSelect="false" :pageInfo="pageInfo" @getList="getList">
+          <template v-slot:search="scope">
+            {{ scope.slotData.label }}
+          </template>
+        </ComplexTable>
+      </div>
+    </PageMain>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onBeforeMount } from 'vue'
+import api from '@/api'
+// 页面加载时获取机构列表
+onBeforeMount(() => {
+  
+  findpage();
+});
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+// 机构树相关变量
+const tableData = ref([]);//表格数据
+const formInline = reactive({
+  name: "",
+  mobile: "",
+  userId: "",
+  userGrade: "",
+  changeTimes: [],//变更时间
+})
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 20,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const gradeOptions = ref([
+  {
+    label: '创始人',
+    value: '1'
+  },
+  {
+    label: '管理人',
+    value: '2'
+  },
+  {
+    label: '合伙人',
+    value: '3'
+  }, {
+    label: '工作室',
+    value: '4'
+  }, {
+    label: '团队长',
+    value: '5'
+  },
+  {
+    label: '业务员',
+    value: '6'
+  },
+])
+//表格字段数据
+const fields = ref([
+  { label: "姓名", model: "name", type: "input", placeholder: "请输入姓名" },
+  {
+    label: "手机号", model: "mobile", type: "input", placeholder: "请输入手机号"
+  },
+  {
+    label: "工号", model: "userId", type: "input", placeholder: "请输入工号"
+  },
+  {
+    label: "等级", model: "grade", type: "select", placeholder: "选择等级", options: gradeOptions.value
+  },
+  {
+    label: "变更时间", model: "changeTimes", type: "date", dateType: "daterange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD", valueFormat: "YYYY-MM-DD",
+  },
+]);
+const columns = [
+  { prop: "name", label: "姓名", },
+  { prop: "mobile", label: "手机号", width: '200' },
+  { prop: "userId", label: "工号", width: '200' },
+  { prop: "deptName", label: "所属机构", width: '200' },
+  {
+    prop: "userGrade", label: "用户等级", width: '200',
+    formatter: (row: any) => {
+      if (!['1', '2', '3', '4'].includes(row.userGrade)) {
+        return '出单员';
+      } else {
+        return gradeOptions.value.find((item: any) => item.value === row.userGrade)?.label || '未知等级';
+      }
+    }
+  },
+  { prop: "originalCommission", label: "原佣金", width: '200' },
+  { prop: "afterChange", label: "变更后佣金", width: '200' },
+  { prop: "changeReason", label: "变更原因", width: '200' },
+  { prop: "changeTime", label: "变更时间", width: '200' },
+];
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  findpage();
+
+};
+const resetForm = () => {
+  findpage();
+}
+//数据查询
+function findpage() {
+  let query = { ...formInline }
+  api.partnerApi.kickbackChangeQueryPage({ pages: pageInfo.value.pageNum, size: pageInfo.value.pageSize, ...query }).then((res: any) => {
+    if (res.code == '200') {
+      tableData.value = res.data.records;
+      pageInfo.value.pageNum = res.data.current;
+      pageInfo.value.pageSize = res.data.size;
+      pageInfo.value.total = res.data.total;
+    } else {
+    }
+  });
+}
+
+</script>
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+:deep(.el-dropdown-link) {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+}
+</style>

+ 148 - 0
src/views/partnerManagement/commissionDetails.vue

@@ -0,0 +1,148 @@
+<!-- 模板区域 -->
+<template>
+  <div>
+    <PageMain class="vh100 flex-1 overflow-hidden flex flex-col">
+      <SearchForm :fields="fields" :formInline="formInline" :onSearch="findpage" :onReset="resetForm" />
+      <div class="flex-1 overflow-auto">
+        <ComplexTable :tableData="tableData" :columns="columns" :showIndex="false" :columnwidth="250"
+          :showOperation="false" :showSelect="false" :pageInfo="pageInfo" @getList="getList">
+          <template v-slot:search="scope">
+            {{ scope.slotData.label }}
+          </template>
+        </ComplexTable>
+      </div>
+    </PageMain>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onBeforeMount } from 'vue'
+import api from '@/api'
+// 页面加载时获取机构列表
+onBeforeMount(() => {
+  getGradeOptions();
+  findpage();
+});
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+// 机构树相关变量
+const tableData = ref([]);//表格数据
+const userGradeList = ref()
+
+const formInline = reactive({
+  userName: "",//姓名
+  mobile: "",//手机号
+  userId: "",//工号
+  source: "",//等级
+  orderno: "",//订单号
+  licenseno: "",//车牌号
+  signingTime: [],
+})
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 20,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+
+//表格字段数据
+const fields = ref([
+  { label: "姓名", model: "userName", type: "input", placeholder: "请输入姓名" },
+  {
+    label: "手机号", model: "mobile", type: "input", placeholder: "请输入手机号"
+  },
+  {
+    label: "工号", model: "userId", type: "input", placeholder: "请输入工号"
+  },
+  {
+    label: "等级", model: "source", type: "select", placeholder: "选择等级", options: userGradeList.value
+  },
+  {
+    label: "订单号", model: "orderno", type: "input", placeholder: "请输入订单号"
+  },
+  {
+    label: "车牌号", model: "licenseno", type: "input", placeholder: "请输入车牌号"
+  },
+  {
+    label: "签单时间", model: "signingTime", type: "date", dateType: "daterange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD", valueFormat: "YYYY-MM-DD",
+  },
+]);
+const columns = [
+  { prop: "orderno", label: "订单号", },
+  { prop: "licenseno", label: "车牌号", width: '200' },
+  { prop: "sumpremium", label: "保费", width: '200' },
+  { prop: "createTime", label: "签单时间", width: '200' },
+  {
+    prop: "source", label: "等级", width: '200',
+    formatter: (row: any) => {
+      if (!['1', '2', '3', '4'].includes(row.source)) {
+        return '出单员';
+      } else {
+        return  userGradeList.value.find((item: any) => item.grade === row.source)?.gradeName || '未知等级';
+      }
+    }
+  },
+  { prop: "proportional", label: "佣金比例", width: '200' },
+  { prop: "extractFee", label: "佣金", width: '200' },
+  { prop: "userName", label: "姓名", width: '200' },
+  { prop: "mobile", label: "手机号", width: '200' },
+  { prop: "userId", label: "工号", width: '200' },
+];
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  findpage();
+
+};
+const resetForm = () => {
+  findpage();
+}
+//数据查询
+function findpage() {
+  let query = { ...formInline }
+  api.partnerApi.commissionDetailsPage({ pages: pageInfo.value.pageNum, size: pageInfo.value.pageSize, ...query }).then((res: any) => {
+    if (res.code == '200') {
+      tableData.value = res.data.records;
+      pageInfo.value.pageNum = res.data.current;
+      pageInfo.value.pageSize = res.data.size;
+      pageInfo.value.total = res.data.total;
+    } else {
+    }
+  });
+}
+// 获取人员等级列表
+const getGradeOptions = () => {
+  api.partnerApi.queryGradeName().then((res: any) => {
+    if (res.code === 200) {
+      userGradeList.value = res.data;
+    }
+  })
+}
+</script>
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+:deep(.el-dropdown-link) {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+}
+</style>

+ 430 - 0
src/views/partnerManagement/commissionRule.vue

@@ -0,0 +1,430 @@
+<!-- 模板区域 -->
+<template>
+  <div>
+    <PageMain style="padding: 20px;margin-bottom: 100px;">
+      <h5>佣金规则</h5>
+      <el-form ref="ruleFormRef" :model="rulefrom" label-width="150px" :rules="rules" style="max-width: 1000px">
+        <el-form-item label="创始人佣金比例" prop="originator">
+          <el-input v-model="rulefrom.originator" class="width"></el-input>
+        </el-form-item>
+        <el-form-item label="管理人佣金比例" prop="originator">
+          <div class="flex f-c a-start">
+            <div class="flex ">
+              <el-form-item label="管理人与合伙人共享" prop="administrator.sharedRatio">
+                <el-input v-model="rulefrom.administrator.sharedRatio"></el-input>
+              </el-form-item>
+              <el-form-item label="管理人默认佣金比例" class="ml-1" prop="administrator.defaultRatio">
+                <el-input v-model="rulefrom.administrator.defaultRatio"></el-input>
+              </el-form-item>
+            </div>
+            <el-form-item label="佣金有效期" class="m-top-20 spacing " label-width="100px"
+              prop="administrator.validityPeriod">
+              <el-radio-group v-model="rulefrom.administrator.validityPeriod" class="flex f-c a-start">
+                <el-radio label="1">不限期</el-radio>
+                <el-radio label="2">
+                  <div class="flex a-c">
+                    <span class="mr-2">固定天数</span>
+                    <el-form-item v-if="rulefrom.administrator.validityPeriod === '2'" label=" 成为该等级后,限期"
+                      prop="administrator.fixedDays">
+                      <el-input class="width" v-model="rulefrom.administrator.fixedDays" style="margin: 0 5px;"
+                        placeholder="请输入1~365的正整数" :maxlength="3">
+                        <template v-slot:append>天</template>
+                      </el-input>
+                    </el-form-item>
+                  </div>
+                </el-radio>
+                <el-radio label="3">
+                  <div class="flex a-c">
+                    <span>固定日期</span>
+                    <div class="flex a-c" v-if="rulefrom.administrator.validityPeriod === '3'">
+                      <el-form-item label="成为该等级后,限期" label-width="200px" prop="administrator.startDate">
+                        <el-date-picker class="width" v-model="rulefrom.administrator.startDate"
+                          :disabled="['1', '2'].includes(rulefrom.administrator.validityPeriod)" type="date"
+                          placeholder="选择日期" value-format="yyyy-MM-dd">
+                        </el-date-picker>
+                      </el-form-item>
+                      <span style="margin: 0 5px;">至</span>
+                      <el-form-item prop="administrator.endDate">
+                        <el-date-picker class="width" v-model="rulefrom.administrator.endDate"
+                          :disabled="['1', '2'].includes(rulefrom.administrator.validityPeriod)" type="date"
+                          placeholder="选择日期" value-format="yyyy-MM-dd">
+                        </el-date-picker>
+                      </el-form-item>
+                    </div>
+                  </div>
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <div class="row flex f-c " v-for="(ruleitem, ruleindex) in rulefrom.administrator.rulesRatioList"
+              :key="ruleindex">
+              <div class="flex j-s a-c">
+                <span>合伙人佣金-阶梯{{ Number(ruleindex) + 1 }}</span>
+                <span v-if="ruleindex != 0" class="cursor" @click="del('administrator', ruleindex)">删除</span>
+              </div>
+              <div class="flex f-c ">
+                <div class="flex a-c mb-4" v-for="(item, index) in ruleitem.partnerRatioList" :key="index">
+                  <!-- 复选框 -->
+                  <el-checkbox v-if="index == 0" v-model="item.ry"
+                    @change="handleCheckboxChange(ruleindex, index, 'administrator')"></el-checkbox>
+                  <el-checkbox v-if="index == 1" v-model="item.bf"
+                    @change="handleCheckboxChange(ruleindex, index, 'administrator')"></el-checkbox>
+                  <el-checkbox v-if="index == 2" v-model="item.gr"
+                    @change="handleCheckboxChange(ruleindex, index, 'administrator')"></el-checkbox>
+                  <span style="margin: 0 10px;">{{ index == 0 ?
+                    `人员考核&nbsp;&nbsp;&nbsp;&nbsp;邀请工作室达` : index == 1 ? `保费考核&nbsp;&nbsp;&nbsp;&nbsp;下属工作室出单保费` :
+                      `保费考核&nbsp;&nbsp;&nbsp;&nbsp;自己的出单费用`
+                  }}</span>
+                  <!-- 输入框 -->
+                  <el-form-item :prop="`administrator.rulesRatioList.${ruleindex}.partnerRatioList.${index}.min`"
+                    :rules="getRules(ruleindex, index, 'min', 'administrator')">
+                    <el-input-number v-model="item.min" controls-position="right" :min="1"
+                      :max="index ? 100000000 : 10000" :precision="index ? 2 : 0"
+                      style="margin: 0 5px;width: 200px;"></el-input-number>
+                    <span>{{ index ? '元' : '人' }}</span>
+                  </el-form-item>
+                </div>
+                <div class="flex a-c">
+                  以上条件
+                  <el-form-item :prop="`administrator.rulesRatioList.${ruleindex}.allSatisfied`"
+                    :rules="rules.allSatisfied">
+                    <el-select v-model="ruleitem.allSatisfied" placeholder="请选择" class="width">
+                      <el-option label="全部满足" :value="1"></el-option>
+                      <el-option label="满足任意一条" :value="2"></el-option>
+                    </el-select>
+                  </el-form-item>
+                  合伙人获取共享佣金的
+                  <el-form-item :prop="`administrator.rulesRatioList.${ruleindex}.kickback`" :rules="rules.kickback">
+                    <el-input class="width" v-model="ruleitem.kickback" style="margin: 0 5px;" placeholder="请输入">
+                      <template v-slot:append>%</template>
+                    </el-input>
+                  </el-form-item>
+                </div>
+              </div>
+            </div>
+            <span class="cursor"
+              v-if="rulefrom.administrator.rulesRatioList && rulefrom.administrator.rulesRatioList.length < 5"
+              @click="rulesAdd('administrator')">添加</span>
+          </div>
+        </el-form-item>
+        <el-form-item label="合伙人佣金比例" prop="originator">
+          <div class="flex f-c a-start">
+            <div class="flex ">
+              <el-form-item label="合伙人与工作室共享" prop="partner.sharedRatio">
+                <el-input v-model="rulefrom.partner.sharedRatio"></el-input>
+              </el-form-item>
+              <el-form-item label="合伙人默认佣金比例" class="ml-1" prop="partner.defaultRatio">
+                <el-input v-model="rulefrom.partner.defaultRatio"></el-input>
+              </el-form-item>
+            </div>
+            <el-form-item label="佣金有效期" class="m-top-20 spacing " prop="partner.validityPeriod">
+              <el-radio-group v-model="rulefrom.partner.validityPeriod" class="flex f-c a-start">
+                <el-radio label="1">不限期</el-radio>
+                <el-radio label="2">
+                  <div class="flex a-c">
+                    <span class="mr-2">固定天数</span>
+                    <el-form-item v-if="rulefrom.partner.validityPeriod === '2'" label=" 成为该等级后,限期"
+                      prop="partner.fixedDays">
+                      <el-input class="width" v-model="rulefrom.partner.fixedDays" type="number" style="margin: 0 5px;"
+                        placeholder="请输入1~365的正整数" :maxlength="3">
+                        <template v-slot:append>天</template>
+                      </el-input>
+                    </el-form-item>
+                  </div>
+                </el-radio>
+                <el-radio label="3">
+                  <div class="flex a-c">
+                    <span>固定日期</span>
+                    <div class="flex a-c" v-if="rulefrom.partner.validityPeriod === '3'">
+                      <el-form-item label="成为该等级后,限期" label-width="200px" prop="partner.startDate">
+                        <el-date-picker class="width" v-model="rulefrom.partner.startDate"
+                          :disabled="['1', '2'].includes(rulefrom.partner.validityPeriod)" type="date"
+                          placeholder="选择日期" value-format="yyyy-MM-dd">
+                        </el-date-picker>
+                      </el-form-item>
+                      <span style="margin: 0 5px;">至</span>
+                      <el-form-item prop="partner.endDate">
+                        <el-date-picker class="width" v-model="rulefrom.partner.endDate"
+                          :disabled="['1', '2'].includes(rulefrom.partner.validityPeriod)" type="date"
+                          placeholder="选择日期" value-format="yyyy-MM-dd">
+                        </el-date-picker>
+                      </el-form-item>
+                    </div>
+                  </div>
+
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <div class="row flex f-c " v-for="(ruleitem, ruleindex) in rulefrom.partner.rulesRatioList" :key="ruleindex">
+            <div class="flex j-s a-c">
+              <span>工作室佣金-阶梯{{ Number(ruleindex) + 1 }}</span>
+              <span v-if="ruleindex != 0" class="cursor" @click="del('partner', ruleindex)">删除</span>
+            </div>
+            <div class="flex f-c ">
+              <div class="flex a-c mb-2" v-for="(item, index) in ruleitem.partnerRatioList" :key="index">
+                <!-- 复选框 -->
+                <el-checkbox v-if="index==0" v-model="item.ry"
+                  @change="handleCheckboxChange(ruleindex, index, 'partner')"></el-checkbox>
+                <el-checkbox v-if="index==1" v-model="item.bf"
+                  @change="handleCheckboxChange(ruleindex, index, 'partner')"></el-checkbox>
+                  <el-checkbox v-if="index==2" v-model="item.gr"
+                  @change="handleCheckboxChange(ruleindex, index, 'partner')"></el-checkbox>
+                <span style="margin: 0 10px;">{{ index == 0 ?
+                  `人员考核&nbsp;&nbsp;&nbsp;&nbsp;邀请团队达` : index == 1 ? `保费考核&nbsp;&nbsp;&nbsp;&nbsp;下属团队出单保费` : `保费考核&nbsp;&nbsp;&nbsp;&nbsp;自己的出单费用`
+                }}</span>
+                <!-- 输入框 -->
+                <el-form-item :prop="`partner.rulesRatioList.${ruleindex}.partnerRatioList.${index}.min`"
+                  :rules="getRules(ruleindex, index, 'min', 'partner')">
+                  <el-input-number v-model="item.min"  controls-position="right" :min="1"
+                    :max="index ? 100000000 : 10000" :precision="index ? 2 : 0"
+                    style="margin: 0 5px;width: 200px;"></el-input-number>
+                  <span>{{ index ? '元' : '人' }}</span>
+                </el-form-item>
+              </div>
+              <div class="flex a-c">
+                以上条件
+                <el-form-item :prop="`partner.rulesRatioList.${ruleindex}.allSatisfied`" :rules="rules.allSatisfied">
+                  <el-select v-model="ruleitem.allSatisfied" placeholder="请选择" class="width">
+                    <el-option label="全部满足" :value="1"></el-option>
+                    <el-option label="满足任意一条" :value="2"></el-option>
+                  </el-select>
+                </el-form-item>
+                工作室获取共享佣金的
+                <el-form-item :prop="`partner.rulesRatioList.${ruleindex}.kickback`" :rules="rules.kickback">
+                  <el-input class="width" v-model="ruleitem.kickback"  style="margin: 0 5px;"
+                    placeholder="请输入">
+                    <template v-slot:append>%</template>
+                  </el-input>
+                </el-form-item>
+              </div>
+            </div>
+          </div>
+          <span class="cursor" v-if="rulefrom.partner.rulesRatioList && rulefrom.partner.rulesRatioList.length < 5"
+            @click="rulesAdd('partner')">添加</span>
+          </div>
+        </el-form-item>
+      </el-form>
+    </PageMain>
+    <FixedActionBar>
+      <ElButton type="primary">
+        保存
+      </ElButton>
+    </FixedActionBar>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onMounted } from 'vue'
+import { FormRules, FormInstance, ElMessage } from 'element-plus';
+
+import api from '@/api';
+onMounted(() => {
+  Query();
+})
+interface DataItem {
+  [key: string]: any
+}
+const ruleFormRef = ref()
+const rulefrom = reactive<DataItem>({
+  administrator: {},
+  originator: "",
+  partner: {},
+})
+const rules = ref<FormRules>({
+  originator: [
+    { required: true, message: '请输入创始人佣金比例', trigger: 'blur' },
+  ],
+  'administrator.sharedRatio': [
+    { required: true, message: '请输入管理人与合伙人共享比例', trigger: 'blur' }
+  ],
+  'administrator.defaultRatio': [
+    { required: true, message: '请输入管理人默认佣金比例', trigger: 'blur' }
+  ],
+  'administrator.validityPeriod': [
+    { required: true, message: '请选择佣金有效期', trigger: 'change' }
+  ],
+  'administrator.fixedDays': [
+    { required: true, message: '请输入固定天数', trigger: 'blur' },
+    { type: 'number', message: '必须为数字', trigger: 'blur', transform: (value) => Number(value) },
+    {
+      validator: (rule, value, callback) => {
+        if (value < 1 || value > 365 || !Number.isInteger(value)) {
+          callback(new Error('必须是1-365的整数'));
+        } else {
+          callback();
+        }
+      },
+      trigger: 'blur'
+    }
+  ],
+  'administrator.startDate': [
+    { required: true, message: '请选择开始日期', trigger: 'change' }
+  ],
+  'administrator.endDate': [
+    { required: true, message: '请选择结束日期', trigger: 'change' }
+  ],
+  'partner.sharedRatio': [
+    { required: true, message: '请输入管理人与合伙人共享比例', trigger: 'blur' }
+  ],
+  'partner.defaultRatio': [
+    { required: true, message: '请输入管理人默认佣金比例', trigger: 'blur' }
+  ],
+  'partner.validityPeriod': [
+    { required: true, message: '请选择佣金有效期', trigger: 'change' }
+  ],
+  'partner.fixedDays': [
+    { required: true, message: '请输入固定天数', trigger: 'blur' },
+    { type: 'number', message: '必须为数字', trigger: 'blur', transform: (value) => Number(value) },
+
+    {
+      validator: (rule, value, callback) => {
+        if (value < 1 || value > 365 || !Number.isInteger(value)) {
+          callback(new Error('必须是1-365的整数'));
+        } else {
+          callback();
+        }
+      },
+      trigger: 'blur'
+    }
+  ],
+  'partner.startDate': [
+    { required: true, message: '请选择开始日期', trigger: 'change' }
+  ],
+  'partner.endDate': [
+    { required: true, message: '请选择结束日期', trigger: 'change' }
+  ],
+  min: [
+    { required: true, message: '请输入最小值', trigger: 'blur' },
+    { type: 'number', message: '必须为数字', trigger: 'blur', transform: (value) => Number(value) }
+  ],
+  allSatisfied: [
+    { required: true, message: '请选择条件', trigger: 'change' }
+  ],
+  kickback: [
+    { required: true, message: '请输入佣金比例', trigger: 'blur' },
+    { type: 'number', message: '必须为数字', trigger: 'blur', transform: (value) => Number(value) }
+  ]
+})
+const Query = () => {
+  api.partnerApi.commissionQuery().then((res: any) => {
+    if (res.code == '200') {
+      Object.assign(rulefrom, res.data);
+      console.log(rulefrom)
+    } else {
+      ElMessage({
+        type: 'error',
+        message: res.msg,
+      });
+    }
+  });
+}
+// 处理复选框变化
+const handleCheckboxChange = (ruleindex:any, index:any, typename:any) => {
+  // 手动触发表单校验
+  ruleFormRef.value.validateField([
+    `${typename}.rulesRatioList.${ruleindex}.partnerRatioList.${index}.min`,
+  ]);
+}
+// 动态获取校验规则
+const getRules = (ruleindex:any, index:any, field:any, typename:any) => {
+  const item = rulefrom[typename].rulesRatioList[ruleindex].partnerRatioList[index];
+  const isRequired = index == 0 ? item.ry : index == 1 ? item.bf : item.gr; // 根据复选框决定是否必填
+
+  // 动态生成规则数组
+  const rules = [];
+
+  // 如果必填,添加 required 规则
+  if (isRequired) {
+    rules.push({
+      required: true,
+      message: `请输入${field === 'min' ? '最小值' : '最大值'}`,
+      trigger: 'blur',
+    });
+  }
+
+  // 如果有值,则校验是否为数字
+  rules.push({
+    validator: (rule:any, value:any, callback:any) => {
+      if (value !== null && value !== undefined && value !== '') {
+        if (isNaN(Number(value))) {
+          callback(new Error('必须为数字'));
+        } else {
+          callback();
+        }
+      } else {
+        callback();
+      }
+    },
+    trigger: 'blur',
+  });
+
+  return rules;
+}
+// 删除规则
+const del = (Name:any, index:any) => {
+  rulefrom[Name].rulesRatioList.splice(index, 1)
+}
+// 添加规则
+const rulesAdd = (Name:any) => {
+  const info = rulefrom[Name].rulesRatioList[rulefrom[Name].rulesRatioList.length - 1]
+  // console.log(this.from[Name].rulesRatioList[this.from[Name].rulesRatioList.length - 1])
+  if (info.partnerRatioList[0].min) {
+    rulefrom[Name].rulesRatioList.push({
+      allSatisfied: "",
+      kickback: "",
+      partnerRatioList: [
+        {
+          bf: false,
+          ry: false,
+          gr: false,
+          min: info.partnerRatioList[0].min + 1,
+        },
+        {
+          bf: false,
+          ry: false,
+          gr: false,
+          min: info.partnerRatioList[1].min + 1,
+        },
+        {
+          bf: false,
+          ry: false,
+          gr: false,
+          min: info.partnerRatioList[1].min + 1,
+        }
+      ]
+    })
+  } else {
+    ElMessage({
+      type: 'error',
+      message: '请先将最小值补充完整',
+    });
+  }
+
+}
+</script>
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.spacing {
+  .el-radio {
+    margin-bottom: 10px;
+  }
+}
+
+.cursor {
+  color: #2680F0;
+  cursor: pointer;
+}
+
+.width {
+  width: 220px;
+}
+
+.row {
+  background-color: #f2f2f2;
+  padding: 6px 20px;
+  box-sizing: border-box;
+  width: 100%;
+  border-radius: 5px;
+  margin-bottom: 10px;
+}
+</style>

+ 134 - 0
src/views/partnerManagement/expiredCommission.vue

@@ -0,0 +1,134 @@
+<!-- 模板区域 -->
+<template>
+  <div>
+    <PageMain class="vh100 flex-1 overflow-hidden flex flex-col">
+      <SearchForm :fields="fields" :formInline="formInline" :onSearch="findpage" :onReset="resetForm" />
+      <div class="flex-1 overflow-auto">
+        <ComplexTable :tableData="tableData" :columns="columns" :showIndex="false" :columnwidth="250"
+          :showOperation="false" :showSelect="false" :pageInfo="pageInfo" @getList="getList">
+          <template v-slot:search="scope">
+            {{ scope.slotData.label }}
+          </template>
+        </ComplexTable>
+      </div>
+    </PageMain>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onBeforeMount } from 'vue'
+import api from '@/api'
+// 页面加载时获取机构列表
+onBeforeMount(() => {
+  getGradeOptions();
+  findpage();
+});
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+// 机构树相关变量
+const tableData = ref([]);//表格数据
+const userGradeList = ref()
+const formInline = reactive({
+  name: "",
+  mobile: "",
+  userId: "",
+  startTime: [],//变更时间
+})
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 20,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+//表格字段数据
+const fields = ref([
+  { label: "姓名", model: "name", type: "input", placeholder: "请输入姓名" },
+  {
+    label: "手机号", model: "mobile", type: "input", placeholder: "请输入手机号"
+  },
+  {
+    label: "工号", model: "userId", type: "input", placeholder: "请输入工号"
+  },
+  {
+    label: "过期时间", model: "changeTimes", type: "date", dateType: "daterange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD", valueFormat: "YYYY-MM-DD",
+  },
+]);
+const columns = [
+  { prop: "name", label: "姓名", },
+  { prop: "mobile", label: "手机号", width: '200' },
+  { prop: "userId", label: "工号", width: '200' },
+  { prop: "deptName", label: "所属机构", width: '200' },
+  {
+    prop: "grade", label: "降级前", width: '200',
+    formatter: (row: any) => {
+      return userGradeList.value?.find((item: any) => item.grade === row.grade)?.gradeName || '未知等级';
+    }
+  },
+  {
+    prop: "gradeAfter", label: "降级后", width: '200',
+    formatter: (row: any) => {
+      return userGradeList.value?.find((item: any) => item.grade === row.gradeAfter)?.gradeName || '未知等级';
+    }
+  },
+  { prop: "lockCommission", label: "锁定佣金", width: '200' },
+  { prop: "downgradeTime", label: "降级时间", width: '200' },
+  { prop: "expiration", label: "过期时间", width: '200' },
+];
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  findpage();
+
+};
+const resetForm = () => {
+  findpage();
+}
+//数据查询
+function findpage() {
+  let query = { ...formInline }
+  api.partnerApi.expiredCommissionPage({ pages: pageInfo.value.pageNum, size: pageInfo.value.pageSize, ...query }).then((res: any) => {
+    if (res.code == '200') {
+      tableData.value = res.data.records;
+      pageInfo.value.pageNum = res.data.current;
+      pageInfo.value.pageSize = res.data.size;
+      pageInfo.value.total = res.data.total;
+    } else {
+    }
+  });
+}
+// 获取人员等级列表
+const getGradeOptions = () => {
+  api.partnerApi.queryGradeName().then((res: any) => {
+    if (res.code === 200) {
+      userGradeList.value = res.data;
+    }
+  })
+}
+</script>
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+:deep(.el-dropdown-link) {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+}
+</style>

+ 1643 - 0
src/views/partnerManagement/modules/addPartner.vue

@@ -0,0 +1,1643 @@
+<template>
+  <div>
+    <el-form :model="operationForm" ref="OperationFormRef" :rules="operationRules" label-width="120">
+      <el-descriptions title="基本信息">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="grade" label="合伙人等级">
+                  <el-select v-model="operationForm.gradeList" :disabled="editId" placeholder="请选择合伙人等级" multiple
+                    @change="handleGradeChange">
+                    <el-option v-for="item in userGradeList" :key="item.grade" :value="item.grade"
+                      :label="item.gradeName"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item label="上级推荐人" :prop="mingrade == 1 ? '' : 'referrerId'">
+                  <el-select v-model="operationForm.referrerId" filterable
+                    :disabled="!operationForm.gradeList || operationForm.gradeList.includes('1') || editId" placeholder="请选择上级推荐人"
+                    @focus="searchRecommend" @change="handleReferrerChange">
+                    <el-option v-for="item in referrerList" :key="item.userId" :value="item.userId" :label="item.name">
+                      <span>{{ item.name }}-</span>
+                      <span> {{ item.mobile }}-</span>
+                      <span class="typeAttrMap mr-1" v-for="typeAttritem in typeAttrMap(item.typeAttr)"
+                        :key="typeAttritem">{{ typeAttritem }}</span>
+                    </el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="name" label="姓名">
+                  <el-input v-model="operationForm.name" placeholder="请填写姓名" maxlength="20"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="mobile" label="手机号">
+                  <el-input type="text" :maxlength="11" :disabled="editId" show-word-limit v-model="operationForm.mobile"
+                    placeholder="请填写手机号" @input="mobileInput"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="deptId" label="所属机构">
+                  <el-cascader style="width: 100%" v-model="operationForm.deptId" :disabled="editId || disabledProperty"
+                    placeholder="请选择所属机构" :options="deptOption" :props="optionProps"
+                    @change="deptIdChange"></el-cascader>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="identity" label="证件号">
+                  <el-input v-model="operationForm.identity" placeholder="请填写身份证号"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="identityTimeStart" label="证件有效期始">
+                  <el-date-picker v-model="operationForm.identityTimeStart" type="date" placeholder="请选择"
+                    format="YYYY-MM-DD" value-format="YYYY-MM-DD" :disabled-date="disabledDateStart"
+                    style="width: 100%" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="identityTimeEnd" label="证件有效期止">
+                  <el-date-picker v-model="operationForm.identityTimeEnd" type="date" placeholder="请选择"
+                    format="YYYY-MM-DD" value-format="YYYY-MM-DD" :disabled-date="disabledDateEnd"
+                    style="width: 100%" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="其他信息">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="leaderId" label="管理人">
+                  <el-select v-model="operationForm.leaderId" filterable placeholder="请选择管理人"
+                    @change="(e) => { operationForm.leaderNumber = e }">
+                    <el-option v-for="(item, index) in recommendList" :key="index" :value="item.userId"
+                      :label="item.name"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="leaderId" label="管理人工号">
+                  <el-input disabled v-model="operationForm.leaderId" placeholder="请填写管理人工号"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <!-- <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="referrerId" label="推荐人">
+                  <el-select v-model="operationForm.referrerId" filterable placeholder="请选择推荐人"
+                    @change="(e) => { operationForm.referrerNumber = e }">
+                    <el-option v-for="(item, index) in userList" :key="item.id" :value="item.id"
+                      :label="item.name"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="referrerNumber" label="推荐人工号">
+                  <el-input readonly v-model="operationForm.referrerNumber" placeholder="请填写推荐人工号"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row> -->
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="资料附件">
+        <el-descriptions-item>
+          <template #default>
+            <el-form-item prop="IDCardFront" label-width="150">
+              <template #label>
+                <span style="color: #f56c6c">*</span>身份证(人像面)
+              </template>
+              <el-upload action="" v-if="!IDCardFront" :auto-upload="false" :show-file-list="false"
+                accept=".png, .jpg, .jpeg" @change="uploadImage($event, 1)">
+                <el-button link type="primary" icon="Upload">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="file-box">
+                  <div class="btn-top">
+                    <img class="image-close" @click="deleteImage(1)" src="@/assets/images/close.png" />
+                    <!--                    <el-icon class="btn-icon"><Delete /></el-icon>-->
+                  </div>
+                  <img class="file-img" :src="IDCardFront" />
+                  <div class="btn-bottom">
+                    <el-upload class="width-50" :show-file-list="false" :auto-upload="false" accept=".png, .jpg, .jpeg"
+                      @change="uploadImage($event, 1)"
+                      style="display: flex; align-items: center; justify-content: center; color: white">
+                      <el-icon>
+                        <Upload />
+                      </el-icon>重新上传
+                    </el-upload>
+                    <div class="width-50"
+                      style="display: flex; align-items: center; justify-content: center; color: white; cursor:pointer;"
+                      @click="downloadImage(1)">
+                      <el-icon>
+                        <Download />
+                      </el-icon>下载资料
+                    </div>
+                  </div>
+                </div>
+                <!--                <div class="fileName">{{ IDCardFrontName }}</div>
+                <div class="fileBtn">
+                  <el-upload :show-file-list="false" :auto-upload="false" accept=".png, .jpg, .jpeg" @change="uploadImage($event, 1)" style="display: flex; align-items: center">
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(1)"><View /></el-icon>
+                  <el-icon class="btn-icon" @click="downloadImage(1)"><Download /></el-icon>
+                  <el-icon class="btn-icon" @click="deleteImage(1)"><Delete /></el-icon>
+                </div>-->
+              </div>
+            </el-form-item>
+            <el-form-item prop="IDCardBack" label-width="150">
+              <template #label>
+                <span style="color: #f56c6c">*</span>身份证(国徽面)
+              </template>
+              <el-upload v-if="!IDCardBack" :auto-upload="false" :show-file-list="false" accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 2)">
+                <el-button link type="primary" icon="Upload">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="file-box">
+                  <div class="btn-top">
+                    <img class="image-close" @click="deleteImage(2)" src="@/assets/images/close.png" />
+                    <!--                    <el-icon class="btn-icon"><Delete /></el-icon>-->
+                  </div>
+                  <img class="file-img" :src="IDCardBack" />
+                  <div class="btn-bottom">
+                    <el-upload class="width-50" :show-file-list="false" :auto-upload="false" accept=".png, .jpg, .jpeg"
+                      @change="uploadImage($event, 2)"
+                      style="display: flex; align-items: center; justify-content: center; color: white">
+                      <el-icon>
+                        <Upload />
+                      </el-icon>重新上传
+                    </el-upload>
+                    <div class="width-50"
+                      style="display: flex; align-items: center; justify-content: center; color: white; cursor:pointer;"
+                      @click="downloadImage(2)">
+                      <el-icon>
+                        <Download />
+                      </el-icon>下载资料
+                    </div>
+                  </div>
+                </div>
+                <!--                <div class="fileName">{{ IDCardBackName }}</div>
+                <div class="fileBtn">
+                  <el-upload :auto-upload="false" :show-file-list="false" accept=".png, .jpg, .jpeg" @change="uploadImage($event, 2)" style="display: flex; align-items: center">
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(2)"><View /></el-icon>
+                  <el-icon class="btn-icon" @click="downloadImage(2)"><Download /></el-icon>
+                  <el-icon class="btn-icon" @click="deleteImage(2)"><Delete /></el-icon>
+                </div>-->
+              </div>
+            </el-form-item>
+            <el-form-item prop="" label="展业资格证" label-width="150">
+              <el-upload :auto-upload="false" v-if="!certification" :show-file-list="false" accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 3)">
+                <el-button link type="primary" icon="Upload">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="file-box">
+                  <div class="btn-top">
+                    <img class="image-close" @click="deleteImage(3)" src="@/assets/images/close.png" />
+                    <!--                    <el-icon class="btn-icon"><Delete /></el-icon>-->
+                  </div>
+                  <img class="file-img" :src="certification" />
+                  <div class="btn-bottom">
+                    <el-upload class="width-50" :show-file-list="false" :auto-upload="false" accept=".png, .jpg, .jpeg"
+                      @change="uploadImage($event, 3)"
+                      style="display: flex; align-items: center; justify-content: center; color: white">
+                      <el-icon>
+                        <Upload />
+                      </el-icon>重新上传
+                    </el-upload>
+                    <div class="width-50"
+                      style="display: flex; align-items: center; justify-content: center; color: white; cursor:pointer;"
+                      @click="downloadImage(3)">
+                      <el-icon>
+                        <Download />
+                      </el-icon>下载资料
+                    </div>
+                  </div>
+                </div>
+                <!--                <div class="fileName">{{ certificationName }}</div>
+                <div class="fileBtn">
+                  <el-upload :auto-upload="false" :show-file-list="false" accept=".png, .jpg, .jpeg" @change="uploadImage($event, 3)" style="display: flex; align-items: center">
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(3)"><View /></el-icon>
+                  <el-icon class="btn-icon" @click="downloadImage(3)"><Download /></el-icon>
+                  <el-icon class="btn-icon" @click="deleteImage(3)"><Delete /></el-icon>
+                </div>-->
+              </div>
+            </el-form-item>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-divider />
+      <el-button v-if="!recordShow" link type="primary" icon="plus"
+        @click="recordShow = !recordShow">填写人事档案(选填)</el-button>
+      <el-button v-else link type="primary" icon="ArrowUp" @click="recordShow = !recordShow">收起人事档案(选填)</el-button>
+      <br /><br />
+      <el-descriptions title="个人信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="sex" label="性别">
+                  <el-select v-model="operationForm.sex" placeholder="请选择性别">
+                    <el-option v-for="item in options[0]" :key="item.value" :value="item.value"
+                      :label="item.label"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="birthday" label="出生日期">
+                  <el-date-picker v-model="operationForm.birthday" type="date" placeholder="请选择" format="YYYY-MM-DD"
+                    value-format="YYYY-MM-DD" style="width: 100%" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="nations" label="民族">
+                  <el-select v-model="operationForm.nations" placeholder="请选择业务员类型">
+                    <el-option v-for="item in options[1]" :key="item.value" :value="item.value"
+                      :label="item.label"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="koseki" label="户籍">
+                  <el-input v-model="operationForm.koseki" placeholder="请填写户籍"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="maritalStatus" label="婚姻状况">
+                  <el-select v-model="operationForm.maritalStatus" placeholder="请选择婚姻状况">
+                    <el-option v-for="item in options[2]" :key="item.value" :value="item.value"
+                      :label="item.label"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="politicsStatus" label="政治面貌">
+                  <el-select v-model="operationForm.politicsStatus" placeholder="请选择政治面貌">
+                    <el-option v-for="item in options[3]" :key="item.value" :value="item.value"
+                      :label="item.label"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="health" label="健康状况">
+                  <el-select v-model="operationForm.health" placeholder="请选择健康状况">
+                    <el-option v-for="item in options[4]" :key="item.value" :value="item.value"
+                      :label="item.label"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="address" label="居住地区">
+                  <el-cascader clearable style="width: 100%" v-model="operationForm.address" :options="areaOptions"
+                    :props="areaProps" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="liveAddress" label="详细地址">
+                  <el-input v-model="operationForm.liveAddress" placeholder="请填写详细地址"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="postalCode" label="邮政编码">
+                  <el-input v-model="operationForm.postalCode" placeholder="请填写邮政编码"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="学历信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="education" label="学历">
+                  <el-select v-model="operationForm.education" placeholder="请选择学历">
+                    <el-option v-for="item in options[5]" :key="item.value" :value="item.value"
+                      :label="item.label"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="graduationTime" label="毕业时间">
+                  <el-date-picker v-model="operationForm.graduationTime" type="date" placeholder="请选择"
+                    format="YYYY-MM-DD" value-format="YYYY-MM-DD" style="width: 100%" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="school" label="毕业院校">
+                  <el-input v-model="operationForm.school" placeholder="请填写毕业院校"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="isComputer" label="是否计算机专业">
+                  <el-select v-model="operationForm.isComputer" placeholder="请选择是否计算机专业">
+                    <el-option key="1" value="1" label="是"></el-option>
+                    <el-option key="0" value="0" label="否"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="紧急联系人信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="emergencyContactName" label="姓名">
+                  <el-input v-model="operationForm.emergencyContactName" placeholder="请填写姓名"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="emergencyContactTel" label="手机号">
+                  <el-input v-model="operationForm.emergencyContactTel" placeholder="请填写手机号"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="工资信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="salary" label="工资">
+                  <el-input v-model="operationForm.salary" placeholder="请填写工资"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="salaryLevel" label="工资等级">
+                  <el-input v-model="operationForm.salaryLevel" placeholder="请填写工资等级"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="10">
+                <el-form-item prop="bankCardId" label="银行卡号">
+                  <el-input v-model="operationForm.bankCardId" placeholder="请填写银行卡号"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="10">
+                <el-form-item prop="bankName" label="开户行">
+                  <el-select v-model="operationForm.bankName" placeholder="请选择开户行">
+                    <el-option v-for="item in bankOption" :key="item.id" :value="item.id"
+                      :label="item.label"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-divider v-show="recordShow" />
+      <el-descriptions v-show="recordShow" title="其它附件">
+        <el-descriptions-item>
+          <template #default>
+            <el-form-item prop="" label="劳动合同" label-width="150">
+              <el-upload v-if="!contract" :auto-upload="false" :show-file-list="false"
+                accept=".png, .jpg, .jpeg, .pdf, .doc, .docx" @change="uploadImage($event, 4)">
+                <el-button link type="primary" icon="Upload">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <img style="width: 40px; height: 40px"
+                  :src="contractName.includes('.png') || contractName.includes('.jpg') || contractName.includes('.jpeg') ? image : contractName.includes('.pdf') ? pdf : contractName.includes('.doc') || contractName.includes('.docx') ? word : ''" />
+                <div class="fileName">{{ contractName }}</div>
+                <div class="fileBtn">
+                  <el-upload :auto-upload="false" :show-file-list="false" accept=".png, .jpg, .jpeg, .pdf, .doc, .docx"
+                    @change="uploadImage($event, 4)" style="display: flex; align-items: center">
+                    <el-icon class="btn-icon">
+                      <Upload />
+                    </el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(4)">
+                    <View />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="downloadImage(4)">
+                    <Download />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="deleteImage(4)">
+                    <Delete />
+                  </el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item prop="" label="应聘表" label-width="150">
+              <el-upload v-if="!applicant" :auto-upload="false" :show-file-list="false"
+                accept=".png, .jpg, .jpeg, .pdf, .doc, .docx" @change="uploadImage($event, 5)">
+                <el-button link type="primary" icon="Upload">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <img style="width: 40px; height: 40px"
+                  :src="applicantName.includes('.png') || applicantName.includes('.jpg') || applicantName.includes('.jpeg') ? image : applicantName.includes('.pdf') ? pdf : applicantName.includes('.doc') || applicantName.includes('.docx') ? word : ''" />
+                <div class="fileName">{{ applicantName }}</div>
+                <div class="fileBtn">
+                  <el-upload :auto-upload="false" :show-file-list="false" accept=".png, .jpg, .jpeg, .pdf, .doc, .docx"
+                    @change="uploadImage($event, 5)" style="display: flex; align-items: center">
+                    <el-icon class="btn-icon">
+                      <Upload />
+                    </el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(5)">
+                    <View />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="downloadImage(5)">
+                    <Download />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="deleteImage(5)">
+                    <Delete />
+                  </el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item prop="" label="定薪表" label-width="150">
+              <el-upload :auto-upload="false" v-if="!decidePay" :show-file-list="false"
+                accept=".png, .jpg, .jpeg, .pdf, .doc, .docx" @change="uploadImage($event, 6)">
+                <el-button link type="primary" icon="Upload">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <img style="width: 40px; height: 40px"
+                  :src="decidePayName.includes('.png') || decidePayName.includes('.jpg') || decidePayName.includes('.jpeg') ? image : decidePayName.includes('.pdf') ? pdf : decidePayName.includes('.doc') || decidePayName.includes('.docx') ? word : ''" />
+                <div class="fileName">{{ decidePayName }}</div>
+                <div class="fileBtn">
+                  <el-upload :auto-upload="false" :show-file-list="false" accept=".png, .jpg, .jpeg, .pdf, .doc, .docx"
+                    @change="uploadImage($event, 6)" style="display: flex; align-items: center">
+                    <el-icon class="btn-icon">
+                      <Upload />
+                    </el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(6)">
+                    <View />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="downloadImage(6)">
+                    <Download />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="deleteImage(6)">
+                    <Delete />
+                  </el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item prop="" label="离职表" label-width="150">
+              <el-upload :auto-upload="false" v-if="!dimission" :show-file-list="false"
+                accept=".png, .jpg, .jpeg, .pdf, .doc, .docx" @change="uploadImage($event, 7)">
+                <el-button link type="primary" icon="Upload">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <img style="width: 40px; height: 40px"
+                  :src="dimissionName.includes('.png') || dimissionName.includes('.jpg') || dimissionName.includes('.jpeg') ? image : dimissionName.includes('.pdf') ? pdf : dimissionName.includes('.doc') || dimissionName.includes('.docx') ? word : ''" />
+                <div class="fileName">{{ dimissionName }}</div>
+                <div class="fileBtn">
+                  <el-upload :auto-upload="false" :show-file-list="false" accept=".png, .jpg, .jpeg, .pdf, .doc, .docx"
+                    @change="uploadImage($event, 7)" style="display: flex; align-items: center">
+                    <el-icon class="btn-icon">
+                      <Upload />
+                    </el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(7)">
+                    <View />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="downloadImage(7)">
+                    <Download />
+                  </el-icon>
+                  <el-icon class="btn-icon" @click="deleteImage(7)">
+                    <Delete />
+                  </el-icon>
+                </div>
+              </div>
+            </el-form-item>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <div style="display: flex; justify-content: flex-end">
+        <el-button @click="onSubmit(OperationFormRef, 0)">取消</el-button>
+        <el-button type="primary" @click="onSubmit(OperationFormRef, 1)">确定</el-button>
+      </div>
+    </el-form>
+    <!--    <div class="image-view" v-if="imageShow" @click="imageShow = false">
+      <img :src="imageUrl" />
+    </div>-->
+    <el-dialog title="图片预览" v-model="imageShow">
+      <img class="image-view" :src="imageUrl" />
+    </el-dialog>
+    <el-dialog title="文件预览" v-model="fileShow">
+      <vue-office-docx :src="fileUrl" style="height: 600px; margin: 0; padding: 0"></vue-office-docx>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, } from 'vue'
+import type { FormRules, FormInstance } from "element-plus";
+import VueOfficeDocx from "@vue-office/docx";
+import api from "@/api";
+import { ElMessage } from "element-plus";
+import image from '@/assets/images/image.png'
+import word from '@/assets/images/word.png'
+import pdf from '@/assets/images/pdf.png'
+// 计算属性:根据等级列表获取等级名称
+
+// 获取人员等级列表
+// 机构是否可选
+const disabledProperty = ref(false);//机构是否可选
+const mingrade = ref();//最小等级
+const userGradeList = ref<any[]>([]);//用户等级列表
+const referrerList = ref<any[]>([]);//上级推荐人列表
+const getGradeOptions = () => {
+  api.partnerApi.queryGradeName().then((res: any) => {
+    if (res.code === 200) {
+      userGradeList.value = res.data;
+    }
+  })
+}
+// 手机号查询上级推荐人
+const searchRecommend = () => {
+  api.partnerApi.selectByUserNameAndMobile(Number(mingrade.value - 1)).then((res: any) => {
+    if (res.code === 200) {
+      referrerList.value = res.data;
+    } else {
+      ElMessage.error(res.msg);
+    }
+  })
+}
+// 处理等级变化
+const handleGradeChange = (val: any) => {
+  mingrade.value = getMinValueFromStrArray(val)
+  console.log(mingrade.value)
+}
+
+const typeAttrMap = (val: string): string => {
+  // 定义类型映射表
+  const map: any = {
+    '6': '个代',
+    '7': '渠道',
+    '5': '团队',
+    '8': '电销组',
+    '3': '合伙人',
+  };
+  if (!val) return '';
+  const typeCodes = val.split(',');
+  const result = typeCodes.map((code: any) => {
+    return map[code] || code;
+  });
+  return result as any;
+};
+// 处理上级推荐人变化
+const handleReferrerChange = (val: any) => {
+  let info = referrerList.value.find((item: any) => item.userId == val)
+  operationForm.referrerName = info.name;
+  operationForm.deptId = info.deptId;
+  if (info.deptId) {
+    disabledProperty.value = true;
+  }
+  getRecommend(info.deptId)//获取机构下管理人列表
+}
+const mobileInput = (val: any) => {
+  if (val.length >= 11) {
+    api.partnerApi.selectByMobile(val).then((res: any) => {
+      if (res.code === 200) {
+        console.log(operationForm)
+        // 只合并res.data中存在且不为空的值
+        if (res.data) {
+          Object.keys(res.data).forEach(key => {
+            const value = res.data[key];
+            // 只合并非null、非undefined的值
+            if (value !== null && value !== undefined) {
+              operationForm[key] = value;
+            }
+          });
+          operationForm.deptId = res.data.deptId;
+          if (res.data.deptId) {
+            disabledProperty.value = true;
+          }
+          getRecommend(res.data.deptId)
+        }
+      } else {
+        ElMessage.error('未查询到该业务员信息');
+      }
+    })
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+let emits = defineEmits(['closeDialog'])
+const OperationFormRef = ref<FormInstance>()
+// 添加/编辑业务员表单
+let operationForm = reactive({
+  gradeList: '',//合伙人等级列表
+  typeAttr: '',
+  deptId: '',
+  name: '',
+  mobile: '',
+  identity: '',
+  identityTimeStart: '',
+  identityTimeEnd: '',
+  leaderId: '',
+  referrerId: '',
+  referrerName: '',//上级推荐人姓名
+  sex: '',
+  birthday: '',
+  nations: '',
+  koseki: '',
+  maritalStatus: '',
+  politicsStatus: '',
+  health: '',
+  province: '',
+  city: '',
+  district: '',
+  liveAddress: '',
+  postalCode: '',
+  education: '',
+  graduationTime: '',
+  school: '',
+  isComputer: '',
+  emergencyContactName: '',
+  emergencyContactTel: '',
+  salary: '',
+  salaryLevel: '',
+  bankCardId: '',
+  bankName: '',
+  sfz1: '',
+  sfz2: '',
+  qualification: '',
+  contract: '',
+  applicant: '',
+  salaryTable: '',
+  leaveTable: '',
+  organizationId: '',
+  organization: '',
+  leaderNumber: '',
+  referrerNumber: '',
+  address: [],
+})
+// 机构数据渲染格式
+const cascaderProps = {
+  value: 'id',
+  label: 'name',
+  children: 'children'
+}
+// 添加/编辑业务员表单校验
+const operationRules = ref<FormRules>({
+  typeAttr: [
+    { required: true, trigger: "change", message: "请选择业务员类型" }
+  ],
+  name: [
+    { required: true, trigger: "blur", message: "请填写姓名" }
+  ],
+  mobile: [
+    { required: true, trigger: "blur", message: "请填写手机号" },
+    {
+      pattern: /^1[0-9]{10}$/,
+      message: '请填写正确的手机号',
+      trigger: 'blur'
+    }
+  ],
+  deptId: [
+    { required: true, trigger: "change", message: "请选择所属机构" }
+  ],
+  identity: [
+    { required: true, trigger: "blur", message: "请填写证件号" },
+    {
+      pattern: /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9X]$/,
+      message: '请填写正确的身份证号',
+      trigger: 'blur'
+    }
+  ],
+  identityTimeStart: [
+    { required: true, trigger: "change", message: "请选择证件有效期始" }
+  ],
+  identityTimeEnd: [
+    { required: true, trigger: "change", message: "请选择证件有效期止" }
+  ],
+  leaderId: [
+    { required: true, trigger: "blur", message: "请选择管理人" }
+  ],
+
+  referrerId: [
+    { required: true, trigger: "blur", message: "请选择推荐人" }
+  ],
+  referrerNumber: [
+    { required: true, trigger: "blur", message: "请填写推荐人工号" }
+  ],
+  // IDCardFront: [
+  //   { required: true, trigger: "change", message: "请上传身份(人像面)" }
+  // ],
+  // IDCardBack: [
+  //   { required: true, trigger: "change", message: "请上传身份(国徽面)" }
+  // ],
+  bankCardId: [
+    {
+      pattern: /^([1-9]{1})(\d{15}|\d{16}|\d{18})$/,
+      message: '请填写正确的银行卡号',
+      trigger: 'blur'
+    }
+  ],
+  emergencyContactTel: [
+    {
+      pattern: /^1[34578][0-9]{9}$/,
+      message: '请填写正确的手机号',
+      trigger: 'blur'
+    }
+  ],
+  postalCode: [
+    {
+      pattern: /^\d{6}$/,
+      message: '请填写正确的邮政编码',
+      trigger: 'blur'
+    }
+  ]
+})
+// 身份证人像面
+let IDCardFrontName = ref('')
+let IDCardFront = ref('')
+// 身份证国徽面
+let IDCardBackName = ref('')
+let IDCardBack = ref('')
+// 展业资格证
+let certificationName = ref('')
+let certification = ref('')
+// 劳务合同
+let contractName = ref('')
+let contract = ref('')
+// 应聘表
+let applicantName = ref('')
+let applicant = ref('')
+// 定薪表
+let decidePayName = ref('')
+let decidePay = ref('')
+// 离职表
+let dimissionName = ref('')
+let dimission = ref('')
+// 图片预览地址
+let imageShow = ref(false)
+let imageUrl = ref('')
+// word
+let fileShow = ref(false)
+
+
+// 限制证件日期
+const disabledDateStart = (time: Date) => {
+  return time.getTime() > new Date()
+}
+const disabledDateEnd = (time: Date) => {
+  return time.getTime() < new Date(operationForm.identityTimeStart)
+}
+
+// 编辑时初始化数据
+// 编辑的id
+let editId = ref()
+const initEditData = (id: any) => {
+    editId.value = id
+    api.operationApi.operationDetail(id).then((res: any) => {
+      if (res?.code == 200) {
+        let formData = res.data
+        Object.assign(operationForm, formData)
+        console.log(operationForm)
+        mingrade.value = getMinValueFromStrArray(formData.gradeList)
+        searchRecommend();//编辑回显查询上级推荐人列表
+        operationForm.deptId = formData.deptId
+        let address = [] as any
+        if (formData.province && formData.city && formData.district) {
+          address = [formData.province, formData.city, formData.district]
+        }
+        if (formData.province && !formData.city && !formData.district) {
+          address = [formData.province]
+        }
+        if (formData.fileList) {
+          let sfz1 = formData.fileList.find((item: any) => item.fileType == 'sfz1')
+          let sfz2 = formData.fileList.find((item: any) => item.fileType == 'sfz2')
+          let qualification = formData.fileList.find((item: any) => item.fileType == 'qualification')
+          let contractImg = formData.fileList.find((item: any) => item.fileType == 'contract')
+          let applicantImg = formData.fileList.find((item: any) => item.fileType == 'applicant')
+          let salaryTable = formData.fileList.find((item: any) => item.fileType == 'salary')
+          let leaveTable = formData.fileList.find((item: any) => item.fileType == 'leave')
+          if (sfz1) {
+            operationForm.sfz1 = sfz1.id
+            IDCardFrontName.value = sfz1.fileName
+            IDCardFront.value = sfz1.fileUrl
+          }
+          if (sfz2) {
+            operationForm.sfz2 = sfz2.id
+            IDCardBackName.value = sfz2.fileName
+            IDCardBack.value = sfz2.fileUrl
+          }
+          if (qualification) {
+            operationForm.qualification = qualification.id
+            certificationName.value = qualification.fileName
+            certification.value = qualification.fileUrl
+          }
+          if (contractImg) {
+            operationForm.contract = contractImg.id
+            contractName.value = contractImg.fileName
+            contract.value = contractImg.fileUrl
+          }
+          if (applicantImg) {
+            operationForm.applicant = applicantImg.id
+            applicantName.value = applicantImg.fileName
+            applicant.value = applicantImg.fileUrl
+          }
+          if (salaryTable) {
+            operationForm.salaryTable = salaryTable.id
+            decidePayName.value = salaryTable.fileName
+            decidePay.value = salaryTable.fileUrl
+          }
+          if (leaveTable) {
+            operationForm.leaveTable = leaveTable.id
+            dimissionName.value = leaveTable.fileName
+            dimission.value = leaveTable.fileUrl
+          }
+        }
+        operationForm.address = address
+        getUser(operationForm.deptId)
+        getRecommend(operationForm.deptId)
+      } else {
+        ElMessage({
+          message: res.msg,
+          type: 'warning'
+        })
+      }
+    })
+}
+
+// 新增数据初始化
+const initAddData = () => {
+  Object.assign(operationForm, {
+    typeAttr: '',
+    deptId: '',
+    name: '',
+    mobile: '',
+    identity: '',
+    identityTimeStart: '',
+    identityTimeEnd: '',
+    leaderId: '',
+    referrerId: '',
+    sex: '',
+    birthday: '',
+    nations: '',
+    koseki: '',
+    maritalStatus: '',
+    politicsStatus: '',
+    health: '',
+    province: '',
+    city: '',
+    district: '',
+    liveAddress: '',
+    postalCode: '',
+    education: '',
+    graduationTime: '',
+    school: '',
+    isComputer: '',
+    emergencyContactName: '',
+    emergencyContactTel: '',
+    salary: '',
+    salaryLevel: '',
+    bankCardId: '',
+    bankName: '',
+    sfz1: '',
+    sfz2: '',
+    qualification: '',
+    contract: '',
+    applicant: '',
+    salaryTable: '',
+    leaveTable: '',
+    organizationId: '',
+    organization: '',
+    leaderNumber: '',
+    referrerNumber: '',
+    address: [],
+  })
+  IDCardFrontName.value = ''
+  IDCardFront.value = ''
+  IDCardBackName.value = ''
+  IDCardBack.value = ''
+  certificationName.value = ''
+  certification.value = ''
+  contractName.value = ''
+  contract.value = ''
+  applicantName.value = ''
+  applicant.value = ''
+  decidePayName.value = ''
+  decidePay.value = ''
+}
+
+// 上传接口
+let postUrl = ref(`${import.meta.env.VITE_APP_API_BASEURL}/file/upload`)
+// 上传图片
+const uploadImage = async (file: any, type: any) => {
+  // const img = new Image();
+  // img.onload = () => {
+  //     console.log('图片尺寸:', img.width, 'x', img.height);
+  //     // 可以在这里处理尺寸信息
+  // };
+  // img.src = URL.createObjectURL(file.raw)
+  let files = file.raw
+  const params = new FormData(); // 声明formData数据类型
+  params.append("file", files);
+  params.append("type", "image");
+  const { code, data, msg }: any = await api.commonApi.fileUpload(params)
+  if (code == 200) {
+    let result = { ...data }
+    switch (type) {
+      case 1:
+        IDCardFrontName.value = result.fileName
+        IDCardFront.value = result.downloadUrl
+        operationForm.sfz1 = result.id
+        break;
+      case 2:
+        IDCardBackName.value = result.fileName
+        IDCardBack.value = result.downloadUrl
+        operationForm.sfz2 = result.id
+        break;
+      case 3:
+        certificationName.value = result.fileName
+        certification.value = result.downloadUrl
+        operationForm.qualification = result.id
+        break;
+      case 4:
+        contractName.value = result.fileName
+        contract.value = result.downloadUrl
+        operationForm.contract = result.id
+        break;
+      case 5:
+        applicantName.value = result.fileName
+        applicant.value = result.downloadUrl
+        operationForm.applicant = result.id
+        break;
+      case 6:
+        decidePayName.value = result.fileName
+        decidePay.value = result.downloadUrl
+        operationForm.salaryTable = result.id
+        break;
+      case 7:
+        dimissionName.value = result.fileName
+        dimission.value = result.downloadUrl
+        operationForm.leaveTable = result.id
+        break;
+    }
+  } else {
+    ElMessage({
+      message: msg,
+      type: 'error'
+    })
+  }
+}
+
+// 人事档案
+let recordShow = ref(false)
+let fileUrl = ref('')
+// word预览
+const filePreview = (file: any) => {
+  nextTick(() => {
+    fileUrl.value = file
+  })
+}
+
+// 图片预览
+const imageView = (type: any) => {
+  switch (type) {
+    case 1:
+      imageShow.value = true
+      imageUrl.value = IDCardFront.value
+      break;
+    case 2:
+      imageShow.value = true
+      imageUrl.value = IDCardBack.value
+      break;
+    case 3:
+      imageShow.value = true
+      imageUrl.value = certification.value
+      break;
+    case 4:
+      imageUrl.value = contract.value
+      nextTick(() => {
+        // loadPdf(contract.value)
+        if (contract.value.includes('.pdf')) {
+          window.open(contract.value, '_blank')
+        } else if (contract.value.includes('.doc') || contract.value.includes('.docx')) {
+          fileShow.value = true
+          nextTick(() => {
+            filePreview(contract.value)
+          })
+        } else if (contract.value.includes('.jpg') || contract.value.includes('.jpeg') || contract.value.includes('.png')) {
+          imageShow.value = true
+        }
+      })
+      break;
+    case 5:
+      imageUrl.value = applicant.value
+      nextTick(() => {
+        // loadPdf(applicant.value)
+        if (applicant.value.includes('.pdf')) {
+          window.open(applicant.value, '_blank')
+        } else if (applicant.value.includes('.doc') || applicant.value.includes('.docx')) {
+          fileShow.value = true
+          filePreview(applicant.value)
+        } else if (applicant.value.includes('.jpg') || applicant.value.includes('.jpeg') || applicant.value.includes('.png')) {
+          imageShow.value = true
+        }
+      })
+      break;
+    case 6:
+      imageUrl.value = decidePay.value
+      nextTick(() => {
+        // loadPdf(decidePay.value)
+        if (decidePay.value.includes('.pdf')) {
+          window.open(decidePay.value, '_blank')
+        } else if (decidePay.value.includes('.doc') || decidePay.value.includes('.docx')) {
+          fileShow.value = true
+          filePreview(decidePay.value)
+        } else if (decidePay.value.includes('.jpg') || decidePay.value.includes('.jpeg') || decidePay.value.includes('.png')) {
+          imageShow.value = true
+        }
+      })
+      break;
+    case 7:
+      imageUrl.value = dimission.value
+      nextTick(() => {
+        // loadPdf(dimission.value)
+        if (dimission.value.includes('.pdf')) {
+          window.open(dimission.value, '_blank')
+        } else if (dimission.value.includes('.doc') || dimission.value.includes('.docx')) {
+          fileShow.value = true
+          filePreview(dimission.value)
+        } else if (dimission.value.includes('.jpg') || dimission.value.includes('.jpeg') || dimission.value.includes('.png')) {
+          imageShow.value = true
+        }
+      })
+      break;
+  }
+}
+
+
+
+// 图片下载
+const download = (url: any, name: any) => {
+  let a_link = document.createElement('a') as any
+  fetch(url).then((res: any) => res.blob())
+    .then((blob: any) => {
+      // 将链接地址字符内容转变成blob地址
+      a_link.href = URL.createObjectURL(blob)
+      console.log(a_link.href)
+      a_link.download = name //下载的文件的名字
+      document.body.appendChild(a_link)
+      a_link.click()
+    })
+  // let image = new Image();
+  // // 解决跨域 Canvas 污染问题
+  // image.setAttribute("crossOrigin", "anonymous");
+  // image.onload = function () {
+  //     let canvas = document.createElement("canvas");
+  //     canvas.width = image.width;
+  //     canvas.height = image.height;
+  //     let context = canvas.getContext("2d");
+  //     context.drawImage(image, 0, 0, image.width, image.height);
+  //     let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据
+  //     let a = document.createElement("a"); // 生成一个a元素
+  //     let event = new MouseEvent("click"); // 创建一个单击事件
+  //     a.download = name; // 设置图片名称
+  //     a.href = url; // 将生成的URL设置为a.href属性
+  //     a.dispatchEvent(event); // 触发a的单击事件
+  // }
+  // image.src = url
+}
+const downloadImage = (type: any) => {
+  switch (type) {
+    case 1:
+      download(IDCardFront.value, IDCardFrontName.value)
+      break;
+    case 2:
+      download(IDCardBack.value, IDCardBackName.value)
+      break;
+    case 3:
+      download(certification.value, certificationName.value)
+      break;
+    case 4:
+      download(contract.value, contractName.value)
+      break;
+    case 5:
+      download(applicant.value, applicantName.value)
+      break;
+    case 6:
+      download(decidePay.value, decidePayName.value)
+      break;
+    case 7:
+      download(dimission.value, dimissionName.value)
+      break;
+  }
+}
+// 图片删除
+const deleteImage = (type: any) => {
+  switch (type) {
+    case 1:
+      IDCardFront.value = ''
+      IDCardFrontName.value = ''
+      break;
+    case 2:
+      IDCardBack.value = ''
+      IDCardBackName.value = ''
+      break;
+    case 3:
+      certification.value = ''
+      certificationName.value = ''
+      break;
+    case 4:
+      contract.value = ''
+      contractName.value = ''
+      break;
+    case 5:
+      applicant.value = ''
+      applicantName.value = ''
+      break;
+    case 6:
+      decidePay.value = ''
+      decidePayName.value = ''
+      break;
+    case 7:
+      dimission.value = ''
+      dimissionName.value = ''
+      break;
+  }
+}
+// 管理人/推荐人
+let userList = ref()
+let recommendList = ref()
+const getUser = (id: any) => {
+  api.operationApi.getUser({
+    id: id
+  }).then((res: any) => {
+    if (res?.code == 200) {
+      userList.value = res.data
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+// 推荐人
+const getRecommend = (id: any) => {
+  api.operationApi.getUser({
+    id: id,
+    typeAttr: 2
+  }).then((res: any) => {
+    if (res.code == 200) {
+      recommendList.value = res.data
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+// 确定
+const onSubmit = async (OperationFormRef: any, type: any) => {
+  console.log(operationForm)
+  if (!OperationFormRef) {
+    emits('closeDialog', '取消')
+    recordShow.value = false
+    OperationFormRef.resetFields()
+    return
+  }
+  if (type) {
+    await OperationFormRef.validate((valid: any, error: any) => {
+      if (valid) {
+        if (IDCardFront.value && IDCardBack.value) {
+          let formData = { ...operationForm }
+          // formData.organization = operationForm.value.organization[operationForm.value.organization.length - 1]
+          formData.systemCode = localStorage.getItem('login_system') ? localStorage.getItem('login_system') : ''
+          formData.province = operationForm.address ? operationForm.address[0] : ''
+          formData.city = operationForm.address ? operationForm.address[1] ? operationForm.address[1] : '' : ''
+          formData.district = operationForm.address ? operationForm.address[2] ? operationForm.address[2] : '' : ''
+          if (editId.value) {
+            api.operationApi.updateOperation(formData).then((res: any) => {
+              if (res.code == 200) {
+                ElMessage({
+                  message: res.msg,
+                  type: 'success'
+                })
+                emits('closeDialog', '确定')
+              } else {
+                ElMessage({
+                  message: res.msg,
+                  type: 'error'
+                })
+              }
+              IDCardFrontName.value = ''
+              IDCardFront.value = ''
+              IDCardBackName.value = ''
+              IDCardBack.value = ''
+              certificationName.value = ''
+              certification.value = ''
+              contractName.value = ''
+              contract.value = ''
+              applicantName.value = ''
+              applicant.value = ''
+              decidePayName.value = ''
+              decidePay.value = ''
+              dimissionName.value = ''
+              dimission.value = ''
+              recordShow.value = false
+              OperationFormRef.resetFields()
+              emits('closeDialog', '取消')
+            })
+          } else {
+            console.log(formData)
+            api.partnerApi.saveByPartner({
+              ...formData,
+            }).then((res: any) => {
+              if (res.code == 200) {
+                ElMessage({
+                  message: res.msg,
+                  type: 'success'
+                })
+                emits('closeDialog', '确定')
+              } else {
+                ElMessage({
+                  message: res.msg,
+                  type: 'error'
+                })
+              }
+              IDCardFrontName.value = ''
+              IDCardFront.value = ''
+              IDCardBackName.value = ''
+              IDCardBack.value = ''
+              certificationName.value = ''
+              certification.value = ''
+              contractName.value = ''
+              contract.value = ''
+              applicantName.value = ''
+              applicant.value = ''
+              decidePayName.value = ''
+              decidePay.value = ''
+              dimissionName.value = ''
+              dimission.value = ''
+              recordShow.value = false
+              OperationFormRef.resetFields()
+              emits('closeDialog', '取消')
+            })
+          }
+        } else {
+          ElMessage({
+            message: '请上传必传附件!',
+            type: 'warning'
+          })
+        }
+      } else {
+        Object.keys(error).forEach((key, i) => {
+          if (i == 0) {
+            const firstFiled = error[key][0].field
+            OperationFormRef.scrollToField(firstFiled)
+          }
+        })
+        ElMessage({
+          message: '请正确填写相关信息!',
+          type: 'warning'
+        })
+      }
+    })
+  } else {
+    IDCardFrontName.value = ''
+    IDCardFront.value = ''
+    IDCardBackName.value = ''
+    IDCardBack.value = ''
+    certificationName.value = ''
+    certification.value = ''
+    contractName.value = ''
+    contract.value = ''
+    applicantName.value = ''
+    applicant.value = ''
+    decidePayName.value = ''
+    decidePay.value = ''
+    dimissionName.value = ''
+    dimission.value = ''
+    recordShow.value = false
+    emits('closeDialog', '取消')
+    OperationFormRef.resetFields()
+  }
+}
+const getMinValueFromStrArray = (strArray: string[]): number | null => {
+  // 检查数组是否为空
+  if (!strArray || strArray.length === 0) {
+    console.warn('数组为空');
+    return null;
+  }
+
+  try {
+    // 将字符串转换为数字
+    const numArray = strArray.map(str => {
+      const num = Number(str);
+      // 检查是否为有效数字
+      if (isNaN(num)) {
+        throw new Error(`字符串 "${str}" 无法转换为数字`);
+      }
+      return num;
+    });
+
+    // 获取最小值
+    const minValue = Math.min(...numArray);
+    return minValue;
+  } catch (error) {
+    console.error('获取最小值失败:', error);
+    return null;
+  }
+};
+// 初始化个人信息
+let options = ref([])
+const initInfo = () => {
+  /*
+  * 性别        gender
+    民族        nation
+    婚姻状况        marriage
+    政治面貌        political_status
+    健康状况        health_status
+    学历        educational
+  * */
+  let infoList = ['gender', 'nation', 'marriage', 'political_status', 'health_status', 'educational', 'team']
+  infoList.forEach((item: string, index: number) => {
+    api.commonApi.personInfo(item).then((res: any) => {
+      if (res.code == 200) {
+        options.value[index] = [...res.data]
+      } else {
+        ElMessage({
+          message: res.msg,
+          type: 'warning'
+        })
+      }
+    })
+  })
+}
+// 获取地区数据
+const areaOptions = ref([]);
+const areaProps = ref({
+  value: "areaCode",
+  label: "areaCname",
+  children: "child",
+});
+const getArea = () => {
+  api.areaApi.areaList({}).then((res) => {
+    areaOptions.value = res.data;
+  });
+}
+
+// 团队数据
+const initTeamData = async (e: any) => {
+  const { code, data, msg }: any = await api.teamApi.teamList({
+    attribute: e,
+    param: ''
+  })
+  if (code == 200) {
+    teamList.value = data
+  } else {
+    ElMessage({
+      message: msg,
+      type: 'warning'
+    })
+  }
+}
+
+let teamList = ref([])
+// 机构切换
+const deptIdChange = (e: any) => {
+  if (e) {
+    operationForm.deptId = e[e.length - 1]
+    getUser(e[e.length - 1])
+    getRecommend(e[e.length - 1])
+
+  }
+}
+
+// 初始化银行数据
+let bankOption = ref()
+const initBankCard = () => {
+  api.commonApi.personInfo('bank_info').then((res: any) => {
+    if (res.code == 200) {
+      bankOption.value = res.data
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+
+let deptOption = ref([])
+const optionProps = {
+  value: 'id',
+  label: 'name',
+  children: 'children',
+  checkStrictly: true,
+}
+// 获取机构数据
+const institutionList = () => {
+  api.institutionApi.institutionList({ name: '', system: '' }).then((res: any) => {
+    if (res?.code == 200) {
+      deptOption.value = res.data
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+
+
+onMounted(() => {
+  initInfo()
+  getArea()
+  initBankCard()
+  institutionList()
+  getGradeOptions()//获取用户等级列表
+})
+
+defineExpose({
+  initEditData,
+  operationForm,
+  initAddData
+})
+
+
+</script>
+
+<style scoped lang="scss">
+.typeAttrMap {
+  padding: 2px 4px;
+  box-sizing: border-box;
+  background-color: #00a0f4;
+  color: #fff;
+  border-radius: 3px;
+}
+
+.fileInfo {
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  //padding: 2px 20px;
+  border-radius: 5px;
+  margin: 0 10px;
+
+  //&:hover{
+  //  background: #ccc;
+  //}
+  .fileName {
+    width: 200px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+
+  .fileBtn {
+    display: flex;
+    align-items: center;
+
+    .btn-icon {
+      margin: 0 10px;
+      font-size: 16px;
+      cursor: pointer;
+
+      &:hover {
+        color: #00a0f4;
+      }
+    }
+  }
+
+  .file-box {
+    position: relative;
+
+    .btn-top {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      position: absolute;
+      top: 0;
+      left: 0;
+
+      .image-close {
+        display: block;
+        width: 12px;
+        height: 12px;
+      }
+    }
+
+    .file-img {
+      display: block;
+      width: 208px;
+      height: 130px;
+      border-radius: 5px;
+    }
+
+    .btn-bottom {
+      position: absolute;
+      left: 0;
+      bottom: 0;
+      z-index: 1000;
+      display: flex;
+      align-items: center;
+      height: 24px;
+      width: 100%;
+      background: url("@/assets/images/btn-bg.png") no-repeat;
+      background-size: 100% 100%;
+
+      .width-50 {
+        width: 50%;
+      }
+    }
+  }
+
+}
+
+.image-view {
+  display: block;
+  width: 400px;
+  height: 260px;
+  border-radius: 5px;
+  margin: 0 auto;
+}
+
+:deep(.el-input__inner[type=number]::-webkit-outer-spin-button) {
+  -webkit-appearance: none;
+  margin: 0;
+}
+
+:deep(.el-input__inner[type=number]::-webkit-inner-spin-button) {
+  -webkit-appearance: none;
+  margin: 0;
+}
+
+:deep(.el-input__inner[type=number]) {
+  -moz-appearance: textfield;
+}
+
+:deep(.vue-office-docx-main) {
+  height: 600px;
+  overflow-y: auto;
+}
+
+:deep(.docx-wrapper) {
+  background: white;
+}
+</style>

+ 465 - 0
src/views/partnerManagement/partner.vue

@@ -0,0 +1,465 @@
+<!-- 模板区域 -->
+<template>
+  <div class="flex overflow-hidden">
+    <!-- 右侧 -->
+    <PageMain class="vh100 flex-1 overflow-hidden flex flex-col">
+      <SearchForm :fields="fields" :formInline="formInline" :onSearch="findpage" :onReset="resetForm">
+      </SearchForm>
+      <div class="flex-1 overflow-auto">
+        <ComplexTable :tableData="tableData" :columns="columns" :showIndex="false" :columnwidth="250"
+          :showSelect="false" :pageInfo="pageInfo" @getList="getList">
+          <template v-slot:table-title-btn>
+            <el-button type="primary" @click="addPartner">
+              添加合伙人
+              <template #icon>
+                <el-icon>
+                  <Plus />
+                </el-icon>
+              </template>
+            </el-button>
+          </template>
+          <template v-slot:operation="scope">
+            <el-button type="primary" link @click="detailPartner(scope.operationData)">详情</el-button>
+            <el-dropdown placement="bottom-start" trigger="click">
+              <span class="el-dropdown-link">
+                更 多
+              </span>
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item @click="editPartner(scope.operationData)">编辑</el-dropdown-item>
+                  <el-dropdown-item @click="enablePartner(scope.operationData)">{{ scope.operationData.partStatus ? '禁用'
+                    : '启用' }}</el-dropdown-item>
+                  <el-dropdown-item @click="queryPartnerRelation(scope.operationData)">关系查询</el-dropdown-item>
+                  <el-dropdown-item @click="addNewGrade(scope.operationData)">添加新等级</el-dropdown-item>
+                  <el-dropdown-item @click="assignDayJudge(scope.operationData)">添加为业务员</el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </template>
+
+          <template v-slot:search="scope">
+            {{ scope.slotData.label }}
+          </template>
+        </ComplexTable>
+      </div>
+    </PageMain>
+    <el-dialog v-model="addPartnerShow" title="添加合伙人" width="1000">
+      <addOperation ref="addOperationRef" @closeDialog="closeAddOperation"></addOperation>
+    </el-dialog>
+    <el-dialog v-model="addNewGradeShow" title="添加合伙人等级" width="1000">
+      <el-checkbox-group v-model="checkList">
+        <el-checkbox :disabled="item.grade <= gradeList[gradeList.length - 1]" :label="item.gradeName"
+          :value="item.grade" v-for="item in userGradeList" :key="item.grade" />
+      </el-checkbox-group>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="addNewGradeShow = false">取消</el-button>
+          <el-button type="primary" @click="addNewGradeSave">
+            确定
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <el-dialog v-model="PartnerRelationShow" title="关系查询" width="1000">
+      <el-table :data="relationQuery" style="width: 100%">
+        <el-table-column prop="type" label="级别" width="100" align="center">
+          <template #default="scope">
+            {{ scope.row.type == 1 ? '一级' : scope.row.type == 2 ? '二级' : scope.row.type == 3 ? '三级' : scope.row.type ==
+              4 ? '四级' : scope.row.type == 5 ? '五级' : '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="userId" label="工号" width="180" align="center" />
+        <el-table-column prop="userName" label="姓名" align="center" />
+        <el-table-column prop="suggestName" label="推荐人" align="center" />
+        <el-table-column prop="deptName" label="部门" width="250" align="center" />
+        <el-table-column prop="mobile" label="电话" align="center" />
+      </el-table>
+    </el-dialog>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onBeforeMount } from 'vue'
+import addOperation from './modules/addPartner.vue'
+import api from '@/api'
+import { ElMessage, ElMessageBox } from 'element-plus';
+import router from '@/router';
+// 页面加载时获取机构列表
+onBeforeMount(() => {
+  getInstitutionList();
+  getGradeOptions();
+  findpage();
+});
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+// 机构树相关变量
+const addOperationRef = ref(null);//添加合伙人弹窗实例
+const userId = ref('');//用户id
+const addPartnerShow = ref(false);//添加合伙人弹窗显示状态
+const addNewGradeShow = ref(false);//添加新等级弹窗显示状态
+const PartnerRelationShow = ref(false);//关系查询弹窗显示状态
+const checkList = ref([]);//选中的等级列表
+const userGradeList = ref();//用户等级列表
+const gradeList = ref([]);//等级列表
+const relationQuery = ref([]);//关系查询数据
+const deptTreeData = ref<any[]>([]);//机构树数据
+const tableData = ref([]);//表格数据
+const formInline = reactive({
+  name: '',//姓名
+  mobile: "",//手机号
+  userId: '',//工号
+  grade: '',//合伙人等级
+  inviter: "",//邀请人
+  deptId: '',//机构id
+})
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 20,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+
+const typeAttrOptions = ref([
+
+  {
+    label: '个代',
+    value: '6'
+  }, {
+    label: '渠道',
+    value: '7'
+  }, {
+    label: '团队',
+    value: '5'
+  },
+  {
+    label: '电销组',
+    value: '8'
+  },
+  {
+    label: '合伙人',
+    value: '3'
+  },
+])
+const statusOptions = ref([
+  {
+    label: '未认证',
+    value: '0'
+  },
+  {
+    label: '实名待认证',
+    value: '1'
+  },
+  {
+    label: '实名认证失败',
+    value: '2'
+  },
+  {
+    label: '待入职',
+    value: '3'
+  },
+  {
+    label: '入司待审核',
+    value: '4'
+  },
+  {
+    label: '入司审核失败',
+    value: '5'
+  },
+  {
+    label: '已入职',
+    value: '6'
+  },
+  {
+    label: '离职待审核',
+    value: '7'
+  },
+  {
+    label: '离职',
+    value: '8'
+  },
+
+])
+const parentIdprops = {
+  expandTrigger: 'hover' as const,
+  value: 'id',
+  label: 'name',
+  checkStrictly: true,
+}
+//表格字段数据
+const fields = ref([
+  { label: "合伙人", model: "name", type: "input", placeholder: "输入姓名手机号查找" },
+  {
+    label: "归属机构", model: "deptId", type: "cascader", options: deptTreeData, props: parentIdprops, onChange: (value: any) => {
+      formInline.deptId = value[value.length - 1];
+    }
+  },
+  {
+    label: "类型", model: "typeAttr", type: "select", placeholder: "请选择类型", options: typeAttrOptions,
+  },
+  {
+    label: "等级", model: "grade", type: "select", placeholder: "选择等级", options: userGradeList, props: {
+      label: 'gradeName',
+      value: 'grade',
+    },
+  },
+  {
+    label: "人员状态", model: "status", type: "select", placeholder: "请选择人员状态", options: statusOptions
+
+  },
+  {
+    label: "账号状态", model: "isEnable", type: "select", placeholder: "请选择账号状态", options: [
+      {
+        label: '启用',
+        value: '0'
+      },
+      {
+        label: '禁用',
+        value: '1'
+      },
+    ],
+  },
+  {
+    label: "推荐人", model: "referrerName", type: "input", placeholder: "输入姓名手机号"
+  },
+]);
+const columns = [
+  { prop: "name", label: "姓名", width: '200' },
+  { prop: "mobile", label: "手机号", width: '200' },
+  {
+    prop: "typeAttr", label: "类型", width: '200',
+    formatter: (row: any) => {
+      const map: any = {
+        '6': '个代',
+        '7': '渠道',
+        '5': '团队',
+        '8': '电销组',
+        '3': '合伙人',
+      }
+      return row.typeAttr
+        .split(',')
+        .map((typeId: any) => map[typeId] || typeId)
+        .join(',') || '未知';
+    }
+  },
+  {
+    prop: "grade", label: "等级", width: '200',
+    formatter: (row: any) => {
+      return row.grade
+        .split(',')
+        .map((gradeId: any) => userGradeList.value.find((item: any) => item.grade == gradeId)?.gradeName || gradeId)
+        .join(',') || '未知';
+    }
+  },
+  {
+    prop: "deptName", label: "所属机构", width: '200'
+  },
+  { prop: "premium", label: "累计保费", width: '200' },
+  { prop: "kickback", label: "累计佣金", width: '200' },
+  { prop: "createTime", label: "创建时间", width: '200' },
+  {
+    prop: "status", label: "人员状态", width: '200',
+    formatter: (row: any) => {
+      return statusOptions.value.find((item: any) => item.value == row.status)?.label || row.status;
+    }
+  },
+  {
+    prop: "partStatus", label: "账号状态", width: '200',
+    formatter: (row: any) => {
+      return row.partStatus ? '启用' : '禁用';
+    }
+  },
+  {
+    prop: "leaderIdName", label: "管理人", width: '200',
+  },
+  {
+    prop: "referrerName", label: "推荐人", width: '200',
+  },
+];
+// 添加合伙人
+const addPartner = () => {
+  console.log('添加合伙人');
+  addPartnerShow.value = true;
+}
+// 详情合伙人
+const detailPartner = (item: any) => {
+  router.push({
+    path: '/PartnerManagement/partnerDetail',
+    query: {
+      userId: item.userId,
+    }
+  })
+}
+// 编辑合伙人
+const editPartner = (item: any) => {
+  console.log('编辑合伙人:', item);
+  addPartnerShow.value = true
+      nextTick(() => {
+        addOperationRef.value.initEditData(item.userId)
+      })
+}
+
+const enablePartner = (item: any) => {
+  console.log('启用合伙人:', item);
+
+  if (item.partStatus) {
+    ElMessageBox.confirm(
+      '确定要禁用该合伙人账号吗?',
+      '禁用',
+      {
+        confirmButtonText: '确定禁用',
+        type: 'warning',
+        center: true,
+        confirmButtonClass: 'el-button--primary',
+      }
+    )
+      .then(() => {
+        api.partnerApi.enableDisable(item.userId, '0').then((res: any) => {
+          if (res.code == '200') {
+            ElMessage({
+              type: 'success',
+              message: res.msg,
+              plain: true,
+            })
+            findpage();
+          } else {
+            ElMessage.error(res.msg || '禁用失败');
+          }
+        })
+      })
+      .catch(() => {
+      })
+  } else {
+    api.partnerApi.enableDisable(item.userId, '1').then((res: any) => {
+      if (res.code == '200') {
+        ElMessage({
+          type: 'success',
+          message: res.msg,
+          plain: true,
+        })
+        findpage();
+      } else {
+        ElMessage.error(res.msg || '启用失败');
+      }
+    })
+  }
+}
+
+// 关系查询
+const queryPartnerRelation = (item: any) => {
+  api.partnerApi.relationalQuery(item.userId).then((res: any) => {
+    if (res.code == '200') {
+      relationQuery.value = res.data;
+      PartnerRelationShow.value = true;
+    } else {
+      ElMessage.error(res.msg || '关系查询失败');
+    }
+  })
+}
+// 添加新等级
+const addNewGrade = (item: any) => {
+  userId.value = item.userId;
+  api.partnerApi.queryGrade(item.userId).then((res: any) => {
+    if (res.code == '200') {
+      gradeList.value = res.data;
+      addNewGradeShow.value = true;
+    } else {
+      ElMessage.error(res.msg);
+    }
+  })
+}
+// 添加新等级保存
+const addNewGradeSave = () => {
+  api.partnerApi.addNewGrade({
+    userId: userId.value,
+    gradeList:checkList.value
+  }).then((res: any) => {
+    if (res.code == '200') {
+      ElMessage({
+        type: 'success',
+        message: res.msg,
+        plain: true,
+      })
+      addNewGradeShow.value = false;
+      findpage();
+    } else {
+      ElMessage.error(res.msg || '添加新等级失败');
+    }
+  })
+}
+// 添加业务员
+const assignDayJudge = (item: any) => {
+  console.log('添加业务员:', item);
+}
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  findpage();
+
+};
+const resetForm = () => {
+  findpage();
+}
+//数据查询
+function findpage() {
+  let query = { ...formInline }
+  api.partnerApi.partnerQueryPage({ pages: pageInfo.value.pageNum, size: pageInfo.value.pageSize, ...query }).then((res: any) => {
+    if (res.code == '200') {
+      tableData.value = res.data.records;
+      pageInfo.value.pageNum = res.data.current;
+      pageInfo.value.pageSize = res.data.size;
+      pageInfo.value.total = res.data.total;
+    } else {
+    }
+  });
+}
+
+// 获取机构列表
+const getInstitutionList = () => {
+  api.institutionApi.institutionList({}).then((res: any) => {
+    if (res.code === 200) {
+      deptTreeData.value = res.data;
+    }
+  });
+};
+// 获取人员等级列表
+const getGradeOptions = () => {
+  api.partnerApi.queryGradeName().then((res: any) => {
+    if (res.code === 200) {
+      userGradeList.value = res.data;
+      console.log(userGradeList.value);
+    }
+  })
+}
+
+const closeAddOperation = (text: string) => {
+  if (text == '确定') {
+    findpage();
+  }
+  addPartnerShow.value = false
+}
+</script>
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+:deep(.el-dropdown-link) {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+}
+</style>

+ 657 - 0
src/views/partnerManagement/partnerDetail.vue

@@ -0,0 +1,657 @@
+<template>
+  <div class="detail">
+    <div class="state" v-if="dataDetail?.status == 5">
+      <el-icon :size="20" style="color: red; margin: 3px 10px 0 0;">
+        <CircleClose />
+      </el-icon>
+      <div>
+        <h3>审核不通过</h3>
+        <p>{{ dataDetail?.approvalOpinion }}如有问题,请联系审核人员或者拨打客服电话400-400-400。</p>
+        <el-button link type="primary" @click="editDetail">修改并重提交</el-button>
+      </div>
+    </div>
+    <div class="info">
+      <el-descriptions>
+        <template #title>
+          <el-row :gutter="20" flex justify="space-between">
+            <el-col :span="12" style="display: flex; align-items: center;">
+              <span class="firstName">{{ initName(dataDetail?.name) }}</span>
+              <span class="allName">{{ dataDetail?.name }}</span>
+            </el-col>
+          </el-row>
+        </template>
+        <el-descriptions-item label="工号:" width="33%">{{ dataDetail?.userId }}</el-descriptions-item>
+        <el-descriptions-item label="所属机构:" width="33%">{{ dataDetail?.deptName }}</el-descriptions-item>
+        <el-descriptions-item label="状态:" width="33%">{{  statusMap(dataDetail?.status)}}</el-descriptions-item>
+        <el-descriptions-item label="合伙人等级" width="33%">{{ gradeMap(dataDetail?.gradeList) }}</el-descriptions-item>
+        <el-descriptions-item label="类型:" width="33%">{{ typeAttrMap(dataDetail?.partnerTypeAttr) }}</el-descriptions-item>
+        <el-descriptions-item label="创建人:" width="33%">{{ dataDetail?.updateBy }}</el-descriptions-item>
+        <el-descriptions-item label="创建时间:" width="33%">{{ dataDetail?.createTime }}</el-descriptions-item>
+      </el-descriptions>
+    </div>
+    <div class="message">
+      <el-tabs v-model="activeName" class="demo-tabs" @tab-click="(tab) => { activeName = tab }">
+        <el-tab-pane label="基本信息" name="msg" style="padding: 0 24px">
+          <div class="other">
+            <el-descriptions title="个人信息">
+              <el-descriptions-item label="姓名:" width="33%">{{ dataDetail?.name }}</el-descriptions-item>
+              <el-descriptions-item label="手机号:" width="33%">{{ dataDetail?.mobile }}</el-descriptions-item>
+              <el-descriptions-item label="证件号:" width="33%">{{ dataDetail?.identity }}</el-descriptions-item>
+              <el-descriptions-item label="证件有效期始:" width="33%">{{ dataDetail?.identityTimeStart }}</el-descriptions-item>
+              <el-descriptions-item label="证件有效期止:" width="33%">{{ dataDetail?.identityTimeEnd }}</el-descriptions-item>
+            </el-descriptions>
+            <el-descriptions title="其他信息">
+              <el-descriptions-item>
+                <template #default>
+                  <el-row :gutter="20">
+                    <el-col :span="12" class="mb-5">
+                      管理人:{{ dataDetail?.leaderName }}
+                    </el-col>
+                    <el-col :span="12" class="mb-5">
+                      管理人工号:{{ dataDetail?.leaderId }}
+                    </el-col>
+                    <el-col :span="12" class="mb-5">
+                      推荐人:{{ dataDetail?.referrerName }}
+                    </el-col>
+                    <el-col :span="12" class="mb-5">
+                      推荐人工号:{{ dataDetail?.referrerId }}
+                    </el-col>
+                  </el-row>
+                </template>
+              </el-descriptions-item>
+            </el-descriptions>
+            <el-descriptions title="银行卡信息">
+              <el-descriptions-item>
+                <template #default>
+                  <el-table
+                    :data="dataDetail?.bankCardList"
+                    height="200"
+                  >
+                    <el-table-column prop="name" label="姓名"></el-table-column>
+                    <el-table-column prop="bankName" label="开户行">
+                      <template #default="scope">
+                        {{ bankCardChange(bankOption, scope.row.bankName) }}
+                      </template>
+                    </el-table-column>
+                    <el-table-column prop="bankCardNumber" label="卡号"></el-table-column>
+                    <el-table-column prop="bankAddress" label="开户支行"></el-table-column>
+                    <el-table-column prop="auditStatus" label="审核状态">
+                      <template #default="scope">
+                        {{ scope.row.auditStatus == '0'?'未审核':scope.row.auditStatus == '1'?'审核通过':scope.row.auditStatus == '2'?'审核驳回':''}}
+                      </template>
+                    </el-table-column>
+                    <el-table-column prop="" label="身份证件照片">
+                      <template #default="scope">
+<!--                        <img class="cardImage" :src="dataDetail?.fileList.length>0?dataDetail?.fileList?.[0].fileUrl:''">-->
+                          {{ dataDetail?.fileList.length>0?`${dataDetail?.fileList?.length}张`: '暂无' }}
+                      </template>
+                    </el-table-column>
+                    <el-table-column prop="cardFile" label="银行卡照片">
+                      <template #default="scope">
+<!--                        <img class="cardImage" :src="scope.row.cardFile">-->
+                          {{ scope.row.cardFileUrl?`1张`: '暂无' }}
+                      </template>
+                    </el-table-column>
+                    <el-table-column label="操作">
+                      <template #default="scope">
+                        <a style="color: #409EFF; cursor: pointer" @click="editBankCard(scope.row)">详情</a>
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                </template>
+              </el-descriptions-item>
+            </el-descriptions>
+            <el-button class="bg-white" plain type="primary" icon="plus" style="width: 100%; border-radius: 2px" @click="addBankCard">添加银行卡</el-button>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane label="资料附件" name="file" style="padding: 0 24px">
+          <div class="other">
+            <el-descriptions title="资料附件">
+              <el-descriptions-item>
+                <template #default>
+                  <div class="fileItem" v-if="imageChangeName('sfz1')">
+                    <span class="label">身份证(人像面)</span>
+                    <div class="fileName">
+                      <span class="file-name">{{ imageChangeName('sfz1') }}</span>
+                      <el-icon class="file-icon" @click="imageView('sfz1')"><View/></el-icon>
+                    </div>
+                  </div>
+                  <div class="fileItem" v-if="imageChangeName('sfz2')">
+                    <span class="label">身份证(国徽面)</span>
+                    <div class="fileName">
+                      <span class="file-name">{{ imageChangeName('sfz2') }}</span>
+                      <el-icon class="file-icon" @click="imageView('sfz2')"><View /></el-icon>
+                    </div>
+                  </div>
+                  <div class="fileItem" v-if="imageChangeName('qualification')">
+                    <span class="label">展业资格证</span>
+                    <div class="fileName">
+                      <span class="file-name">{{ imageChangeName('qualification') }}</span>
+                      <el-icon class="file-icon" @click="imageView('qualification')"><View /></el-icon>
+                    </div>
+                  </div>
+                </template>
+              </el-descriptions-item>
+            </el-descriptions>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+    <el-dialog
+      v-model="bankCardDialogShow"
+      :title="bankTitle"
+      width="500"
+    >
+      <addCard @closeDialog="closeAddBankCard" :userInfo="bankCardInfo"></addCard>
+    </el-dialog>
+    <el-dialog
+      v-model="dialogShow"
+      title="编辑"
+      width="1000"
+    >
+      <addOperation ref="AddOperationRef" @closeDialog="closeAddOperation"></addOperation>
+    </el-dialog>
+    <el-dialog
+      v-model="allocationShow"
+      title="分配管理人"
+      width="800"
+    >
+      <allocation ref="AllocationRef" @closeDialog="closeAllocation"></allocation>
+    </el-dialog>
+    <el-dialog
+      v-model="imageShow"
+      title="预览"
+      width="500"
+    >
+      <div class="image-box">
+        <img class="image-view" :src="imageUrl" />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {nextTick, ref} from 'vue'
+import pinyin from "js-pinyin";
+import { ElMessage, ElMessageBox } from 'element-plus'
+import Allocation from "@/views/operationManagement/modules/allocation.vue";
+import { useRoute, useRouter } from 'vue-router'
+import api from '@/api'
+import {OperationIsEnable} from "@/api/modules/operation.ts";
+import router from "@/router";
+
+let AddOperationRef = ref(null)
+const AllocationRef = ref(null)
+
+let myRouter = useRouter()
+const myRoute = useRoute()
+
+// 更多
+const handleCommand = (e) => {
+  switch (e) {
+    case '删除':
+      ElMessageBox({
+        title: '删除业务员',
+        message: '确定要删除该业务员吗?',
+        type: 'warning',
+        showCancelButton: true,
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+      }).then(( action ) => {
+        if(action === 'confirm') {
+          let ids = [myRoute.query.id]
+          operationDel(ids)
+        }
+      }).catch(( action ) => {
+
+      })
+      break;
+    case '禁用':
+      ElMessageBox({
+        title: '禁用业务员',
+        message: '确定要禁用该业务员吗?',
+        type: 'warning',
+        showCancelButton: true,
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+      }).then(( action ) => {
+        if(action === 'confirm') {
+          let data = {
+            ids: [myRoute.query.ids],
+            isEnable: 1,
+            getAll: 0
+          }
+          operationIsEnable(data)
+        }
+      }).catch(( action ) => {
+
+      })
+      break;
+    case '启用':
+      ElMessageBox({
+        title: '启用业务员',
+        message: '确定要启用该业务员吗?',
+        type: 'warning',
+        showCancelButton: true,
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+      }).then(( action ) => {
+        if(action === 'confirm'){
+          let data = {
+            ids: [myRoute.query.ids],
+            isEnable: 0,
+            getAll: 0
+          }
+          operationIsEnable(data)
+        }
+      }).catch(( action ) => {
+
+      })
+      break;
+    case '分配管理人':
+      allocationShow.value = true
+      nextTick(() => {
+        AllocationRef.value.initCheckedKeys(dataDetail.value.deptId, 'cur', [dataDetail.value.id], dataDetail.value.leaderId)
+      })
+      break;
+  }
+}
+// 分配管理人
+let allocationShow = ref(false)
+const closeAllocation = (type: boolean) => {
+  allocationShow.value = type
+}
+//状态匹配
+const statusMap = (value: any) => {
+  const map = {
+    "0": '未认证',
+    "1": '认证中',
+    "2": '认证失败',
+    "3": '待入职',
+    "4": '入司审核中',
+    "5": '入司审核失败',
+    "6": '已入职',
+    "7": '离职待审核',
+    "8": '离职',
+  }
+  return map[value]
+}
+//人员类型匹配
+const typeAttrMap=(value)=>{
+  const map = {
+    "1": '前线人员',
+    "2": '后线人员',
+    "3": '合伙人',
+    "4": '工作是管理员',
+    "5": '团队',
+    "6": '个代',
+    "7": '电销',
+    "8": '渠道',
+  }
+  return map[value]
+}
+// 合伙人等级匹配
+const gradeMap = (value: any) => {
+  if(value == null) {
+    return '未知'
+  }else{
+    return value
+        .map((gradeId: any) => userGradeList.value.find((item: any) => item.grade == gradeId)?.gradeName || gradeId)
+        .join(',') || '未知';
+  }
+}
+
+// 银行卡列表数据
+// let tableData = ref([])
+
+// Tabs切换
+let activeName = ref('msg')
+
+// 银行卡信息
+let bankCardInfo = ref({})
+let bankTitle = ref('添加银行卡')
+// 添加银行卡弹框
+let bankCardDialogShow = ref(false)
+// 添加银行卡
+const addBankCard = () => {
+  bankTitle.value = '添加银行卡'
+  bankCardDialogShow.value = true
+  bankCardInfo.value = {
+    userJzgInfoId: dataDetail.value.id,
+    name: dataDetail.value.name,
+    isRead: false
+  }
+}
+// 编辑银行卡
+const editBankCard = (row) => {
+  bankTitle.value = '查看银行卡'
+  bankCardDialogShow.value = true
+  bankCardInfo.value = {
+    userJzgInfoId: dataDetail.value.id,
+    name: dataDetail.value.name,
+    bankName: row.bankName,
+    bankCardNumber: row.bankCardNumber,
+    bankAddress: row.bankAddress,
+    attachment: row.cardFile,
+    imageUrl: row.cardFile,
+    isRead: true
+  }
+}
+// 关闭添加银行卡弹框
+const closeAddBankCard = (type: string) => {
+  if(type == '确定') {
+    initDetail()
+  }
+  bankCardDialogShow.value = false
+}
+
+// 删除
+const operationDel = (id: string[]) => {
+  api.operationApi.operationDelete({
+    ids: id,
+    getAll: 0
+  }).then(res => {
+    if(res?.code == 200) {
+      ElMessage({
+        message: res.msg,
+        type: 'success'
+      })
+      myRouter.push({
+        path: 'operationManagement/operation',
+      })
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+// 启用/禁用
+const operationIsEnable = (data: OperationIsEnable) => {
+  api.operationApi.operationIsEnable(data).then(res => {
+    if(res?.code == 200) {
+      ElMessage({
+        message: res.msg,
+        type: 'success'
+      })
+      initDetail()
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+
+// 审核通过
+const checkPass = () => {
+  api.operationApi.salesmanAuthSuccess({ userInfoId: dataDetail.value.id }).then(res => {
+    if(res.code == 200) {
+      ElMessage({
+        message: res.msg,
+        type: 'success',
+      })
+      initDetail()
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning',
+      })
+    }
+  })
+}
+// 审核不通过
+const checkNotPass = () => {
+  ElMessageBox({
+    title: '审核不通过',
+    showInput: true,
+    inputPlaceholder: '请输入原因',
+    inputValue: '',
+    showCancelButton: true,
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+  }).then(({ value, action } ) => {
+    if(action == 'confirm') {
+      api.operationApi.salesmanAuthFailed({
+        userInfoId: dataDetail.value.id,
+        approvalOpinion: value
+      }).then(res => {
+        if(res.code == 200) {
+          ElMessage({
+            message: res.msg,
+            type: 'success',
+          })
+          initDetail()
+        } else {
+          ElMessage({
+            message: res.msg,
+            type: 'warning',
+          })
+        }
+      })
+    }
+  }).catch(( action ) => {
+
+  })
+}
+
+// 编辑/修改
+let dialogShow = ref(false)
+const editDetail = () => {
+  dialogShow.value = true
+  nextTick(() => {
+    AddOperationRef.value.initEditData(dataDetail.value.userId, dataDetail.value.id)
+  })
+}
+const closeAddOperation = (text: string) => {
+  if(text == '确定') {
+    initDetail()
+  }
+  dialogShow.value = false
+}
+
+// 附件转换
+const imageChangeName = (type) => {
+  if(dataDetail.value&&dataDetail.value.fileList.length>0) {
+    let obj = dataDetail.value.fileList.find(item => item.fileType === type)
+    return obj?.fileName
+  }
+}
+const imageChangeUrl = (type) => {
+  if(dataDetail.value.fileList.length>0) {
+    let obj = dataDetail.value.fileList.find(item => item.fileType == type)
+    return obj?.fileUrl
+  }
+}
+
+// 预览
+let imageUrl = ref('')
+let imageShow = ref(false)
+const imageView = (type) => {
+  imageUrl.value = imageChangeUrl(type)
+  imageShow.value = true
+}
+
+// 详情
+let dataDetail = ref(null)
+const initDetail = () => {
+  let id = myRoute.query?.userId
+  api.operationApi.operationDetail(id).then(res => {
+    if(res?.code == 200) {
+      dataDetail.value = res.data
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+
+// 初始化银行数据
+let bankOption = ref([])
+const initBankCard = () => {
+  api.commonApi.personInfo('bank_info').then(res => {
+    if(res.code == 200) {
+      bankOption.value = res.data
+    } else {
+      ElMessage({
+        message: res.msg,
+        type: 'warning'
+      })
+    }
+  })
+}
+// 转换
+const bankCardChange = (list, code) => {
+  if(code&&list.length>0) {
+    let obj = list.find(item => item.id == code)
+    return obj.label
+  }
+}
+
+// 名字转换首字母
+const initName = (name) => {
+  return name?pinyin.getFullChars(name).substring(0, 1):''
+}
+
+onMounted(() => {
+  initDetail()
+  initBankCard()
+  getGradeOptions()
+})
+// 获取人员等级列表
+let userGradeList = ref()
+const getGradeOptions = () => {
+  api.partnerApi.queryGradeName().then((res: any) => {
+    if (res.code === 200) {
+      userGradeList.value = res.data;
+    }
+  })
+}
+</script>
+
+<style scoped lang="scss">
+.detail{
+  margin: 0 10px;
+  height: calc(100vh - 120px);
+  background-color: white;
+  overflow-y: auto;
+  .state{
+    border: 1px solid #FF4545;
+    border-radius: 10px;
+    padding: 10px 20px;
+    background: #FFF4F4;
+    display: flex;
+    margin: 5px 0;
+    font-weight: 400;
+    color: #333333;
+    h3{
+      font-size: 16px;
+      margin: 0 0 10px;
+      color: rgba(0,0,0,.64);
+    }
+    p{
+      font-size: 14px;
+      margin: 10px 0;
+    }
+  }
+  .info{
+    background: white;
+    padding: 24px;
+    margin: 10px 0;
+    border-radius: 10px;
+    :deep(.el-descriptions__title) {
+      width: 100%;
+    }
+    :deep(.el-tabs__nav-wrap) {
+      padding: 0 25px;
+    }
+    :deep(.el-tabs__item) {
+      font-size: 18px;
+    }
+    .firstName{
+      width: 30px;
+      height: 30px;
+      text-align: center;
+      line-height: 30px;
+      border-radius: 15px;
+      background: #409EFF;
+      color: white;
+      font-size: 18px;
+      margin-right: 10px;
+    }
+    .allName{
+      font-size: 14px;
+    }
+  }
+  .message{
+    background: white;
+    :deep(.el-tabs__nav-scroll) {
+      padding: 24px 0 0 24px;
+    }
+    .other{
+      .fileItem{
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        margin: 10px 0;
+        .label{
+          width: 200px;
+        }
+        .fileName{
+          width: calc(100% - 500px);
+          line-height: 30px;
+          display: flex;
+          align-items: center;
+          padding: 0 20px;
+          &:hover{
+            background: #ccc;
+          }
+          .file-name{
+            width: 200px;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            margin-right: 20px;
+          }
+          .file-icon{
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+            height: 30px;
+            cursor: pointer;
+            &:hover{
+              color: #00a0f4;
+            }
+          }
+        }
+      }
+      .cardImage{
+        display: block;
+        width: 80px;
+        height: 80px;
+        border-radius: 5px;
+      }
+      :deep(.el-descriptions__title) {
+        padding-left: 20px;
+        font-size: 16px;
+      }
+    }
+  }
+  .image-box{
+    display: flex;
+    align-content: center;
+    justify-content: center;
+    .image-view{
+      width: 300px;
+      height: 200px;
+    }
+  }
+  :deep(.el-table th.el-table__cell) {
+    background-color: #F7F7F9;
+  }
+}
+</style>

+ 176 - 0
src/views/partnerManagement/purchaseHistory.vue

@@ -0,0 +1,176 @@
+<!-- 模板区域 -->
+<template>
+  <div>
+    <PageMain class="vh100 flex-1 overflow-hidden flex flex-col">
+      <SearchForm :fields="fields" :formInline="formInline" :onSearch="findpage" :onReset="resetForm" />
+      <div class="flex-1 overflow-auto">
+        <ComplexTable :tableData="tableData" :columns="columns" :showIndex="false" :columnwidth="250"
+          :showOperation="false" :showSelect="false" :pageInfo="pageInfo" @getList="getList">
+          <template #customSlot="{ bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'apperId'">
+              <el-button link type="primary" @click="purchaseVoucher(scope.row.apperId)">查看凭证</el-button>
+            </template>
+          </template>
+          <template v-slot:search="scope">
+            {{ scope.slotData.label }}
+          </template>
+        </ComplexTable>
+      </div>
+    </PageMain>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onBeforeMount } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+
+import api from '@/api'
+
+// 页面加载时获取机构列表
+onBeforeMount(() => {
+  getGradeOptions();
+  findpage();
+});
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+// 机构树相关变量
+const tableData = ref([
+  {
+    "id": "2008711122119659522",
+    "name": "杨密",
+    "mobile": "15513920005",
+    "userId": "99140602006",
+    "deptId": null,
+    "deptName": "朔州朔城区营业部",
+    "grade": "3",
+    "gradeAfter": "4",
+    "lockCommission": 0,
+    "purchasingTime": "2026-01-07 09:23:46",
+    "apperId": "2008711122077716482",
+    "pageNum": 1,
+    "pageSize": 10,
+    "startTime": null
+  }
+]);//表格数据
+const showViewer = ref(false);//是否显示查看凭证弹窗
+const formInline = reactive({
+  name: "",//姓名
+  mobile: "",//手机号
+  userId: "",//工号
+  signingTime: [],
+})
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 20,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+// 获取人员等级列表
+const userGradeList = ref()
+const getGradeOptions = () => {
+  api.partnerApi.queryGradeName().then((res: any) => {
+    if (res.code === 200) {
+      userGradeList.value = res.data;
+    }
+  })
+}
+//表格字段数据
+const fields = ref([
+  { label: "姓名", model: "name", type: "input", placeholder: "请输入姓名" },
+  {
+    label: "手机号", model: "mobile", type: "input", placeholder: "请输入手机号"
+  },
+  {
+    label: "工号", model: "userId", type: "input", placeholder: "请输入工号"
+  },
+  {
+    label: "购买时间", model: "signingTime", type: "date", dateType: "daterange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD", valueFormat: "YYYY-MM-DD",
+  },
+]);
+const columns = [
+  { prop: "name", label: "姓名", },
+  { prop: "mobile", label: "手机号", width: '200' },
+  { prop: "userId", label: "工号", width: '200' },
+  { prop: "deptName", label: "所属机构", width: '200' },
+  {
+    prop: "grade", label: "降级前", width: '200',
+    formatter: (row: any) => {
+      return userGradeList.value?.find((item: any) => item.grade === row.grade)?.gradeName || '未知等级';
+    }
+  },
+  {
+    prop: "gradeAfter", label: "降级后", width: '200',
+    formatter: (row: any) => {
+      return userGradeList.value?.find((item: any) => item.grade === row.gradeAfter)?.gradeName || '未知等级';
+    }
+  },
+  { prop: "lockCommission", label: "锁定佣金", width: '200' },
+  { prop: "purchasingTime", label: "购买时间", width: '200' },
+  { prop: "apperId", label: "购买凭证", width: '200', component: "customSlot" },
+];
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  findpage();
+
+};
+const resetForm = () => {
+  findpage();
+}
+//数据查询
+function findpage() {
+  let query = { ...formInline }
+  api.partnerApi.kickbackChangeQueryPage({ pages: pageInfo.value.pageNum, size: pageInfo.value.pageSize, ...query }).then((res: any) => {
+    if (res.code == '200') {
+      // tableData.value = res.data.records;
+      pageInfo.value.pageNum = res.data.current;
+      pageInfo.value.pageSize = res.data.size;
+      pageInfo.value.total = res.data.total;
+    } else {
+    }
+  });
+}
+const purchaseVoucher = (id: any) => {
+  api.partnerApi.purchaseviewVouchers(id).then((res: any) => {
+    if (res.code == '200') {
+      ElMessage({
+        type: 'success',
+        message: res.msg,
+      });
+      showViewer.value = true;
+    } else {
+      ElMessage({
+        type: 'error',
+        message: res.msg,
+      });
+    }
+  });
+}
+</script>
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+:deep(.el-dropdown-link) {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+}
+</style>

+ 399 - 0
src/views/partnerManagement/upgradeDowngradeRecord.vue

@@ -0,0 +1,399 @@
+<!-- 模板区域 -->
+<template>
+  <div>
+    <PageMain class="vh100 flex-1 overflow-hidden flex flex-col">
+      <el-tabs v-model="formInline.auditStatus" @tab-click="handleClick">
+        <el-tab-pane :label="`待审核 (${pendingReview})`" name="0"></el-tab-pane>
+        <el-tab-pane :label="`审核通过(${isApproved})`" name="1"></el-tab-pane>
+        <el-tab-pane :label="`审核不通过(${isNotApproved})`" name="2"></el-tab-pane>
+      </el-tabs>
+      <SearchForm :fields="fields" :formInline="formInline" :onSearch="findpage" :onReset="resetForm" />
+      <div class="flex-1 overflow-auto">
+        <ComplexTable :tableData="tableData" :columns="columns" :showIndex="false" :columnwidth="250"
+          :showOperation="formInline.auditStatus == '0' ? true : false" :showSelect="false" :pageInfo="pageInfo"
+          @getList="getList">
+          <!-- 自定义操作插槽 -->
+          <template v-slot:operation="scope">
+            <el-button v-if="scope.operationData.type == '0'" type="primary" link
+              @click="isOperationPassed(scope.operationData)">通过</el-button>
+            <el-button v-if="scope.operationData.type == '0'" type="primary" link
+              @click="denyOperation(scope.operationData)">拒绝</el-button>
+            <el-button v-if="scope.operationData.type == '1'" type="primary" link
+              @click="unlockLevel(scope.operationData)">解锁等级</el-button>
+          </template>
+          <!-- 自定义插槽 -->
+          <template #customSlot="{ bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'conditions'">
+              <el-popover placement="bottom" :width="250" trigger="click">
+                <template #default>
+                  <div v-html="scope.row.conditions"></div>
+                </template>
+                <template #reference>
+                  <el-button link type="primary">查看规则</el-button>
+                </template>
+              </el-popover>
+            </template>
+            <template v-if="column.prop == 'rules'">
+              <el-popover placement="bottom" :width="250" trigger="click">
+                <template #default>
+                  <div v-html="scope.row.rules"></div>
+                </template>
+                <template #reference>
+                  <el-button link type="primary">查看规则</el-button>
+                </template>
+              </el-popover>
+            </template>
+          </template>
+          <!-- 自定义表头插槽 -->
+          <template v-slot:search="scope">
+            {{ scope.slotData.label }}
+          </template>
+        </ComplexTable>
+
+      </div>
+    </PageMain>
+    <el-dialog v-model="upgradeReviewVisible" title="升级审核" width="400">
+      <el-form :model="upgradeReviewInfo" label-width="180px" label-position="top">
+        <el-form-item label="升级前">
+          <el-input disabled v-model="upgradeReviewInfo.originalLevel" />
+        </el-form-item>
+        <el-form-item label="升级后">
+          <el-input disabled v-model="upgradeReviewInfo.afterChange" />
+        </el-form-item>
+        <el-form-item :label="`升级后${upgradeReviewInfo.originalLevel}佣金比例`" v-if="auditCommissionshow">
+          <el-input v-model="upgradeReviewInfo.auditCommission">
+            <template #append>%</template>
+          </el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="upgradeReviewVisible = false">取消</el-button>
+          <el-button type="primary" @click="upgradeReviewsubmit">
+            审核通过
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <el-dialog v-model="OperationVisible" title="驳回原因" width="400">
+      <el-input type="textarea" :rows="3" placeholder="请输入内容" v-model="rejectReason" maxlength="200" show-word-limit>
+      </el-input>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="OperationVisible = false">取消</el-button>
+          <el-button type="primary" @click="OperationVisiblesubmit">
+            确定
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <el-dialog v-model="unlockLevelVisible" title="解锁等级" width="500">
+      <el-form :model="unlockLevelInfo" label-width="180px" label-position="top">
+        <el-form-item label="支付金额">
+          <el-input v-model="unlockLevelInfo.paymentAmount">
+            <template #append>%</template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="收款凭证">
+          <el-upload v-model:file-list="fileList" :limit="1" :auto-upload="false" @change="handleChange"
+            list-type="picture-card">
+            <el-icon>
+              <Plus />
+            </el-icon>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="unlockLevelVisible = false">取消</el-button>
+          <el-button type="primary" @click="confirmUnlock">
+            确定解锁
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<!-- 行为区域 -->
+<script lang='ts' setup>
+import { ref, reactive, onBeforeMount } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import type { UploadUserFile } from 'element-plus'
+import api from '@/api'
+// 页面加载时获取机构列表
+onBeforeMount(() => {
+  getGradeOptions();
+  findpage();
+});
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+// 机构树相关变量
+const id = ref("");//选中的id
+const pendingReview = ref(0);//待审核条数
+const isApproved = ref(0);//已审核条数
+const isNotApproved = ref(0);//审核不通过条数
+const upgradeReviewVisible = ref(false);//升级审核弹窗是否显示
+const OperationVisible = ref(false);//拒绝操作弹窗是否显示
+const auditCommissionshow = ref(true);//是否显示佣金比例
+const unlockLevelVisible = ref(false);//解锁等级弹窗是否显示
+const upgradeType = ref("");//升级类型
+const rejectReason = ref("");//拒绝原因
+const fileList = ref<UploadUserFile[]>([
+
+])
+
+const upgradeReviewInfo = reactive({
+  originalLevel: "",//原等级
+  afterChange: "",//变更后等级
+  auditCommission: "",//比例
+});//升级审核表单
+const unlockLevelInfo = reactive({
+  paymentAmount: 0,//支付金额
+  fileId: '',//图片id
+  recordId: "",//数据id
+});
+const tableData = ref([
+]);//表格数据
+const formInline = reactive({
+  name: "",//姓名
+  mobile: "",//手机号
+  userId: "",//工号
+  type: "",//类型
+  applyTimes: [],//申请时间
+  auditStatus: '0',
+})
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 20,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const typeOptions = ref([
+  {
+    label: '全部',
+    value: ' '
+  },
+  {
+    label: '升级',
+    value: '0'
+  }, {
+    label: '降级',
+    value: '1'
+  },
+])
+//表格字段数据
+const fields = ref([
+  { label: "姓名", model: "name", type: "input", placeholder: "请输入姓名" },
+  {
+    label: "手机号", model: "mobile", type: "input", placeholder: "请输入手机号"
+  },
+  {
+    label: "工号", model: "userId", type: "input", placeholder: "请输入工号"
+  },
+  {
+    label: "类型", model: "type", type: "select", placeholder: "选择类型", options: typeOptions.value
+  },
+  {
+    label: "申请时间", model: "applyTimes", type: "date", dateType: "daterange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD", valueFormat: "YYYY-MM-DD",
+  },
+]);
+const columns = [
+  { prop: "name", label: "姓名", },
+  { prop: "mobile", label: "手机号", width: '200' },
+  { prop: "userId", label: "工号", width: '200' },
+  { prop: "deptName", label: "所属机构", width: '200' },
+  {
+    prop: "type", label: "类型", width: '200',
+    formatter: (row: any) => {
+      if (row.type === '0') {
+        return '升级';
+      } else if (row.type === '1') {
+        return '降级';
+      } else {
+        return '未知类型';
+      }
+    }
+  },
+  {
+    prop: "originalLevel", label: "原等级", width: '200',
+    formatter: (row: any) => {
+      return userGradeList.value?.find((item: any) => item.grade == row.originalLevel)?.gradeName || '未知等级';
+    }
+  },
+  {
+    prop: "afterChange", label: "变更后等级", width: '200',
+    formatter: (row: any) => {
+      return userGradeList.value?.find((item: any) => item.grade == row.afterChange)?.gradeName || '未知等级';
+    }
+  },
+  {
+    prop: "conditions", label: "升级条件", width: '200', component: "customSlot",
+  },
+  { prop: "rules", label: "考核规则", width: '200', component: "customSlot", },
+  { prop: "rejectReason", label: "驳回原因", width: '200' },
+  { prop: "createTime", label: "申请时间", width: '200' },
+];
+// 通过
+const isOperationPassed = (item: any) => {
+  console.log(item)
+  if (item.afterChange == item.originalLevel) {
+    auditCommissionshow.value = false;
+  }
+  id.value = item.id;
+  upgradeType.value = item.upgradeType;
+  upgradeReviewVisible.value = true;
+  upgradeReviewInfo.originalLevel = userGradeList.value.find(val => val.grade == item.originalLevel).gradeName;
+  upgradeReviewInfo.afterChange = userGradeList.value.find(val => val.grade == item.afterChange).gradeName;
+}
+// 拒绝操作
+const denyOperation = (item: any) => {
+  OperationVisible.value = true;
+  id.value = item.id;
+}
+// 解锁等级
+const unlockLevel = (item: any) => {
+  api.partnerApi.unlockLevels(item.originalLevel).then((res: any) => {
+    if (res.code == '200') {
+      unlockLevelInfo.recordId = item.id;
+      // 使用JavaScript原生方法计算
+      if (item.frozenAmount) {
+        // 先将数值转换为字符串处理,避免浮点精度问题
+        const frozenAmount = Number(item.frozenAmount);
+        const rate = Number(res.data);
+        // 计算并保留适当的小数位数
+        unlockLevelInfo.paymentAmount = Number((frozenAmount * rate / 100).toFixed(2));
+      } else {
+        unlockLevelInfo.paymentAmount = 0;
+      }
+      unlockLevelVisible.value = true;
+    } else {
+      ElMessage.error(res.msg)
+    }
+  });
+}
+// 升级审核提交
+const upgradeReviewsubmit = () => {
+  api.partnerApi[upgradeType.value == '1' ? 'liftingRecorddowngradeAudit' : 'liftingRecordaudit']({
+    id: id.value,
+    auditStatus: "1",
+    auditCommission: upgradeReviewInfo.auditCommission,
+  }).then((res: any) => {
+    if (res.code == '200') {
+      ElMessage.success(res.msg)
+      upgradeReviewVisible.value = false;
+      findpage();
+    } else {
+      ElMessage.error(res.msg)
+    }
+  });
+}
+const OperationVisiblesubmit = () => {
+  api.partnerApi[upgradeType.value == '1' ? 'liftingRecorddowngradeAudit' : 'liftingRecordaudit']({
+    id: id.value,
+    auditStatus: "2",
+    rejectReason: rejectReason.value,
+  }).then((res: any) => {
+    if (res.code == '200') {
+      ElMessage.success(res.msg)
+      OperationVisible.value = false;
+      findpage();
+    } else {
+      ElMessage.error(res.msg)
+    }
+  });
+}
+// 解锁等级
+const confirmUnlock = () => {
+  api.partnerApi.confirmUnlocking(unlockLevelInfo).then((res: any) => {
+    if (res.code == '200') {
+      ElMessage({
+        type: 'success',
+        message: res.msg,
+      });
+      unlockLevelVisible.value = false;
+      findpage();
+    } else {
+      ElMessage({
+        type: 'error',
+        message: res.msg,
+      });
+    }
+  });
+}
+// 处理文件上传
+const handleChange = (file: any, FileList: any) => {
+  let files = file.raw
+  const params = new FormData(); // 声明formData数据类型
+  params.append("file", files);
+  api.commonApi.fileUpload(params).then((res: any) => {
+    if (res.code == '200') {
+      unlockLevelInfo.fileId = res.data.id;
+    } else {
+      ElMessage.error(res.msg)
+    }
+  });
+};
+// 处理点击事件
+const handleClick = (tab: any) => {
+  formInline.auditStatus = tab.props.name;
+  console.log(formInline.auditStatus);
+  findpage();
+};
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  findpage();
+
+};
+const resetForm = () => {
+  findpage();
+}
+//数据查询
+function findpage() {
+  api.partnerApi.liftingRecordQueryPage({ pages: pageInfo.value.pageNum, size: pageInfo.value.pageSize, ...formInline }).then((res: any) => {
+    if (res.code == '200') {
+      tableData.value = res.data.records;
+      pageInfo.value.pageNum = res.data.current;
+      pageInfo.value.pageSize = res.data.size;
+      pageInfo.value.total = res.data.total;
+    } else {
+    }
+  });
+}
+// 获取人员等级列表
+const userGradeList = ref()
+const getGradeOptions = () => {
+  api.partnerApi.queryGradeName().then((res: any) => {
+    if (res.code === 200) {
+      userGradeList.value = res.data;
+    }
+  })
+}
+
+</script>
+<!-- 样式区域 -->
+<style lang='scss' scoped>
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+:deep(.el-dropdown-link) {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+}
+</style>

+ 3 - 1
src/views/quoteConfig/agreement/agreementIndex.vue

@@ -164,6 +164,7 @@ const fields = ref([
   },
   {
     label: "生效时间", model: "value1", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       console.log(value)
       formInline.takeStartDate = value[0];
@@ -172,6 +173,7 @@ const fields = ref([
   },
   {
     label: "失效时间", model: "value2", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       formInline.loseStartDate = value[0];
       formInline.loseEndDate = value[1];
@@ -341,7 +343,7 @@ function getUncheckedIds(data: any[]): string[] {
   return ids;
 }
 //编辑跳转
-const agreementEdit = (id) => {
+const agreementEdit = (id:any) => {
     router.push({
         name: 'AgreementAdd',
         query: {

+ 2 - 0
src/views/quoteConfig/costManagement.vue

@@ -177,6 +177,7 @@ const fields = ref([
   },
   {
     label: "生效时间", model: "effectiveTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       console.log(value)
       formInline.effectiveTime = value;
@@ -184,6 +185,7 @@ const fields = ref([
   },
   {
     label: "失效时间", model: "failureTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       formInline.failureTime = value;
     }

+ 2 - 0
src/views/representative/externalCostApproval.vue

@@ -115,6 +115,7 @@ const fields = ref([
   },
   {
     label: "生效时间", model: "effectiveTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       console.log(value)
       formInline.effectiveTime = value;
@@ -122,6 +123,7 @@ const fields = ref([
   },
   {
     label: "失效时间", model: "failureTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       formInline.failureTime = value;
     }

+ 66 - 135
src/views/representative/member.vue

@@ -1,70 +1,41 @@
 <template>
   <div class="institution">
     <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
-      <el-tab-pane :label="'待审核'+'('+countObj?.noAuditCount +')'" name="hold">
+      <el-tab-pane :label="'待审核' + '(' + countObj?.noAuditCount + ')'" name="hold">
         <div class="institution-main">
           <el-form label-position="left" label-width="auto">
             <el-row :gutter="24">
               <el-col :span="6">
                 <el-form-item label="成员信息">
-                  <el-input
-                    v-model="formAccessibility.firstName"
-                    placeholder="输入成员信息查找"
-                    :prefix-icon="Search"
-                  />
+                  <el-input v-model="formAccessibility.firstName" placeholder="输入成员信息查找" :prefix-icon="Search" />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
-                  <el-form-item label="归属机构">
-                      <el-cascader
-                              clearable
-                              style="width: 100%"
-                              v-model="info.deptId"
-                              :options="institutionList"
-                              :props="tableProps"
-
-                      />
-                  </el-form-item>
+                <el-form-item label="归属机构">
+                  <el-cascader clearable style="width: 100%" v-model="info.deptId" :options="institutionList"
+                    :props="tableProps" />
+                </el-form-item>
               </el-col>
               <el-col :span="6">
-                  <el-form-item label="状态">
-                      <el-select
-                        clearable
-                        style="width: 100%"
-                        v-model="info.status"
-                      >
-                          <el-option
-                                  v-for="item in statusList"
-                                  :key="item.value"
-                                  :label="item.label"
-                                  :value="item.value"
-                          />
-                      </el-select>
-                  </el-form-item>
+                <el-form-item label="状态">
+                  <el-select clearable style="width: 100%" v-model="info.status">
+                    <el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </el-form-item>
               </el-col>
 
               <el-col :span="4">
                 <el-form-item label="">
                   <el-button type="primary" @click="salesmanAuth">查询</el-button>
-                  <el-button type="primary" plain @click="reset"
-                    >重置</el-button
-                  >
+                  <el-button type="primary" plain @click="reset">重置</el-button>
                 </el-form-item>
               </el-col>
             </el-row>
           </el-form>
 
-          <Table
-            :tableData="tableData"
-            :columns="columns"
-            :showIndex="false"
-            :showSelect="true"
-            :pageInfo="pageInfo"
-            @getList="getList"
-            :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
-            @select-all-change="selectAllChange"
-            @select-change="selectChange"
-          >
+          <Table :tableData="tableData" :columns="columns" :showIndex="false" :showSelect="true" :pageInfo="pageInfo"
+            @getList="getList" :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
+            @select-all-change="selectAllChange" @select-change="selectChange">
             <template v-slot:table-title-btn>
               <div>
                 <!-- <el-button type="primary" @click="add(ruleFormRef)">
@@ -86,25 +57,13 @@
               </div>
             </template>
             <template v-slot:operation="scope">
-              <el-button
-                type="primary"
-                link
-                @click="toExamine(scope.operationData.row, 'success')"
-              >
+              <el-button type="primary" link @click="toExamine(scope.operationData.row, 'success')">
                 审核通过
               </el-button>
-              <el-button
-                type="primary"
-                link
-                @click="toExamine(scope.operationData.row, 'error')"
-              >
+              <el-button type="primary" link @click="toExamine(scope.operationData.row, 'error')">
                 审核不通过
               </el-button>
-              <el-button
-                type="primary"
-                link
-                @click="editor(scope.operationData.row)"
-              >
+              <el-button type="primary" link @click="editor(scope.operationData.row)">
                 详情
               </el-button>
             </template>
@@ -114,70 +73,41 @@
           </Table>
         </div>
       </el-tab-pane>
-      <el-tab-pane :label="'审核不通过'+'('+countObj?.failAuditCount +')'" name="pass">
+      <el-tab-pane :label="'审核不通过' + '(' + countObj?.failAuditCount + ')'" name="pass">
         <div class="institution-main">
           <el-form label-position="left" label-width="auto">
             <el-row :gutter="24">
               <el-col :span="6">
                 <el-form-item label="成员信息">
-                  <el-input
-                    v-model="formAccessibility.firstName"
-                    placeholder="输入成员信息查找"
-                    :prefix-icon="Search"
-                  />
+                  <el-input v-model="formAccessibility.firstName" placeholder="输入成员信息查找" :prefix-icon="Search" />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
                 <el-form-item label="归属机构">
-                  <el-cascader
-                    clearable
-                    style="width: 100%"
-                    v-model="info.deptId"
-                    :options="institutionList"
-                    :props="tableProps"
-
-                  />
+                  <el-cascader clearable style="width: 100%" v-model="info.deptId" :options="institutionList"
+                    :props="tableProps" />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
-                  <el-form-item label="状态">
-                      <el-select
-                              clearable
-                              style="width: 100%"
-                              v-model="info.status"
-                      >
-                          <el-option
-                                  v-for="item in statusList"
-                                  :key="item.value"
-                                  :label="item.label"
-                                  :value="item.value"
-                          />
-                      </el-select>
-                  </el-form-item>
+                <el-form-item label="状态">
+                  <el-select clearable style="width: 100%" v-model="info.status">
+                    <el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </el-form-item>
               </el-col>
 
               <el-col :span="4">
                 <el-form-item label="">
                   <el-button type="primary" @click="salesmanAuth">查询</el-button>
-                  <el-button type="primary" plain @click="reset"
-                    >重置</el-button
-                  >
+                  <el-button type="primary" plain @click="reset">重置</el-button>
                 </el-form-item>
               </el-col>
             </el-row>
           </el-form>
 
-          <Table
-            :tableData="tableData"
-            :columns="columns"
-            :showIndex="false"
-            :showSelect="true"
-            :pageInfo="pageInfo"
-            @getList="getList"
-            :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
-            @select-all-change="selectAllChange"
-            @select-change="selectChange"
-          >
+          <Table :tableData="tableData" :columns="columns" :showIndex="false" :showSelect="true" :pageInfo="pageInfo"
+            @getList="getList" :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
+            @select-all-change="selectAllChange" @select-change="selectChange">
             <template v-slot:table-title-btn>
               <div>
                 <!-- <el-button type="primary" @click="add(ruleFormRef)">
@@ -199,11 +129,7 @@
               </div>
             </template>
             <template v-slot:operation="scope">
-              <el-button
-                type="primary"
-                link
-                @click="editor(scope.operationData.row)"
-              >
+              <el-button type="primary" link @click="editor(scope.operationData.row)">
                 详情
               </el-button>
             </template>
@@ -216,11 +142,7 @@
     </el-tabs>
 
     <el-dialog v-model="dialogVisible" title="审核不通过" width="500" draggable>
-      <el-input
-        type="textarea"
-        placeholder="请输入审核不通过原因"
-        v-model="textValue"
-      />
+      <el-input type="textarea" placeholder="请输入审核不通过原因" v-model="textValue" />
       <template #footer>
         <div class="dialog-footer">
           <el-button @click="cancel()">取 消</el-button>
@@ -307,10 +229,11 @@ const columns = [
     prop: "username",
     label: "角色",
   },
-  { prop: "status", label: "状态",
-      formatter: (row: any) => {
-          return () => h("div", {}, row.status == '4' ? "入司审核" : row.status == '7'? "离职审核" : '');
-      }
+  {
+    prop: "status", label: "状态",
+    formatter: (row: any) => {
+      return () => h("div", {}, row.status == '4' ? "入司审核" : row.status == '7' ? "离职审核" : '');
+    }
   },
   { prop: "createTime", label: "创建时间" },
   { prop: "createBy", label: "创建人" },
@@ -475,9 +398,9 @@ const salesmanAuth = () => {
 
 //成员列表
 
-const countObj=ref({
-  noAuditCount:'',
-  failAuditCount:"",
+const countObj = ref({
+  noAuditCount: '',
+  failAuditCount: "",
 })
 const institutionList = ref([]);
 const getAllMemberList = () => {
@@ -485,29 +408,29 @@ const getAllMemberList = () => {
     if (res.code === 200) institutionList.value = res.data;
   });
   api.representativeApi.getAuditCount({
-    typeAttr:'2'
-  }).then((res:any)=>{
+    typeAttr: '2'
+  }).then((res: any) => {
     // console.log(res)
-    if(res.code===200){
-      countObj.value=res.data
+    if (res.code === 200) {
+      countObj.value = res.data
     }
   })
   // pageInfo.pageSize=item.pageSize
 };
 
 let statusList = ref([
-    {
-        value: '0',
-        label: '全部'
-    },
-    {
-        value: '4',
-        label: '入司审核'
-    },
-    {
-        value: '7',
-        label: '离职审核'
-    },
+  {
+    value: '0',
+    label: '全部'
+  },
+  {
+    value: '4',
+    label: '入司审核'
+  },
+  {
+    value: '7',
+    label: '离职审核'
+  },
 ])
 
 const reset = (item: any) => {
@@ -528,10 +451,12 @@ onMounted(() => {
   display: flex;
   align-items: center;
   justify-content: space-between;
-  > div {
+
+  >div {
     display: flex;
   }
 }
+
 .institution {
   background: #fff;
   width: 100%;
@@ -539,11 +464,13 @@ onMounted(() => {
   // padding: 20px;
   box-sizing: border-box;
   display: flex;
+
   :deep(.demo-tabs) {
     width: 100%;
     padding: 20px;
     box-sizing: border-box;
   }
+
   // .institution-main {
   //   flex: 1;
   //   // width: 80%;
@@ -551,6 +478,7 @@ onMounted(() => {
   //   box-sizing: border-box;
   // }
 }
+
 :deep(.el-dropdown-link) {
   cursor: pointer;
   color: var(--el-color-primary);
@@ -558,6 +486,7 @@ onMounted(() => {
   align-items: center;
   margin-left: 15px;
 }
+
 .custom-tree-node {
   flex: 1;
   display: flex;
@@ -566,8 +495,10 @@ onMounted(() => {
   font-size: 14px;
   padding-right: 8px;
 }
+
 :deep(.el-message-box__container) {
   width: 100% !important;
+
   .el-message-box__message {
     width: 100% !important;
   }

+ 2 - 0
src/views/representative/quoteApproval.vue

@@ -123,6 +123,7 @@ const fields = ref([
   },
   {
     label: "生效时间", model: "effectiveTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       console.log(value)
       formInline.effectiveTime = value;
@@ -130,6 +131,7 @@ const fields = ref([
   },
   {
     label: "失效时间", model: "failureTime", type: "date", dateType: "datetimerange", startplaceholder: "开始时间", endplaceholder: "结束时间",
+    format: "YYYY-MM-DD HH:mm:ss", valueFormat: "YYYY-MM-DD HH:mm:ss", timeFormat: "HH:mm:ss",
     onChange: (value: any) => {
       formInline.failureTime = value;
     }

+ 30 - 95
src/views/representative/salesman.vue

@@ -1,32 +1,19 @@
 <template>
   <div class="institution">
     <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
-      <el-tab-pane :label="'待审核'+'('+countObj?.noAuditCount +')'" name="hold">
+      <el-tab-pane :label="'待审核' + '(' + countObj?.noAuditCount + ')'" name="hold">
         <div class="institution-main">
           <el-form label-position="left" label-width="auto">
             <el-row :gutter="24">
               <el-col :span="6">
                 <el-form-item label="成员信息">
-                  <el-input
-                    v-model="formAccessibility.firstName"
-                    placeholder="输入成员信息查找"
-                    :prefix-icon="Search"
-                  />
+                  <el-input v-model="formAccessibility.firstName" placeholder="输入成员信息查找" :prefix-icon="Search" />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
                 <el-form-item label="归属机构">
-                  <el-select
-                    v-model="form.leaderId"
-                    placeholder="归属机构"
-                    clearable
-                  >
-                    <el-option
-                      v-for="item in memberList"
-                      :key="item.id"
-                      :label="item.name"
-                      :value="item.id"
-                    />
+                  <el-select v-model="form.leaderId" placeholder="归属机构" clearable>
+                    <el-option v-for="item in memberList" :key="item.id" :label="item.name" :value="item.id" />
                   </el-select>
                 </el-form-item>
               </el-col>
@@ -34,25 +21,15 @@
               <el-col :span="4">
                 <el-form-item label="">
                   <el-button type="primary">查询</el-button>
-                  <el-button type="primary" plain @click="reset"
-                    >重置</el-button
-                  >
+                  <el-button type="primary" plain @click="reset">重置</el-button>
                 </el-form-item>
               </el-col>
             </el-row>
           </el-form>
 
-          <Table
-            :tableData="tableData"
-            :columns="columns"
-            :showIndex="false"
-            :showSelect="true"
-            :pageInfo="pageInfo"
-            @getList="getList"
-            :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
-            @select-all-change="selectAllChange"
-            @select-change="selectChange"
-          >
+          <Table :tableData="tableData" :columns="columns" :showIndex="false" :showSelect="true" :pageInfo="pageInfo"
+            @getList="getList" :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
+            @select-all-change="selectAllChange" @select-change="selectChange">
             <template v-slot:table-title-btn>
               <div>
                 <!-- <el-button type="primary" @click="add(ruleFormRef)">
@@ -74,25 +51,13 @@
               </div>
             </template>
             <template v-slot:operation="scope">
-              <el-button
-                type="primary"
-                link
-                @click="toExamine(scope.operationData.row, 'success')"
-              >
+              <el-button type="primary" link @click="toExamine(scope.operationData.row, 'success')">
                 审核通过
               </el-button>
-              <el-button
-                type="primary"
-                link
-                @click="toExamine(scope.operationData.row, 'error')"
-              >
+              <el-button type="primary" link @click="toExamine(scope.operationData.row, 'error')">
                 审核不通过
               </el-button>
-              <el-button
-                type="primary"
-                link
-                @click="editor(scope.operationData.row)"
-              >
+              <el-button type="primary" link @click="editor(scope.operationData.row)">
                 详情
               </el-button>
             </template>
@@ -102,32 +67,19 @@
           </Table>
         </div>
       </el-tab-pane>
-      <el-tab-pane :label="'审核不通过'+'('+countObj?.failAuditCount +')'" name="pass">
+      <el-tab-pane :label="'审核不通过' + '(' + countObj?.failAuditCount + ')'" name="pass">
         <div class="institution-main">
           <el-form label-position="left" label-width="auto">
             <el-row :gutter="24">
               <el-col :span="6">
                 <el-form-item label="成员信息">
-                  <el-input
-                    v-model="formAccessibility.firstName"
-                    placeholder="输入成员信息查找"
-                    :prefix-icon="Search"
-                  />
+                  <el-input v-model="formAccessibility.firstName" placeholder="输入成员信息查找" :prefix-icon="Search" />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
                 <el-form-item label="归属机构">
-                  <el-select
-                    v-model="form.leaderId"
-                    placeholder="归属机构"
-                    clearable
-                  >
-                    <el-option
-                      v-for="item in memberList"
-                      :key="item.id"
-                      :label="item.name"
-                      :value="item.id"
-                    />
+                  <el-select v-model="form.leaderId" placeholder="归属机构" clearable>
+                    <el-option v-for="item in memberList" :key="item.id" :label="item.name" :value="item.id" />
                   </el-select>
                 </el-form-item>
               </el-col>
@@ -135,25 +87,15 @@
               <el-col :span="4">
                 <el-form-item label="">
                   <el-button type="primary">查询</el-button>
-                  <el-button type="primary" plain @click="reset"
-                    >重置</el-button
-                  >
+                  <el-button type="primary" plain @click="reset">重置</el-button>
                 </el-form-item>
               </el-col>
             </el-row>
           </el-form>
 
-          <Table
-            :tableData="tableData"
-            :columns="columns"
-            :showIndex="false"
-            :showSelect="true"
-            :pageInfo="pageInfo"
-            @getList="getList"
-            :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
-            @select-all-change="selectAllChange"
-            @select-change="selectChange"
-          >
+          <Table :tableData="tableData" :columns="columns" :showIndex="false" :showSelect="true" :pageInfo="pageInfo"
+            @getList="getList" :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
+            @select-all-change="selectAllChange" @select-change="selectChange">
             <template v-slot:table-title-btn>
               <div>
                 <!-- <el-button type="primary" @click="add(ruleFormRef)">
@@ -175,11 +117,7 @@
               </div>
             </template>
             <template v-slot:operation="scope">
-              <el-button
-                type="primary"
-                link
-                @click="editor(scope.operationData.row)"
-              >
+              <el-button type="primary" link @click="editor(scope.operationData.row)">
                 详情
               </el-button>
             </template>
@@ -192,11 +130,7 @@
     </el-tabs>
 
     <el-dialog v-model="dialogVisible" title="审核不通过" width="500" draggable>
-      <el-input
-        type="textarea"
-        placeholder="请输入审核不通过原因"
-        v-model="textValue"
-      />
+      <el-input type="textarea" placeholder="请输入审核不通过原因" v-model="textValue" />
       <template #footer>
         <div class="dialog-footer">
           <el-button @click="cancel()">取 消</el-button>
@@ -457,9 +391,9 @@ const salesmanAuth = () => {
 };
 
 //成员列表
-const countObj=ref({
-  noAuditCount:'',
-  failAuditCount:"",
+const countObj = ref({
+  noAuditCount: '',
+  failAuditCount: "",
 })
 const memberList = ref([]);
 const getAllMemberList = () => {
@@ -467,11 +401,11 @@ const getAllMemberList = () => {
     if (res.code === 200) memberList.value = res.data;
   });
   api.representativeApi.getAuditCount({
-    typeAttr:'1'
-  }).then((res:any)=>{
+    typeAttr: '1'
+  }).then((res: any) => {
     // console.log(res)
-    if(res.code===200){
-      countObj.value=res.data
+    if (res.code === 200) {
+      countObj.value = res.data
     }
   })
   // pageInfo.pageSize=item.pageSize
@@ -496,7 +430,7 @@ onMounted(() => {
   align-items: center;
   justify-content: space-between;
 
-  > div {
+  >div {
     display: flex;
   }
 }
@@ -514,6 +448,7 @@ onMounted(() => {
     width: 100%;
     padding: 20px;
   }
+
   // .institution-main {
   //   flex: 1;
   //   // width: 80%;